blob: 355600f84f7de9a7d7b98df14644fa673db26c44 [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
37#include <libxml/xmlschemas.h>
38#include <libxml/schemasInternals.h>
39#include <libxml/xmlschemastypes.h>
40#include <libxml/xmlautomata.h>
41#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000042#include <libxml/dict.h>
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000043#ifdef LIBXML_PATTERN_ENABLED
44#include <libxml/pattern.h>
45#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000046#ifdef LIBXML_READER_ENABLED
47#include <libxml/xmlreader.h>
48#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000049
Daniel Veillarda84c0b32003-06-02 16:58:46 +000050/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000051
Daniel Veillard82bbbd42003-05-11 20:16:09 +000052/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000053
Daniel Veillard82bbbd42003-05-11 20:16:09 +000054/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000055
Daniel Veillard118aed72002-09-24 14:13:13 +000056/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000057
Daniel Veillard4255d502002-04-16 15:50:10 +000058/* #define DEBUG_AUTOMATA 1 */
59
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000060#define DEBUG_ATTR_VALIDATION 0
Daniel Veillardc0826a72004-08-10 14:17:33 +000061
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000062/* #define DEBUG_IDC 1 */
63
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000064/* #define DEBUG_INCLUDES 1 */
65
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000066/* #define ENABLE_PARTICLE_RESTRICTION 1 */
67
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000068#define DUMP_CONTENT_MODEL
69
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000070#define XML_SCHEMA_SAX_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000071
72#ifdef LIBXML_READER_ENABLED
73/* #define XML_SCHEMA_READER_ENABLED */
74#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000075
Daniel Veillard4255d502002-04-16 15:50:10 +000076#define UNBOUNDED (1 << 30)
77#define TODO \
78 xmlGenericError(xmlGenericErrorContext, \
79 "Unimplemented block at %s:%d\n", \
80 __FILE__, __LINE__);
81
William M. Brack2f2a6632004-08-20 23:09:47 +000082#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000083
Daniel Veillard4255d502002-04-16 15:50:10 +000084/*
85 * The XML Schemas namespaces
86 */
87static const xmlChar *xmlSchemaNs = (const xmlChar *)
88 "http://www.w3.org/2001/XMLSchema";
89
90static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
91 "http://www.w3.org/2001/XMLSchema-instance";
92
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000093static const xmlChar *xmlNamespaceNs = (const xmlChar *)
94 "http://www.w3.org/2000/xmlns/";
95
Daniel Veillardc0826a72004-08-10 14:17:33 +000096static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000097 "element decl.";
Daniel Veillardc0826a72004-08-10 14:17:33 +000098static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000099 "attribute decl.";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000100static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000101 "attribute use";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000102static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +0000103 "complex type";
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000104static const xmlChar *xmlSchemaElemModelGrDef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000105 "model group";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000106#if 0
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000107static const xmlChar *xmlSchemaElemModelGrRef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000108 "model group ref.";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000109#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +0000110
Daniel Veillard4255d502002-04-16 15:50:10 +0000111#define IS_SCHEMA(node, type) \
112 ((node != NULL) && (node->ns != NULL) && \
113 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
114 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
115
Daniel Veillardc0826a72004-08-10 14:17:33 +0000116#define FREE_AND_NULL(str) \
117 if (str != NULL) { \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000118 xmlFree((xmlChar *) str); \
Daniel Veillardc0826a72004-08-10 14:17:33 +0000119 str = NULL; \
120 }
121
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000122#define IS_ANYTYPE(item) \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000123 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
124 (item->builtInType == XML_SCHEMAS_ANYTYPE))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000125
126#define IS_COMPLEX_TYPE(item) \
127 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
128 (item->builtInType == XML_SCHEMAS_ANYTYPE))
129
130#define IS_SIMPLE_TYPE(item) \
131 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
132 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000133 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000134
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000135#define IS_ANY_SIMPLE_TYPE(item) \
136 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000137 (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000138
139#define IS_NOT_TYPEFIXED(item) \
140 ((item->type != XML_SCHEMA_TYPE_BASIC) && \
141 ((item->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
142
143#define HAS_COMPLEX_CONTENT(item) \
144 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
145 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
146 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
147
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000148#define HAS_SIMPLE_CONTENT(item) \
149 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
150 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
151
152#define HAS_MIXED_CONTENT(item) (item->contentType == XML_SCHEMA_CONTENT_MIXED)
153
154#define IS_PARTICLE_EMPTIABLE(item) \
155 (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr) item->subtypes))
156
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000157#define GET_NODE(item) xmlSchemaGetComponentNode((xmlSchemaBasicItemPtr) item)
158
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000159#define GET_LIST_ITEM_TYPE(item) item->subtypes
160
161#define VARIETY_ATOMIC(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
162#define VARIETY_LIST(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
163#define VARIETY_UNION(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
164
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000165#define IS_MODEL_GROUP(item) \
166 ((item->type == XML_SCHEMA_TYPE_SEQUENCE) || \
167 (item->type == XML_SCHEMA_TYPE_CHOICE) || \
168 (item->type == XML_SCHEMA_TYPE_ALL))
169
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000170#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
171
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000172#define ELEM_TYPE(item) item->subtypes
173
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000174#define GET_PARTICLE(item) (xmlSchemaParticlePtr) item->subtypes;
175
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000176#define SUBST_GROUP_AFF(item) item->refDecl
177
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000178#if 0
179#define WXS_GET_NEXT(item) xmlSchemaGetNextComponent((xmlSchemaBasicItemPtr) item)
180#endif
181
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000182#define SUBSET_RESTRICTION 1<<0
183#define SUBSET_EXTENSION 1<<1
184#define SUBSET_SUBSTITUTION 1<<2
185#define SUBSET_LIST 1<<3
186#define SUBSET_UNION 1<<4
187
Daniel Veillard4255d502002-04-16 15:50:10 +0000188#define XML_SCHEMAS_PARSE_ERROR 1
189
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000190#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
191
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000192typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
193typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000194
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000195
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000196typedef struct _xmlSchemaItemList xmlSchemaAssemble;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000197typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000198
199typedef struct _xmlSchemaItemList xmlSchemaItemList;
200typedef xmlSchemaItemList *xmlSchemaItemListPtr;
201
202struct _xmlSchemaItemList {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000203 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000204 int nbItems; /* used for dynamic addition of schemata */
205 int sizeItems; /* used for dynamic addition of schemata */
206};
207
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000208typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
209typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
210struct _xmlSchemaAbstractCtxt {
211 int type;
212};
213
214#define XML_SCHEMA_CTXT_PARSER 1
215#define XML_SCHEMA_CTXT_VALIDATOR 2
216
Daniel Veillard4255d502002-04-16 15:50:10 +0000217struct _xmlSchemaParserCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000218 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000219 void *userData; /* user specific data block */
220 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
221 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000222 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000223 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000224 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000225
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000226 xmlSchemaPtr topschema; /* The main schema */
227 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
228
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000229 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000230 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000231 int counter;
232
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000233 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000234 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000235 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000236
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000237 const char *buffer;
238 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000239
Daniel Veillard4255d502002-04-16 15:50:10 +0000240 /*
241 * Used to build complex element content models
242 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000243 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000244 xmlAutomataStatePtr start;
245 xmlAutomataStatePtr end;
246 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000247
248 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000249 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000250 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
251 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000252 xmlSchemaAssemblePtr assemble;
253 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000254 xmlSchemaValidCtxtPtr vctxt;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000255 const xmlChar **localImports; /* list of locally imported namespaces */
256 int sizeLocalImports;
257 int nbLocalImports;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000258 xmlHashTablePtr substGroups;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +0000259 int isS4S;
Daniel Veillard4255d502002-04-16 15:50:10 +0000260};
261
Daniel Veillard4255d502002-04-16 15:50:10 +0000262#define XML_SCHEMAS_ATTR_UNKNOWN 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000263#define XML_SCHEMAS_ATTR_ASSESSED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000264#define XML_SCHEMAS_ATTR_PROHIBITED 3
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000265#define XML_SCHEMAS_ATTR_ERR_MISSING 4
Daniel Veillard3646d642004-06-02 19:19:14 +0000266#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000267#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
268#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000269#define XML_SCHEMAS_ATTR_DEFAULT 8
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +0000270#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000271#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
272#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
273#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
274#define XML_SCHEMAS_ATTR_WILD_SKIP 13
275#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
276#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
277#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
278#define XML_SCHEMAS_ATTR_META 17
Daniel Veillard4255d502002-04-16 15:50:10 +0000279
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000280/**
281 * xmlSchemaBasicItem:
282 *
283 * The abstract base type for schema components.
284 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000285typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
286typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
287struct _xmlSchemaBasicItem {
288 xmlSchemaTypeType type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000289};
290
291/**
292 * xmlSchemaAnnotItem:
293 *
294 * The abstract base type for annotated schema components.
295 * (Extends xmlSchemaBasicItem)
296 */
297typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
298typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
299struct _xmlSchemaAnnotItem {
300 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000301 xmlSchemaAnnotPtr annot;
302};
303
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000304/**
305 * xmlSchemaTreeItem:
306 *
307 * The abstract base type for tree-like structured schema components.
308 * (Extends xmlSchemaAnnotItem)
309 */
310typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
311typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
312struct _xmlSchemaTreeItem {
313 xmlSchemaTypeType type;
314 xmlSchemaAnnotPtr annot;
315 xmlSchemaTreeItemPtr next;
316 xmlSchemaTreeItemPtr children;
317};
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000318
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000319/**
320 * xmlSchemaQNameRef:
321 *
322 * A component reference item (not a schema component)
323 * (Extends xmlSchemaBasicItem)
324 */
325typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
326typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
327struct _xmlSchemaQNameRef {
328 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000329 xmlSchemaBasicItemPtr item;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000330 xmlSchemaTypeType itemType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000331 const xmlChar *name;
332 const xmlChar *targetNamespace;
333};
334
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000335/**
336 * xmlSchemaParticle:
337 *
338 * A particle component.
339 * (Extends xmlSchemaTreeItem)
340 */
341typedef struct _xmlSchemaParticle xmlSchemaParticle;
342typedef xmlSchemaParticle *xmlSchemaParticlePtr;
343struct _xmlSchemaParticle {
344 xmlSchemaTypeType type;
345 xmlSchemaAnnotPtr annot;
346 xmlSchemaTreeItemPtr next; /* next particle (OR "element decl" OR "wildcard") */
347 xmlSchemaTreeItemPtr children; /* the "term" ("model group" OR "group definition") */
348 int minOccurs;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000349 int maxOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000350 xmlNodePtr node;
351};
352
353/**
354 * xmlSchemaModelGroup:
355 *
356 * A model group component.
357 * (Extends xmlSchemaTreeItem)
358 */
359typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
360typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
361struct _xmlSchemaModelGroup {
362 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
363 xmlSchemaAnnotPtr annot;
364 xmlSchemaTreeItemPtr next; /* not used */
365 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
366 xmlNodePtr node;
367};
368
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000369#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000370/**
371 * xmlSchemaModelGroupDef:
372 *
373 * A model group definition component.
374 * (Extends xmlSchemaTreeItem)
375 */
376typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
377typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
378struct _xmlSchemaModelGroupDef {
379 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
380 xmlSchemaAnnotPtr annot;
381 xmlSchemaTreeItemPtr next; /* not used */
382 xmlSchemaTreeItemPtr children; /* the "model group" */
383 const xmlChar *name;
384 const xmlChar *targetNamespace;
385 xmlNodePtr node;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000386 int flags;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000387};
388
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000389typedef struct _xmlSchemaIDC xmlSchemaIDC;
390typedef xmlSchemaIDC *xmlSchemaIDCPtr;
391
392/**
393 * xmlSchemaIDCSelect:
394 *
395 * The identity-constraint "field" and "selector" item, holding the
396 * XPath expression.
397 */
398typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
399typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000400struct _xmlSchemaIDCSelect {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000401 xmlSchemaIDCSelectPtr next;
402 xmlSchemaIDCPtr idc;
403 int index; /* an index position if significant for IDC key-sequences */
404 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000405 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000406};
407
408/**
409 * xmlSchemaIDC:
410 *
411 * The identity-constraint definition component.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000412 * (Extends xmlSchemaAnnotItem)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000413 */
414
415struct _xmlSchemaIDC {
416 xmlSchemaTypeType type;
417 xmlSchemaAnnotPtr annot;
418 xmlSchemaIDCPtr next;
419 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000420 const xmlChar *name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000421 const xmlChar *targetNamespace;
422 xmlSchemaIDCSelectPtr selector;
423 xmlSchemaIDCSelectPtr fields;
424 int nbFields;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000425 xmlSchemaQNameRefPtr ref;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000426};
427
428/**
429 * xmlSchemaIDCAug:
430 *
431 * The augmented IDC information used for validation.
432 */
433typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
434typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
435struct _xmlSchemaIDCAug {
436 xmlSchemaIDCAugPtr next; /* next in a list */
437 xmlSchemaIDCPtr def; /* the IDC definition */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000438 int bubbleDepth; /* the lowest tree level to which IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000439 tables need to be bubbled upwards */
440};
441
442/**
443 * xmlSchemaPSVIIDCKeySequence:
444 *
445 * The key sequence of a node table item.
446 */
447typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
448typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
449struct _xmlSchemaPSVIIDCKey {
450 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000451 xmlSchemaValPtr val;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000452};
453
454/**
455 * xmlSchemaPSVIIDCNode:
456 *
457 * The node table item of a node table.
458 */
459typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
460typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
461struct _xmlSchemaPSVIIDCNode {
462 xmlNodePtr node;
463 xmlSchemaPSVIIDCKeyPtr *keys;
464};
465
466/**
467 * xmlSchemaPSVIIDCBinding:
468 *
469 * The identity-constraint binding item of the [identity-constraint table].
470 */
471typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
472typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
473struct _xmlSchemaPSVIIDCBinding {
474 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
475 xmlSchemaIDCPtr definition; /* the IDC definition */
476 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
477 int nbNodes; /* number of entries in the node table */
478 int sizeNodes; /* size of the node table */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000479 int nbDupls; /* number of already identified duplicates in the node
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000480 table */
481 /* int nbKeys; number of keys in each key-sequence */
482};
483
484#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
485#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
486
487#define XPATH_STATE_OBJ_MATCHES -2
488#define XPATH_STATE_OBJ_BLOCKED -3
489
490typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
491typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
492
493/**
494 * xmlSchemaIDCStateObj:
495 *
496 * The state object used to evaluate XPath expressions.
497 */
498typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
499typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
500struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000501 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000502 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000503 int depth; /* depth of creation */
504 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000505 int nbHistory;
506 int sizeHistory;
507 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
508 matcher */
509 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000510 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000511};
512
513#define IDC_MATCHER 0
514
515/**
516 * xmlSchemaIDCMatcher:
517 *
518 * Used to IDC selectors (and fields) successively.
519 */
520struct _xmlSchemaIDCMatcher {
521 int type;
522 int depth; /* the tree depth at creation time */
523 xmlSchemaIDCMatcherPtr next; /* next in the list */
524 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
525 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
526 elements */
527 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000528 int targetDepth;
529};
530
531/*
532* Element info flags.
533*/
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000534#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
535#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
536#define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
537#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
538
539#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
540#define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
541#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
542
543#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
544#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
545#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
546#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000547
548/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000549 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000550 *
551 * Holds information of an element node.
552 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000553struct _xmlSchemaNodeInfo {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000554 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000555 int nodeType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000556 const xmlChar *localName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000557 const xmlChar *nsName;
558 const xmlChar *value;
559 xmlSchemaValPtr val; /* the pre-computed value if any */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000560 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000561 int flags; /* combination of node info flags */
562 int valNeeded;
563 int normVal;
564
565 xmlSchemaElementPtr decl; /* the element/attribute declaration */
566 int depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000567 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
568 for the scope element*/
569 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
570 element */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000571 xmlRegExecCtxtPtr regexCtxt;
572
573 const xmlChar **nsBindings; /* Namespace bindings on this element */
574 int nbNsBindings;
575 int sizeNsBindings;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000576};
577
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000578/*
579* @metaType values of xmlSchemaAttrInfo.
580*/
581#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
582#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
583#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
584#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
585#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000586
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000587typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
588typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
589struct _xmlSchemaAttrInfo {
590 xmlNodePtr node;
591 int nodeType;
592 const xmlChar *localName;
593 const xmlChar *nsName;
594 const xmlChar *value;
595 xmlSchemaValPtr val; /* the pre-computed value if any */
596 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
597 int flags; /* combination of node info flags */
598
599 xmlSchemaAttributePtr decl; /* the attribute declaration */
600 xmlSchemaAttributePtr use; /* the attribute use */
601 int state;
602 int metaType;
603 const xmlChar *vcValue; /* the value constraint value */
604 xmlSchemaNodeInfoPtr parent;
605};
606
607
608#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
Daniel Veillard4255d502002-04-16 15:50:10 +0000609/**
610 * xmlSchemaValidCtxt:
611 *
612 * A Schemas validation context
613 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000614struct _xmlSchemaValidCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000615 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000616 void *userData; /* user specific data block */
617 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000618 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000619 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000620
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000621 xmlSchemaPtr schema; /* The schema in use */
622 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000623 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000624 xmlCharEncoding enc;
625 xmlSAXHandlerPtr sax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000626 xmlParserCtxtPtr parserCtxt;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000627 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000628
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000629 int err;
630 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000631
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000632 xmlNodePtr node;
633 xmlNodePtr cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000634 /* xmlSchemaTypePtr type; */
Daniel Veillard4255d502002-04-16 15:50:10 +0000635
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000636 xmlRegExecCtxtPtr regexp;
637 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000638
Daniel Veillardc0826a72004-08-10 14:17:33 +0000639 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000640 int options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000641 xmlNodePtr validationRoot;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000642 xmlSchemaParserCtxtPtr pctxt;
643 int xsiAssemble;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000644
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000645 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000646 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000647 int sizeElemInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000648 xmlSchemaNodeInfoPtr inode; /* the current element information */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000649
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000650 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
651
652 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
653 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000654
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000655 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
656 int nbIdcNodes;
657 int sizeIdcNodes;
658
659 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
660 int nbIdcKeys;
661 int sizeIdcKeys;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000662
663 int flags;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000664
665 xmlDictPtr dict;
666
Daniel Veillard39e5c892005-07-03 22:48:50 +0000667#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000668 xmlTextReaderPtr reader;
Daniel Veillard39e5c892005-07-03 22:48:50 +0000669#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000670
671 xmlSchemaAttrInfoPtr *attrInfos;
672 int nbAttrInfos;
673 int sizeAttrInfos;
674
675 int skipDepth;
Daniel Veillard4255d502002-04-16 15:50:10 +0000676};
677
Daniel Veillard1d913862003-11-21 00:28:39 +0000678/*
679 * These are the entries in the schemas importSchemas hash table
680 */
681typedef struct _xmlSchemaImport xmlSchemaImport;
682typedef xmlSchemaImport *xmlSchemaImportPtr;
683struct _xmlSchemaImport {
684 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000685 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000686 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000687 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000688};
Daniel Veillard4255d502002-04-16 15:50:10 +0000689
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000690/*
691 * These are the entries associated to includes in a schemas
692 */
693typedef struct _xmlSchemaInclude xmlSchemaInclude;
694typedef xmlSchemaInclude *xmlSchemaIncludePtr;
695struct _xmlSchemaInclude {
696 xmlSchemaIncludePtr next;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000697 const xmlChar *schemaLocation;
698 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000699 const xmlChar *origTargetNamespace;
700 const xmlChar *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000701};
702
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000703/**
704 * xmlSchemaSubstGroup:
705 *
706 *
707 */
708typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
709typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
710struct _xmlSchemaSubstGroup {
711 xmlSchemaElementPtr head;
712 xmlSchemaItemListPtr members;
713};
714
Daniel Veillard4255d502002-04-16 15:50:10 +0000715/************************************************************************
716 * *
717 * Some predeclarations *
718 * *
719 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000720
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000721static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
722 xmlSchemaPtr schema,
723 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000724static void
725xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
726 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000727static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +0000728xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
729static int
William M. Brack2f2a6632004-08-20 23:09:47 +0000730xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
731 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000732static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000733xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
734 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +0000735static void
736xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000737static xmlSchemaWhitespaceValueType
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +0000738xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000739static xmlSchemaTreeItemPtr
740xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
741 xmlNodePtr node, xmlSchemaTypeType type,
742 int withParticle);
743static const xmlChar *
744xmlSchemaCompTypeToString(xmlSchemaTypeType type);
745static xmlSchemaTypeLinkPtr
746xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000747static void
748xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
749 const char *funcName,
750 const char *message);
751static int
752xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
753 xmlSchemaTypePtr baseType,
754 int subset);
755static void
756xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
757 xmlSchemaParserCtxtPtr ctxt,
758 const xmlChar * name ATTRIBUTE_UNUSED);
William M. Brack87640d52004-04-17 14:58:15 +0000759
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000760/************************************************************************
761 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000762 * Helper functions *
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000763 * *
764 ************************************************************************/
765
766/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000767 * xmlSchemaCompTypeToString:
768 * @type: the type of the schema item
769 *
770 * Returns the component name of a schema item.
771 */
772static const xmlChar *
773xmlSchemaCompTypeToString(xmlSchemaTypeType type)
774{
775 switch (type) {
776 case XML_SCHEMA_TYPE_SIMPLE:
777 return(BAD_CAST "simple type definition");
778 case XML_SCHEMA_TYPE_COMPLEX:
779 return(BAD_CAST "complex type definition");
780 case XML_SCHEMA_TYPE_ELEMENT:
781 return(BAD_CAST "element declaration");
782 case XML_SCHEMA_TYPE_ATTRIBUTE:
783 return(BAD_CAST "attribute declaration");
784 case XML_SCHEMA_TYPE_GROUP:
785 return(BAD_CAST "model group definition");
786 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
787 return(BAD_CAST "attribute group definition");
788 case XML_SCHEMA_TYPE_NOTATION:
789 return(BAD_CAST "notation declaration");
790 case XML_SCHEMA_TYPE_SEQUENCE:
791 return(BAD_CAST "model group (sequence)");
792 case XML_SCHEMA_TYPE_CHOICE:
793 return(BAD_CAST "model group (choice)");
794 case XML_SCHEMA_TYPE_ALL:
795 return(BAD_CAST "model group (all)");
796 case XML_SCHEMA_TYPE_PARTICLE:
797 return(BAD_CAST "particle");
798 default:
799 return(BAD_CAST "Not a schema component");
800 }
801}
802
803/**
804 * xmlSchemaGetComponentNode:
805 * @item: a schema component
806 *
807 * Returns node associated with the schema component.
808 * NOTE that such a node need not be available; plus, a component's
809 * node need not to reflect the component directly, since there is no
810 * one-to-one relationship between the XML Schema representation and
811 * the component representation.
812 */
813static xmlNodePtr
814xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
815{
816 switch (item->type) {
817 case XML_SCHEMA_TYPE_ELEMENT:
818 return (((xmlSchemaElementPtr) item)->node);
819 case XML_SCHEMA_TYPE_ATTRIBUTE:
820 return (((xmlSchemaAttributePtr) item)->node);
821 case XML_SCHEMA_TYPE_COMPLEX:
822 case XML_SCHEMA_TYPE_SIMPLE:
823 return (((xmlSchemaTypePtr) item)->node);
824 case XML_SCHEMA_TYPE_ANY:
825 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
826 return (((xmlSchemaWildcardPtr) item)->node);
827 case XML_SCHEMA_TYPE_PARTICLE:
828 return (((xmlSchemaParticlePtr) item)->node);
829 case XML_SCHEMA_TYPE_SEQUENCE:
830 case XML_SCHEMA_TYPE_CHOICE:
831 case XML_SCHEMA_TYPE_ALL:
832 return (((xmlSchemaModelGroupPtr) item)->node);
833 case XML_SCHEMA_TYPE_GROUP:
834 return (((xmlSchemaModelGroupDefPtr) item)->node);
835 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
836 return (((xmlSchemaAttributeGroupPtr) item)->node);
837 case XML_SCHEMA_TYPE_IDC_UNIQUE:
838 case XML_SCHEMA_TYPE_IDC_KEY:
839 case XML_SCHEMA_TYPE_IDC_KEYREF:
840 return (((xmlSchemaIDCPtr) item)->node);
841 default:
842 return (NULL);
843 }
844}
845
846#if 0
847/**
848 * xmlSchemaGetNextComponent:
849 * @item: a schema component
850 *
851 * Returns the next sibling of the schema component.
852 */
853static xmlSchemaBasicItemPtr
854xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
855{
856 switch (item->type) {
857 case XML_SCHEMA_TYPE_ELEMENT:
858 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
859 case XML_SCHEMA_TYPE_ATTRIBUTE:
860 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
861 case XML_SCHEMA_TYPE_COMPLEX:
862 case XML_SCHEMA_TYPE_SIMPLE:
863 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
864 case XML_SCHEMA_TYPE_ANY:
865 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
866 return (NULL);
867 case XML_SCHEMA_TYPE_PARTICLE:
868 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
869 case XML_SCHEMA_TYPE_SEQUENCE:
870 case XML_SCHEMA_TYPE_CHOICE:
871 case XML_SCHEMA_TYPE_ALL:
872 return (NULL);
873 case XML_SCHEMA_TYPE_GROUP:
874 return (NULL);
875 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
876 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
877 case XML_SCHEMA_TYPE_IDC_UNIQUE:
878 case XML_SCHEMA_TYPE_IDC_KEY:
879 case XML_SCHEMA_TYPE_IDC_KEYREF:
880 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
881 default:
882 return (NULL);
883 }
884}
885#endif
886
887/**
888 * xmlSchemaGetAttrName:
889 * @attr: the attribute declaration/use
890 *
891 * Returns the name of the attribute; if the attribute
892 * is a reference, the name of the referenced global type will be returned.
893 */
894static const xmlChar *
895xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
896{
897 if (attr->ref != NULL)
898 return(attr->ref);
899 else
900 return(attr->name);
901}
902
903/**
904 * xmlSchemaGetAttrTargetNsURI:
905 * @type: the type (element or attribute)
906 *
907 * Returns the target namespace URI of the type; if the type is a reference,
908 * the target namespace of the referenced type will be returned.
909 */
910static const xmlChar *
911xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
912{
913 if (attr->ref != NULL)
914 return (attr->refNs);
915 else
916 return(attr->targetNamespace);
917}
918
919/**
920 * xmlSchemaFormatQName:
921 * @buf: the string buffer
922 * @namespaceName: the namespace name
923 * @localName: the local name
924 *
925 * Returns the given QName in the format "{namespaceName}localName" or
926 * just "localName" if @namespaceName is NULL.
927 *
928 * Returns the localName if @namespaceName is NULL, a formatted
929 * string otherwise.
930 */
931static const xmlChar*
932xmlSchemaFormatQName(xmlChar **buf,
933 const xmlChar *namespaceName,
934 const xmlChar *localName)
935{
936 FREE_AND_NULL(*buf)
937 if (namespaceName == NULL)
938 return(localName);
939
940 *buf = xmlStrdup(BAD_CAST "{");
941 *buf = xmlStrcat(*buf, namespaceName);
942 *buf = xmlStrcat(*buf, BAD_CAST "}");
943 *buf = xmlStrcat(*buf, localName);
944
945 return ((const xmlChar *) *buf);
946}
947
948static const xmlChar*
949xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
950{
951 if (ns != NULL)
952 return (xmlSchemaFormatQName(buf, ns->href, localName));
953 else
954 return (xmlSchemaFormatQName(buf, NULL, localName));
955}
956
957static const xmlChar *
958xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
959{
960 switch (item->type) {
961 case XML_SCHEMA_TYPE_ELEMENT:
962 return (((xmlSchemaElementPtr) item)->name);
963 case XML_SCHEMA_TYPE_ATTRIBUTE:
964 return (((xmlSchemaAttributePtr) item)->name);
965 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
966 return (((xmlSchemaAttributeGroupPtr) item)->name);
967 case XML_SCHEMA_TYPE_BASIC:
968 case XML_SCHEMA_TYPE_SIMPLE:
969 case XML_SCHEMA_TYPE_COMPLEX:
970 return (((xmlSchemaTypePtr) item)->name);
971 case XML_SCHEMA_TYPE_GROUP:
972 return (((xmlSchemaModelGroupDefPtr) item)->name);
973 case XML_SCHEMA_TYPE_IDC_KEY:
974 case XML_SCHEMA_TYPE_IDC_UNIQUE:
975 case XML_SCHEMA_TYPE_IDC_KEYREF:
976 return (((xmlSchemaIDCPtr) item)->name);
977 default:
978 /*
979 * Other components cannot have names.
980 */
981 break;
982 }
983 return (NULL);
984}
985
986static const xmlChar *
987xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
988{
989 switch (item->type) {
990 case XML_SCHEMA_TYPE_ELEMENT:
991 return (((xmlSchemaElementPtr) item)->targetNamespace);
992 case XML_SCHEMA_TYPE_ATTRIBUTE:
993 return (((xmlSchemaAttributePtr) item)->targetNamespace);
994 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
995 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
996 case XML_SCHEMA_TYPE_BASIC:
997 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
998 case XML_SCHEMA_TYPE_SIMPLE:
999 case XML_SCHEMA_TYPE_COMPLEX:
1000 return (((xmlSchemaTypePtr) item)->targetNamespace);
1001 case XML_SCHEMA_TYPE_GROUP:
1002 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1003 case XML_SCHEMA_TYPE_IDC_KEY:
1004 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1005 case XML_SCHEMA_TYPE_IDC_KEYREF:
1006 return (((xmlSchemaIDCPtr) item)->targetNamespace);
1007 default:
1008 /*
1009 * Other components cannot have names.
1010 */
1011 break;
1012 }
1013 return (NULL);
1014}
1015
1016static const xmlChar*
1017xmlSchemaGetComponentQName(xmlChar **buf,
1018 void *item)
1019{
1020 return (xmlSchemaFormatQName(buf,
1021 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1022 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1023}
1024
1025/**
1026 * xmlSchemaWildcardPCToString:
1027 * @pc: the type of processContents
1028 *
1029 * Returns a string representation of the type of
1030 * processContents.
1031 */
1032static const xmlChar *
1033xmlSchemaWildcardPCToString(int pc)
1034{
1035 switch (pc) {
1036 case XML_SCHEMAS_ANY_SKIP:
1037 return (BAD_CAST "skip");
1038 case XML_SCHEMAS_ANY_LAX:
1039 return (BAD_CAST "lax");
1040 case XML_SCHEMAS_ANY_STRICT:
1041 return (BAD_CAST "strict");
1042 default:
1043 return (BAD_CAST "invalid process contents");
1044 }
1045}
1046
1047/**
1048 * xmlSchemaGetCanonValueWhtspExt:
1049 * @val: the precomputed value
1050 * @retValue: the returned value
1051 * @ws: the whitespace type of the value
1052 *
1053 * Get a the cononical representation of the value.
1054 * The caller has to free the returned retValue.
1055 *
1056 * Returns 0 if the value could be built and -1 in case of
1057 * API errors or if the value type is not supported yet.
1058 */
1059static int
1060xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1061 xmlSchemaWhitespaceValueType ws,
1062 xmlChar **retValue)
1063{
1064 int list;
1065 xmlSchemaValType valType;
1066 const xmlChar *value, *value2 = NULL;
1067
1068
1069 if ((retValue == NULL) || (val == NULL))
1070 return (-1);
1071 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1072 *retValue = NULL;
1073 do {
1074 value = NULL;
1075 valType = xmlSchemaGetValType(val);
1076 switch (valType) {
1077 case XML_SCHEMAS_STRING:
1078 case XML_SCHEMAS_NORMSTRING:
1079 case XML_SCHEMAS_ANYSIMPLETYPE:
1080 value = xmlSchemaValueGetAsString(val);
1081 if (value != NULL) {
1082 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1083 value2 = xmlSchemaCollapseString(value);
1084 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1085 value2 = xmlSchemaWhiteSpaceReplace(value);
1086 if (value2 != NULL)
1087 value = value2;
1088 }
1089 break;
1090 default:
1091 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1092 if (value2 != NULL)
1093 xmlFree((xmlChar *) value2);
1094 goto internal_error;
1095 }
1096 value = value2;
1097 }
1098 if (*retValue == NULL)
1099 if (value == NULL) {
1100 if (! list)
1101 *retValue = xmlStrdup(BAD_CAST "");
1102 } else
1103 *retValue = xmlStrdup(value);
1104 else if (value != NULL) {
1105 /* List. */
1106 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1107 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1108 }
1109 FREE_AND_NULL(value2)
1110 val = xmlSchemaValueGetNext(val);
1111 } while (val != NULL);
1112
1113 return (0);
1114internal_error:
1115 if (*retValue != NULL)
1116 xmlFree((xmlChar *) (*retValue));
1117 if (value2 != NULL)
1118 xmlFree((xmlChar *) value2);
1119 return (-1);
1120}
1121
1122/**
1123 * xmlSchemaFormatItemForReport:
1124 * @buf: the string buffer
1125 * @itemDes: the designation of the item
1126 * @itemName: the name of the item
1127 * @item: the item as an object
1128 * @itemNode: the node of the item
1129 * @local: the local name
1130 * @parsing: if the function is used during the parse
1131 *
1132 * Returns a representation of the given item used
1133 * for error reports.
1134 *
1135 * The following order is used to build the resulting
1136 * designation if the arguments are not NULL:
1137 * 1a. If itemDes not NULL -> itemDes
1138 * 1b. If (itemDes not NULL) and (itemName not NULL)
1139 * -> itemDes + itemName
1140 * 2. If the preceding was NULL and (item not NULL) -> item
1141 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1142 *
1143 * If the itemNode is an attribute node, the name of the attribute
1144 * will be appended to the result.
1145 *
1146 * Returns the formatted string and sets @buf to the resulting value.
1147 */
1148static xmlChar*
1149xmlSchemaFormatItemForReport(xmlChar **buf,
1150 const xmlChar *itemDes,
1151 xmlSchemaTypePtr item,
1152 xmlNodePtr itemNode)
1153{
1154 xmlChar *str = NULL;
1155 int named = 1;
1156
1157 if (*buf != NULL) {
1158 xmlFree(*buf);
1159 *buf = NULL;
1160 }
1161
1162 if (itemDes != NULL) {
1163 *buf = xmlStrdup(itemDes);
1164 } else if (item != NULL) {
1165 switch (item->type) {
1166 case XML_SCHEMA_TYPE_BASIC:
1167 if (VARIETY_ATOMIC(item))
1168 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1169 else if (VARIETY_LIST(item))
1170 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
1171 else if (VARIETY_UNION(item))
1172 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1173 else
1174 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1175 *buf = xmlStrcat(*buf, item->name);
1176 *buf = xmlStrcat(*buf, BAD_CAST "'");
1177 break;
1178 case XML_SCHEMA_TYPE_SIMPLE:
1179 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1180 *buf = xmlStrdup(BAD_CAST"");
1181 } else {
1182 *buf = xmlStrdup(BAD_CAST "local ");
1183 }
1184 if (VARIETY_ATOMIC(item))
1185 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1186 else if (VARIETY_LIST(item))
1187 *buf = xmlStrcat(*buf, BAD_CAST "list type");
1188 else if (VARIETY_UNION(item))
1189 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1190 else
1191 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
1192 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1193 *buf = xmlStrcat(*buf, BAD_CAST " '");
1194 *buf = xmlStrcat(*buf, item->name);
1195 *buf = xmlStrcat(*buf, BAD_CAST "'");
1196 }
1197 break;
1198 case XML_SCHEMA_TYPE_COMPLEX:
1199 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1200 *buf = xmlStrdup(BAD_CAST "");
1201 else
1202 *buf = xmlStrdup(BAD_CAST "local ");
1203 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1204 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1205 *buf = xmlStrcat(*buf, BAD_CAST " '");
1206 *buf = xmlStrcat(*buf, item->name);
1207 *buf = xmlStrcat(*buf, BAD_CAST "'");
1208 }
1209 break;
1210 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1211 xmlSchemaAttributePtr attr;
1212
1213 attr = (xmlSchemaAttributePtr) item;
1214 if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
1215 (attr->ref == NULL)) {
1216 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1217 *buf = xmlStrcat(*buf, BAD_CAST " '");
1218 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1219 attr->targetNamespace, attr->name));
1220 FREE_AND_NULL(str)
1221 *buf = xmlStrcat(*buf, BAD_CAST "'");
1222 } else {
1223 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1224 *buf = xmlStrcat(*buf, BAD_CAST " '");
1225 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1226 attr->refNs, attr->ref));
1227 FREE_AND_NULL(str)
1228 *buf = xmlStrcat(*buf, BAD_CAST "'");
1229 }
1230 }
1231 break;
1232 case XML_SCHEMA_TYPE_ELEMENT: {
1233 xmlSchemaElementPtr elem;
1234
1235 elem = (xmlSchemaElementPtr) item;
1236 if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) ||
1237 (elem->ref == NULL)) {
1238 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1239 *buf = xmlStrcat(*buf, BAD_CAST " '");
1240 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1241 elem->targetNamespace, elem->name));
1242 *buf = xmlStrcat(*buf, BAD_CAST "'");
1243 }
1244 }
1245 break;
1246 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1247 case XML_SCHEMA_TYPE_IDC_KEY:
1248 case XML_SCHEMA_TYPE_IDC_KEYREF:
1249 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1250 *buf = xmlStrdup(BAD_CAST "unique '");
1251 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1252 *buf = xmlStrdup(BAD_CAST "key '");
1253 else
1254 *buf = xmlStrdup(BAD_CAST "keyRef '");
1255 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1256 *buf = xmlStrcat(*buf, BAD_CAST "'");
1257 break;
1258 case XML_SCHEMA_TYPE_ANY:
1259 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1260 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1261 ((xmlSchemaWildcardPtr) item)->processContents));
1262 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1263 break;
1264 case XML_SCHEMA_FACET_MININCLUSIVE:
1265 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1266 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1267 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1268 case XML_SCHEMA_FACET_TOTALDIGITS:
1269 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1270 case XML_SCHEMA_FACET_PATTERN:
1271 case XML_SCHEMA_FACET_ENUMERATION:
1272 case XML_SCHEMA_FACET_WHITESPACE:
1273 case XML_SCHEMA_FACET_LENGTH:
1274 case XML_SCHEMA_FACET_MAXLENGTH:
1275 case XML_SCHEMA_FACET_MINLENGTH:
1276 *buf = xmlStrdup(BAD_CAST "facet '");
1277 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1278 *buf = xmlStrcat(*buf, BAD_CAST "'");
1279 break;
1280 case XML_SCHEMA_TYPE_NOTATION:
1281 *buf = xmlStrdup(BAD_CAST "notation");
1282 break;
1283 case XML_SCHEMA_TYPE_GROUP: {
1284 *buf = xmlStrdup(xmlSchemaElemModelGrDef);
1285 *buf = xmlStrcat(*buf, BAD_CAST " '");
1286 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1287 ((xmlSchemaModelGroupDefPtr) item)->targetNamespace,
1288 ((xmlSchemaModelGroupDefPtr) item)->name));
1289 *buf = xmlStrcat(*buf, BAD_CAST "'");
1290 FREE_AND_NULL(str)
1291 }
1292 break;
1293 case XML_SCHEMA_TYPE_SEQUENCE:
1294 case XML_SCHEMA_TYPE_CHOICE:
1295 case XML_SCHEMA_TYPE_ALL:
1296 case XML_SCHEMA_TYPE_PARTICLE:
1297 *buf = xmlStrdup(xmlSchemaCompTypeToString(item->type));
1298 break;
1299 default:
1300 named = 0;
1301 }
1302 } else
1303 named = 0;
1304
1305 if ((named == 0) && (itemNode != NULL)) {
1306 xmlNodePtr elem;
1307
1308 if (itemNode->type == XML_ATTRIBUTE_NODE)
1309 elem = itemNode->parent;
1310 else
1311 elem = itemNode;
1312 *buf = xmlStrdup(BAD_CAST "Element '");
1313 if (elem->ns != NULL) {
1314 *buf = xmlStrcat(*buf,
1315 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1316 FREE_AND_NULL(str)
1317 } else
1318 *buf = xmlStrcat(*buf, elem->name);
1319 *buf = xmlStrcat(*buf, BAD_CAST "'");
1320
1321 }
1322 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1323 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1324 if (itemNode->ns != NULL) {
1325 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1326 itemNode->ns->href, itemNode->name));
1327 FREE_AND_NULL(str)
1328 } else
1329 *buf = xmlStrcat(*buf, itemNode->name);
1330 *buf = xmlStrcat(*buf, BAD_CAST "'");
1331 }
1332 FREE_AND_NULL(str)
1333
1334 return (*buf);
1335}
1336
1337/**
1338 * xmlSchemaFormatFacetEnumSet:
1339 * @buf: the string buffer
1340 * @type: the type holding the enumeration facets
1341 *
1342 * Builds a string consisting of all enumeration elements.
1343 *
1344 * Returns a string of all enumeration elements.
1345 */
1346static const xmlChar *
1347xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1348 xmlChar **buf, xmlSchemaTypePtr type)
1349{
1350 xmlSchemaFacetPtr facet;
1351 xmlSchemaWhitespaceValueType ws;
1352 xmlChar *value = NULL;
1353 int res;
1354
1355 if (*buf != NULL)
1356 xmlFree(*buf);
1357 *buf = NULL;
1358
1359 do {
1360 /*
1361 * Use the whitespace type of the base type.
1362 */
1363 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1364 for (facet = type->facets; facet != NULL; facet = facet->next) {
1365 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1366 continue;
1367 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1368 ws, &value);
1369 if (res == -1) {
1370 xmlSchemaInternalErr(actxt,
1371 "xmlSchemaFormatFacetEnumSet",
1372 "compute the canonical lexical representation");
1373 if (*buf != NULL)
1374 xmlFree(*buf);
1375 *buf = NULL;
1376 return (NULL);
1377 }
1378 if (*buf == NULL)
1379 *buf = xmlStrdup(BAD_CAST "'");
1380 else
1381 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1382 *buf = xmlStrcat(*buf, BAD_CAST value);
1383 *buf = xmlStrcat(*buf, BAD_CAST "'");
1384 if (value != NULL) {
1385 xmlFree((xmlChar *)value);
1386 value = NULL;
1387 }
1388 }
1389 type = type->baseType;
1390 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1391
1392 return ((const xmlChar *) *buf);
1393}
1394
1395/************************************************************************
1396 * *
1397 * Error functions *
1398 * *
1399 ************************************************************************/
1400
1401#if 0
1402static void
1403xmlSchemaErrMemory(const char *msg)
1404{
1405 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1406 msg);
1407}
1408#endif
1409
1410/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001411 * xmlSchemaPErrMemory:
1412 * @node: a context node
1413 * @extra: extra informations
1414 *
1415 * Handle an out of memory condition
1416 */
1417static void
1418xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1419 const char *extra, xmlNodePtr node)
1420{
1421 if (ctxt != NULL)
1422 ctxt->nberrors++;
1423 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1424 extra);
1425}
1426
1427/**
1428 * xmlSchemaPErr:
1429 * @ctxt: the parsing context
1430 * @node: the context node
1431 * @error: the error code
1432 * @msg: the error message
1433 * @str1: extra data
1434 * @str2: extra data
1435 *
1436 * Handle a parser error
1437 */
1438static void
1439xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1440 const char *msg, const xmlChar * str1, const xmlChar * str2)
1441{
1442 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001443 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001444 void *data = NULL;
1445
1446 if (ctxt != NULL) {
1447 ctxt->nberrors++;
1448 channel = ctxt->error;
1449 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001450 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001451 }
Daniel Veillard659e71e2003-10-10 14:10:40 +00001452 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001453 error, XML_ERR_ERROR, NULL, 0,
1454 (const char *) str1, (const char *) str2, NULL, 0, 0,
1455 msg, str1, str2);
1456}
1457
1458/**
1459 * xmlSchemaPErr2:
1460 * @ctxt: the parsing context
1461 * @node: the context node
1462 * @node: the current child
1463 * @error: the error code
1464 * @msg: the error message
1465 * @str1: extra data
1466 * @str2: extra data
1467 *
1468 * Handle a parser error
1469 */
1470static void
1471xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1472 xmlNodePtr child, int error,
1473 const char *msg, const xmlChar * str1, const xmlChar * str2)
1474{
1475 if (child != NULL)
1476 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1477 else
1478 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1479}
1480
Daniel Veillard01fa6152004-06-29 17:04:39 +00001481
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001482/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001483 * xmlSchemaPErrExt:
1484 * @ctxt: the parsing context
1485 * @node: the context node
1486 * @error: the error code
1487 * @strData1: extra data
1488 * @strData2: extra data
1489 * @strData3: extra data
1490 * @msg: the message
1491 * @str1: extra parameter for the message display
1492 * @str2: extra parameter for the message display
1493 * @str3: extra parameter for the message display
1494 * @str4: extra parameter for the message display
1495 * @str5: extra parameter for the message display
1496 *
1497 * Handle a parser error
1498 */
1499static void
1500xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1501 const xmlChar * strData1, const xmlChar * strData2,
1502 const xmlChar * strData3, const char *msg, const xmlChar * str1,
1503 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1504 const xmlChar * str5)
1505{
1506
1507 xmlGenericErrorFunc channel = NULL;
1508 xmlStructuredErrorFunc schannel = NULL;
1509 void *data = NULL;
1510
1511 if (ctxt != NULL) {
1512 ctxt->nberrors++;
1513 channel = ctxt->error;
1514 data = ctxt->userData;
1515 schannel = ctxt->serror;
1516 }
1517 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1518 error, XML_ERR_ERROR, NULL, 0,
1519 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +00001520 (const char *) strData3, 0, 0, msg, str1, str2,
1521 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +00001522}
Daniel Veillard01fa6152004-06-29 17:04:39 +00001523
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001524/************************************************************************
1525 * *
1526 * Allround error functions *
1527 * *
1528 ************************************************************************/
Daniel Veillard3646d642004-06-02 19:19:14 +00001529
1530/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001531 * xmlSchemaVTypeErrMemory:
1532 * @node: a context node
1533 * @extra: extra informations
1534 *
1535 * Handle an out of memory condition
1536 */
1537static void
1538xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1539 const char *extra, xmlNodePtr node)
1540{
1541 if (ctxt != NULL) {
1542 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001543 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001544 }
1545 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1546 extra);
1547}
1548
1549/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001550 * xmlSchemaErr3:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001551 * @ctxt: the validation context
1552 * @node: the context node
1553 * @error: the error code
1554 * @msg: the error message
1555 * @str1: extra data
1556 * @str2: extra data
1557 * @str3: extra data
1558 *
1559 * Handle a validation error
1560 */
1561static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001562xmlSchemaErr3(xmlSchemaAbstractCtxtPtr ctxt,
1563 int error, xmlNodePtr node, const char *msg,
1564 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001565{
Daniel Veillard659e71e2003-10-10 14:10:40 +00001566 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001567 xmlGenericErrorFunc channel = NULL;
1568 void *data = NULL;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001569
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001570 if (ctxt != NULL) {
1571 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1572 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
1573
1574 vctxt->nberrors++;
1575 vctxt->err = error;
1576 channel = vctxt->error;
1577 schannel = vctxt->serror;
1578 data = vctxt->userData;
1579 if ((node == NULL) && (vctxt->depth >= 0) &&
1580 (vctxt->inode != NULL))
1581 node = vctxt->inode->node;
1582 __xmlRaiseError(schannel, channel, data, ctxt,
1583 node, XML_FROM_SCHEMASV,
1584 error, XML_ERR_ERROR, NULL, 0,
1585 (const char *) str1, (const char *) str2,
1586 (const char *) str3, 0, 0, msg, str1, str2, str3);
1587
1588 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
1589 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
1590
1591 pctxt->nberrors++;
1592 pctxt->err = error;
1593 channel = pctxt->error;
1594 schannel = pctxt->serror;
1595 data = pctxt->userData;
1596 __xmlRaiseError(schannel, channel, data, ctxt,
1597 node, XML_FROM_SCHEMASP,
1598 error, XML_ERR_ERROR, NULL, 0,
1599 (const char *) str1, (const char *) str2,
1600 (const char *) str3, 0, 0, msg, str1, str2, str3);
1601 } else {
1602 TODO
1603 }
1604 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001605}
1606
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001607static void
1608xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
1609 int error, xmlNodePtr node, const char *msg,
1610 const xmlChar *str1, const xmlChar *str2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001611{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001612 xmlSchemaErr3(actxt, error, node, msg, str1, str2, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001613}
1614
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001615static xmlChar *
1616xmlSchemaFormatNodeForError(xmlChar ** msg,
1617 xmlSchemaAbstractCtxtPtr actxt,
1618 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001619{
1620 xmlChar *str = NULL;
1621
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001622 if (node != NULL) {
1623 /*
1624 * Work on tree nodes.
1625 */
1626 if (node->type == XML_ATTRIBUTE_NODE) {
1627 xmlNodePtr elem = node->parent;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001628
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001629 *msg = xmlStrdup(BAD_CAST "Element '");
1630 if (elem->ns != NULL)
1631 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1632 elem->ns->href, elem->name));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001633 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001634 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1635 NULL, elem->name));
1636 FREE_AND_NULL(str);
1637 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1638 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1639 } else {
1640 *msg = xmlStrdup(BAD_CAST "Element '");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001641 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001642 if (node->ns != NULL)
1643 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1644 node->ns->href, node->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001645 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001646 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1647 NULL, node->name));
1648 FREE_AND_NULL(str);
1649 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1650 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1651 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
1652 /*
1653 * Work on node infos.
1654 */
1655 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
1656 xmlSchemaNodeInfoPtr ielem =
1657 vctxt->elemInfos[vctxt->depth];
1658
1659 *msg = xmlStrdup(BAD_CAST "Element '");
1660 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1661 ielem->nsName, ielem->localName));
1662 FREE_AND_NULL(str);
1663 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1664 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1665 } else {
1666 *msg = xmlStrdup(BAD_CAST "Element '");
1667 }
1668 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1669 vctxt->inode->nsName, vctxt->inode->localName));
1670 FREE_AND_NULL(str);
1671 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1672 } else {
1673 TODO
1674 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001675 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001676 /*
1677 * VAL TODO: The output of the given schema component is currently
1678 * disabled.
1679 */
1680#if 0
1681 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
1682 *msg = xmlStrcat(*msg, BAD_CAST " [");
1683 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
1684 NULL, type, NULL, 0));
1685 FREE_AND_NULL(str)
1686 *msg = xmlStrcat(*msg, BAD_CAST "]");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001687 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001688#endif
1689 return (*msg);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001690}
1691
Daniel Veillardc0826a72004-08-10 14:17:33 +00001692static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001693xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1694 const char *funcName,
1695 const char *message)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001696{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001697 xmlChar *msg = NULL;
1698
1699 msg = xmlStrdup(BAD_CAST "Internal error: ");
1700 msg = xmlStrcat(msg, BAD_CAST funcName);
1701 msg = xmlStrcat(msg, BAD_CAST ", ");
1702 msg = xmlStrcat(msg, BAD_CAST message);
1703 msg = xmlStrcat(msg, BAD_CAST ".\n");
1704
1705 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
1706 xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
1707 (const char *) msg, NULL, NULL);
1708
1709 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
1710 xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
1711 (const char *) msg, NULL, NULL);
1712
1713 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001714}
1715
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001716static void
1717xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
1718 xmlParserErrors error,
1719 xmlNodePtr node,
1720 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
1721 const char *message,
1722 const xmlChar *str1,
1723 const xmlChar *str2)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001724{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001725 xmlChar *msg = NULL;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001726
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001727 xmlSchemaFormatNodeForError(&msg, actxt, node);
1728 msg = xmlStrcat(msg, (const xmlChar *) message);
1729 msg = xmlStrcat(msg, BAD_CAST ".\n");
1730 xmlSchemaErr(actxt, error, node,
1731 (const char *) msg, str1, str2);
1732 FREE_AND_NULL(msg)
1733}
1734
1735static int
1736xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
1737 xmlNodePtr node)
1738{
1739 if (node != NULL)
1740 return (node->type);
1741 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
1742 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
1743 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
1744 return (-1);
1745}
1746
1747static int
1748xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
1749{
1750 switch (item->type) {
1751 case XML_SCHEMA_TYPE_COMPLEX:
1752 case XML_SCHEMA_TYPE_SIMPLE:
1753 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1754 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001755 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001756 case XML_SCHEMA_TYPE_GROUP:
1757 return (1);
1758 case XML_SCHEMA_TYPE_ELEMENT:
1759 if ( ((xmlSchemaElementPtr) item)->flags &
1760 XML_SCHEMAS_ELEM_GLOBAL)
1761 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001762 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001763 case XML_SCHEMA_TYPE_ATTRIBUTE:
1764 if ( ((xmlSchemaAttributePtr) item)->flags &
1765 XML_SCHEMAS_ATTR_GLOBAL)
1766 return(1);
1767 break;
1768 /* Note that attribute groups are always global. */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001769 default:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001770 return(1);
1771 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001772 return (0);
1773}
1774
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001775static void
1776xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1777 xmlParserErrors error,
1778 xmlNodePtr node,
1779 const xmlChar *value,
1780 xmlSchemaTypePtr type,
1781 int displayValue)
1782{
1783 xmlChar *msg = NULL;
1784
1785 xmlSchemaFormatNodeForError(&msg, actxt, node);
1786
1787 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1788 XML_ATTRIBUTE_NODE))
1789 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
1790 else
1791 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
1792 "value of ");
1793
1794 if (! xmlSchemaIsGlobalItem(type))
1795 msg = xmlStrcat(msg, BAD_CAST "the local ");
1796 else
1797 msg = xmlStrcat(msg, BAD_CAST "the ");
1798
1799 if (VARIETY_ATOMIC(type))
1800 msg = xmlStrcat(msg, BAD_CAST "atomic type");
1801 else if (VARIETY_LIST(type))
1802 msg = xmlStrcat(msg, BAD_CAST "list type");
1803 else if (VARIETY_UNION(type))
1804 msg = xmlStrcat(msg, BAD_CAST "union type");
1805
1806 if (xmlSchemaIsGlobalItem(type)) {
1807 xmlChar *str = NULL;
1808 msg = xmlStrcat(msg, BAD_CAST " '");
1809 if (type->builtInType != 0) {
1810 msg = xmlStrcat(msg, BAD_CAST "xs:");
1811 msg = xmlStrcat(msg, type->name);
1812 } else
1813 msg = xmlStrcat(msg,
1814 xmlSchemaFormatQName(&str,
1815 type->targetNamespace, type->name));
1816 msg = xmlStrcat(msg, BAD_CAST "'");
1817 FREE_AND_NULL(str);
1818 }
1819 msg = xmlStrcat(msg, BAD_CAST ".\n");
1820 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1821 XML_ATTRIBUTE_NODE))
1822 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
1823 else
1824 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
1825 FREE_AND_NULL(msg)
1826}
1827
Daniel Veillardc0826a72004-08-10 14:17:33 +00001828static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001829xmlSchemaFormatErrorNodeQName(xmlChar ** str,
1830 xmlSchemaNodeInfoPtr ni,
1831 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001832{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001833 if (node != NULL) {
1834 if (node->ns != NULL)
1835 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
1836 else
1837 return (xmlSchemaFormatQName(str, NULL, node->name));
1838 } else if (ni != NULL)
1839 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
1840 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001841}
1842
Daniel Veillardc0826a72004-08-10 14:17:33 +00001843static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001844xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
1845 xmlParserErrors error,
1846 xmlSchemaAttrInfoPtr ni,
1847 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001848{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001849 xmlChar *msg = NULL, *str = NULL;
1850
1851 xmlSchemaFormatNodeForError(&msg, actxt, node);
1852 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
1853 xmlSchemaErr(actxt, error, node, (const char *) msg,
1854 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
1855 NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001856 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001857 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001858}
1859
Daniel Veillardc0826a72004-08-10 14:17:33 +00001860static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001861xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1862 xmlParserErrors error,
1863 xmlNodePtr node,
1864 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001865 const char *message,
1866 int nbval,
1867 int nbneg,
1868 xmlChar **values)
1869{
1870 xmlChar *str = NULL, *msg = NULL;
1871 xmlChar *localName, *nsName;
1872 const xmlChar *cur, *end;
1873 int i;
1874
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001875 xmlSchemaFormatNodeForError(&msg, actxt, node);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001876 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001877 msg = xmlStrcat(msg, BAD_CAST ".");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001878 /*
1879 * Note that is does not make sense to report that we have a
1880 * wildcard here, since the wildcard might be unfolded into
1881 * multiple transitions.
1882 */
1883 if (nbval + nbneg > 0) {
1884 if (nbval + nbneg > 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001885 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001886 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001887 str = xmlStrdup(BAD_CAST " Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001888 nsName = NULL;
1889
1890 for (i = 0; i < nbval + nbneg; i++) {
1891 cur = values[i];
1892 /*
1893 * Get the local name.
1894 */
1895 localName = NULL;
1896
1897 end = cur;
1898 if (*end == '*') {
1899 localName = xmlStrdup(BAD_CAST "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001900 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001901 } else {
1902 while ((*end != 0) && (*end != '|'))
1903 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001904 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001905 }
1906 if (*end != 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001907 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001908 /*
1909 * Skip "*|*" if they come with negated expressions, since
1910 * they represent the same negated wildcard.
1911 */
1912 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1913 /*
1914 * Get the namespace name.
1915 */
1916 cur = end;
1917 if (*end == '*') {
1918 nsName = xmlStrdup(BAD_CAST "{*}");
1919 } else {
1920 while (*end != 0)
1921 end++;
1922
1923 if (i >= nbval)
1924 nsName = xmlStrdup(BAD_CAST "{##other:");
1925 else
1926 nsName = xmlStrdup(BAD_CAST "{");
1927
1928 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1929 nsName = xmlStrcat(nsName, BAD_CAST "}");
1930 }
1931 str = xmlStrcat(str, BAD_CAST nsName);
1932 FREE_AND_NULL(nsName)
1933 } else {
1934 FREE_AND_NULL(localName);
1935 continue;
1936 }
1937 }
1938 str = xmlStrcat(str, BAD_CAST localName);
1939 FREE_AND_NULL(localName);
1940
1941 if (i < nbval + nbneg -1)
1942 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001943 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001944 str = xmlStrcat(str, BAD_CAST " ).\n");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001945 msg = xmlStrcat(msg, BAD_CAST str);
1946 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001947 } else
1948 msg = xmlStrcat(msg, BAD_CAST "\n");
1949 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001950 xmlFree(msg);
1951}
1952
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001953static void
1954xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
1955 xmlParserErrors error,
1956 xmlNodePtr node,
1957 const xmlChar *value,
1958 unsigned long length,
1959 xmlSchemaTypePtr type,
1960 xmlSchemaFacetPtr facet,
1961 const char *message,
1962 const xmlChar *str1,
1963 const xmlChar *str2)
1964{
1965 xmlChar *str = NULL, *msg = NULL;
1966 xmlSchemaTypeType facetType;
1967 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
1968
1969 xmlSchemaFormatNodeForError(&msg, actxt, node);
1970 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
1971 facetType = XML_SCHEMA_FACET_ENUMERATION;
1972 /*
1973 * If enumerations are validated, one must not expect the
1974 * facet to be given.
1975 */
1976 } else
1977 facetType = facet->type;
1978 msg = xmlStrcat(msg, BAD_CAST "[");
1979 msg = xmlStrcat(msg, BAD_CAST "facet '");
1980 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
1981 msg = xmlStrcat(msg, BAD_CAST "'] ");
1982 if (message == NULL) {
1983 /*
1984 * Use a default message.
1985 */
1986 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
1987 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
1988 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
1989
1990 char len[25], actLen[25];
1991
1992 /* FIXME, TODO: What is the max expected string length of the
1993 * this value?
1994 */
1995 if (nodeType == XML_ATTRIBUTE_NODE)
1996 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
1997 else
1998 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
1999
2000 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2001 snprintf(actLen, 24, "%lu", length);
2002
2003 if (facetType == XML_SCHEMA_FACET_LENGTH)
2004 msg = xmlStrcat(msg,
2005 BAD_CAST "this differs from the allowed length of '%s'.\n");
2006 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2007 msg = xmlStrcat(msg,
2008 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2009 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2010 msg = xmlStrcat(msg,
2011 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2012
2013 if (nodeType == XML_ATTRIBUTE_NODE)
2014 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2015 value, (const xmlChar *) actLen, (const xmlChar *) len);
2016 else
2017 xmlSchemaErr(actxt, error, node, (const char *) msg,
2018 (const xmlChar *) actLen, (const xmlChar *) len);
2019
2020 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2021 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2022 "of the set {%s}.\n");
2023 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2024 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2025 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2026 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2027 "by the pattern '%s'.\n");
2028 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2029 facet->value);
2030 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2031 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2032 "minimum value allowed ('%s').\n");
2033 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2034 facet->value);
2035 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2036 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2037 "maximum value allowed ('%s').\n");
2038 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2039 facet->value);
2040 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2041 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2042 "'%s'.\n");
2043 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2044 facet->value);
2045 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2046 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be more than "
2047 "'%s'.\n");
2048 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2049 facet->value);
2050 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2051 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2052 "digits than are allowed ('%s').\n");
2053 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2054 facet->value);
2055 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2056 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2057 "digits than are allowed ('%s').\n");
2058 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2059 facet->value);
2060 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2061 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2062 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2063 } else {
2064 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2065 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2066 }
2067 } else {
2068 msg = xmlStrcat(msg, (const xmlChar *) message);
2069 msg = xmlStrcat(msg, BAD_CAST ".\n");
2070 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2071 }
2072 FREE_AND_NULL(str)
2073 xmlFree(msg);
2074}
2075
2076#define VERROR(err, type, msg) \
2077 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, err, NULL, type, msg, NULL, NULL);
2078
2079#define VERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) vctxt, func, msg);
2080
2081#define PERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) pctxt, func, msg);
2082
2083#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2084
2085
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002086/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00002087 * xmlSchemaPMissingAttrErr:
2088 * @ctxt: the schema validation context
2089 * @ownerDes: the designation of the owner
2090 * @ownerName: the name of the owner
2091 * @ownerItem: the owner as a schema object
2092 * @ownerElem: the owner as an element node
2093 * @node: the parent element node of the missing attribute node
2094 * @type: the corresponding type of the attribute node
2095 *
2096 * Reports an illegal attribute.
2097 */
2098static void
2099xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002100 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002101 xmlSchemaTypePtr ownerItem,
2102 xmlNodePtr ownerElem,
2103 const char *name,
2104 const char *message)
2105{
2106 xmlChar *des = NULL;
2107
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002108 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2109
Daniel Veillardc0826a72004-08-10 14:17:33 +00002110 if (message != NULL)
2111 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002112 else
2113 xmlSchemaPErr(ctxt, ownerElem, error,
2114 "%s: The attribute '%s' is required but missing.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002115 BAD_CAST des, BAD_CAST name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002116 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002117}
2118
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002119
Daniel Veillardc0826a72004-08-10 14:17:33 +00002120/**
2121 * xmlSchemaPResCompAttrErr:
2122 * @ctxt: the schema validation context
2123 * @error: the error code
2124 * @ownerDes: the designation of the owner
2125 * @ownerItem: the owner as a schema object
2126 * @ownerElem: the owner as an element node
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002127 * @name: the name of the attribute holding the QName
Daniel Veillardc0826a72004-08-10 14:17:33 +00002128 * @refName: the referenced local name
2129 * @refURI: the referenced namespace URI
2130 * @message: optional message
2131 *
2132 * Used to report QName attribute values that failed to resolve
2133 * to schema components.
2134 */
2135static void
2136xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002137 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002138 xmlSchemaTypePtr ownerItem,
2139 xmlNodePtr ownerElem,
2140 const char *name,
2141 const xmlChar *refName,
2142 const xmlChar *refURI,
2143 xmlSchemaTypeType refType,
2144 const char *refTypeStr)
2145{
2146 xmlChar *des = NULL, *strA = NULL;
2147
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002148 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002149 if (refTypeStr == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002150 refTypeStr = (const char *) xmlSchemaCompTypeToString(refType);
2151 xmlSchemaPErrExt(ctxt, ownerElem, error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002152 NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002153 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2154 "%s.\n", BAD_CAST des, BAD_CAST name,
2155 xmlSchemaFormatQName(&strA, refURI, refName),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002156 BAD_CAST refTypeStr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002157 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002158 FREE_AND_NULL(strA)
2159}
2160
William M. Brack2f2a6632004-08-20 23:09:47 +00002161/**
2162 * xmlSchemaPCustomAttrErr:
2163 * @ctxt: the schema parser context
2164 * @error: the error code
2165 * @ownerDes: the designation of the owner
2166 * @ownerItem: the owner as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002167 * @attr: the illegal attribute node
William M. Brack2f2a6632004-08-20 23:09:47 +00002168 *
2169 * Reports an illegal attribute during the parse.
2170 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002171static void
2172xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002173 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002174 xmlChar **ownerDes,
2175 xmlSchemaTypePtr ownerItem,
2176 xmlAttrPtr attr,
2177 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002178{
2179 xmlChar *des = NULL;
2180
2181 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002182 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002183 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002184 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002185 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002186 } else
2187 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002188 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002189 "%s, attribute '%s': %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002190 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2191 if (ownerDes == NULL)
2192 FREE_AND_NULL(des);
2193}
2194
2195/**
2196 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002197 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002198 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002199 * @ownerDes: the designation of the attribute's owner
2200 * @ownerItem: the attribute's owner item
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002201 * @attr: the illegal attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00002202 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002203 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002204 */
2205static void
2206xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002207 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002208 xmlChar **ownerDes,
2209 xmlSchemaTypePtr ownerItem,
2210 xmlAttrPtr attr)
2211{
2212 xmlChar *des = NULL, *strA = NULL;
2213
2214 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002215 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002216 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002217 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002218 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002219 } else
2220 des = *ownerDes;
2221 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
2222 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
2223 xmlSchemaFormatQNameNs(&strA, attr->ns, attr->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002224 if (ownerDes == NULL)
2225 FREE_AND_NULL(des);
2226 FREE_AND_NULL(strA);
2227}
2228
William M. Brack2f2a6632004-08-20 23:09:47 +00002229/**
2230 * xmlSchemaPAquireDes:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002231 * @des: the first designation
William M. Brack2f2a6632004-08-20 23:09:47 +00002232 * @itemDes: the second designation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002233 * @item: the schema item
William M. Brack2f2a6632004-08-20 23:09:47 +00002234 * @itemElem: the node of the schema item
2235 *
2236 * Creates a designation for an item.
2237 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002238static void
2239xmlSchemaPAquireDes(xmlChar **des,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002240 xmlChar **itemDes,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002241 xmlSchemaTypePtr item,
2242 xmlNodePtr itemElem)
2243{
2244 if (itemDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002245 xmlSchemaFormatItemForReport(des, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002246 else if (*itemDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002247 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002248 *des = *itemDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002249 } else
2250 *des = *itemDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002251}
2252
William M. Brack2f2a6632004-08-20 23:09:47 +00002253/**
2254 * xmlSchemaPCustomErr:
2255 * @ctxt: the schema parser context
2256 * @error: the error code
2257 * @itemDes: the designation of the schema item
2258 * @item: the schema item
2259 * @itemElem: the node of the schema item
2260 * @message: the error message
2261 * @str1: an optional param for the error message
2262 * @str2: an optional param for the error message
2263 * @str3: an optional param for the error message
2264 *
2265 * Reports an error during parsing.
2266 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002267static void
2268xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002269 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002270 xmlChar **itemDes,
2271 xmlSchemaTypePtr item,
2272 xmlNodePtr itemElem,
2273 const char *message,
2274 const xmlChar *str1,
2275 const xmlChar *str2,
2276 const xmlChar *str3)
2277{
2278 xmlChar *des = NULL, *msg = NULL;
2279
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002280 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002281 msg = xmlStrdup(BAD_CAST "%s: ");
2282 msg = xmlStrcat(msg, (const xmlChar *) message);
2283 msg = xmlStrcat(msg, BAD_CAST ".\n");
2284 if ((itemElem == NULL) && (item != NULL))
2285 itemElem = item->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002286 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002287 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2288 if (itemDes == NULL)
2289 FREE_AND_NULL(des);
2290 FREE_AND_NULL(msg);
2291}
2292
William M. Brack2f2a6632004-08-20 23:09:47 +00002293/**
2294 * xmlSchemaPCustomErr:
2295 * @ctxt: the schema parser context
2296 * @error: the error code
2297 * @itemDes: the designation of the schema item
2298 * @item: the schema item
2299 * @itemElem: the node of the schema item
2300 * @message: the error message
2301 * @str1: the optional param for the error message
2302 *
2303 * Reports an error during parsing.
2304 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002305static void
2306xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002307 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002308 xmlChar **itemDes,
2309 xmlSchemaTypePtr item,
2310 xmlNodePtr itemElem,
2311 const char *message,
2312 const xmlChar *str1)
2313{
2314 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
2315 str1, NULL, NULL);
2316}
2317
William M. Brack2f2a6632004-08-20 23:09:47 +00002318/**
2319 * xmlSchemaPAttrUseErr:
2320 * @ctxt: the schema parser context
2321 * @error: the error code
2322 * @itemDes: the designation of the schema type
2323 * @item: the schema type
2324 * @itemElem: the node of the schema type
2325 * @attr: the invalid schema attribute
2326 * @message: the error message
2327 * @str1: the optional param for the error message
2328 *
2329 * Reports an attribute use error during parsing.
2330 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002331static void
2332xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002333 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002334 xmlSchemaTypePtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002335 const xmlSchemaAttributePtr attr,
2336 const char *message,
2337 const xmlChar *str1)
2338{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002339 xmlChar *str = NULL, *msg = NULL;
2340 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2341 msg = xmlStrcat(msg, BAD_CAST ", ");
2342 msg = xmlStrcat(msg,
2343 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2344 (xmlSchemaTypePtr) attr, NULL));
2345 FREE_AND_NULL(str);
2346 msg = xmlStrcat(msg, BAD_CAST ": ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002347 msg = xmlStrcat(msg, (const xmlChar *) message);
2348 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002349 xmlSchemaPErr(ctxt, attr->node, error,
2350 (const char *) msg, str1, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002351 xmlFree(msg);
2352}
2353
William M. Brack2f2a6632004-08-20 23:09:47 +00002354/**
2355 * xmlSchemaPIllegalFacetAtomicErr:
2356 * @ctxt: the schema parser context
2357 * @error: the error code
2358 * @itemDes: the designation of the type
2359 * @item: the schema type
2360 * @baseItem: the base type of type
2361 * @facet: the illegal facet
2362 *
2363 * Reports an illegal facet for atomic simple types.
2364 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002365static void
2366xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002367 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002368 xmlChar **itemDes,
2369 xmlSchemaTypePtr item,
2370 xmlSchemaTypePtr baseItem,
2371 xmlSchemaFacetPtr facet)
2372{
2373 xmlChar *des = NULL, *strT = NULL;
2374
2375 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2376 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
2377 "%s: The facet '%s' is not allowed on types derived from the "
2378 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002379 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002380 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002381 NULL, NULL);
2382 if (itemDes == NULL)
2383 FREE_AND_NULL(des);
2384 FREE_AND_NULL(strT);
2385}
2386
William M. Brack2f2a6632004-08-20 23:09:47 +00002387/**
2388 * xmlSchemaPIllegalFacetListUnionErr:
2389 * @ctxt: the schema parser context
2390 * @error: the error code
2391 * @itemDes: the designation of the schema item involved
2392 * @item: the schema item involved
2393 * @facet: the illegal facet
2394 *
2395 * Reports an illegal facet for <list> and <union>.
2396 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002397static void
2398xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002399 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002400 xmlChar **itemDes,
2401 xmlSchemaTypePtr item,
2402 xmlSchemaFacetPtr facet)
2403{
2404 xmlChar *des = NULL, *strT = NULL;
2405
2406 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002407 xmlSchemaPErr(ctxt, item->node, error,
2408 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002409 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002410 if (itemDes == NULL)
2411 FREE_AND_NULL(des);
2412 FREE_AND_NULL(strT);
2413}
2414
2415/**
2416 * xmlSchemaPMutualExclAttrErr:
2417 * @ctxt: the schema validation context
2418 * @error: the error code
2419 * @elemDes: the designation of the parent element node
2420 * @attr: the bad attribute node
2421 * @type: the corresponding type of the attribute node
2422 *
2423 * Reports an illegal attribute.
2424 */
2425static void
2426xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
2427 xmlParserErrors error,
2428 xmlChar **ownerDes,
2429 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002430 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002431 const char *name1,
2432 const char *name2)
2433{
2434 xmlChar *des = NULL;
2435
2436 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002437 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002438 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002439 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002440 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002441 } else
2442 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002443 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002444 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002445 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
2446 if (ownerDes == NULL)
2447 FREE_AND_NULL(des)
2448}
2449
2450/**
2451 * xmlSchemaPSimpleTypeErr:
2452 * @ctxt: the schema validation context
2453 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002454 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00002455 * @ownerDes: the designation of the owner
2456 * @ownerItem: the schema object if existent
2457 * @node: the validated node
2458 * @value: the validated value
2459 *
2460 * Reports a simple type validation error.
2461 * TODO: Should this report the value of an element as well?
2462 */
2463static void
2464xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
2465 xmlParserErrors error,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002466 xmlSchemaTypePtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002467 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00002468 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002469 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002470 const xmlChar *value,
2471 const char *message,
2472 const xmlChar *str1,
2473 const xmlChar *str2)
2474{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002475 xmlChar *msg = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002476
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002477 xmlSchemaFormatNodeForError(&msg, (xmlSchemaAbstractCtxtPtr) ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002478 if (message == NULL) {
2479 /*
2480 * Use default messages.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002481 */
2482 if (type != NULL) {
2483 if (node->type == XML_ATTRIBUTE_NODE)
2484 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2485 else
2486 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
2487 "valid value of ");
2488 if (! xmlSchemaIsGlobalItem(type))
2489 msg = xmlStrcat(msg, BAD_CAST "the local ");
2490 else
2491 msg = xmlStrcat(msg, BAD_CAST "the ");
2492
2493 if (VARIETY_ATOMIC(type))
2494 msg = xmlStrcat(msg, BAD_CAST "atomic type");
2495 else if (VARIETY_LIST(type))
2496 msg = xmlStrcat(msg, BAD_CAST "list type");
2497 else if (VARIETY_UNION(type))
2498 msg = xmlStrcat(msg, BAD_CAST "union type");
2499
2500 if (xmlSchemaIsGlobalItem(type)) {
2501 xmlChar *str = NULL;
2502 msg = xmlStrcat(msg, BAD_CAST " '");
2503 if (type->builtInType != 0) {
2504 msg = xmlStrcat(msg, BAD_CAST "xs:");
2505 msg = xmlStrcat(msg, type->name);
2506 } else
2507 msg = xmlStrcat(msg,
2508 xmlSchemaFormatQName(&str,
2509 type->targetNamespace, type->name));
2510 msg = xmlStrcat(msg, BAD_CAST "'.");
2511 FREE_AND_NULL(str);
2512 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00002513 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002514 if (node->type == XML_ATTRIBUTE_NODE)
2515 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
2516 else
2517 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
2518 "valid.");
2519 }
2520 if (expected) {
2521 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
2522 msg = xmlStrcat(msg, BAD_CAST expected);
2523 msg = xmlStrcat(msg, BAD_CAST "'.\n");
2524 } else
2525 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002526 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002527 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
2528 else
2529 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
2530 } else {
2531 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2532 "%s%s.\n", msg, BAD_CAST message, str1, str2, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002533 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002534 /* Cleanup. */
2535 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002536}
2537
William M. Brack2f2a6632004-08-20 23:09:47 +00002538/**
2539 * xmlSchemaPContentErr:
2540 * @ctxt: the schema parser context
2541 * @error: the error code
2542 * @onwerDes: the designation of the holder of the content
2543 * @ownerItem: the owner item of the holder of the content
2544 * @ownerElem: the node of the holder of the content
2545 * @child: the invalid child node
2546 * @message: the optional error message
2547 * @content: the optional string describing the correct content
2548 *
2549 * Reports an error concerning the content of a schema element.
2550 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002551static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002552xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002553 xmlParserErrors error,
2554 xmlChar **ownerDes,
2555 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002556 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002557 xmlNodePtr child,
2558 const char *message,
2559 const char *content)
2560{
2561 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002562
Daniel Veillardc0826a72004-08-10 14:17:33 +00002563 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002564 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002565 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002566 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002567 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002568 } else
2569 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002570 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002571 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2572 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002573 BAD_CAST des, BAD_CAST message);
2574 else {
2575 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002576 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2577 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002578 BAD_CAST des, BAD_CAST content);
2579 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002580 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2581 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002582 BAD_CAST des, NULL);
2583 }
2584 }
2585 if (ownerDes == NULL)
2586 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002587}
2588
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002589/************************************************************************
2590 * *
2591 * Streamable error functions *
2592 * *
2593 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002594
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002595
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002596
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002597
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002598/************************************************************************
2599 * *
2600 * Validation helper functions *
2601 * *
2602 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002603
Daniel Veillardc0826a72004-08-10 14:17:33 +00002604
Daniel Veillard4255d502002-04-16 15:50:10 +00002605/************************************************************************
2606 * *
2607 * Allocation functions *
2608 * *
2609 ************************************************************************/
2610
2611/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002612 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002613 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002614 *
2615 * Allocate a new Schema structure.
2616 *
2617 * Returns the newly allocated structure or NULL in case or error
2618 */
2619static xmlSchemaPtr
2620xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2621{
2622 xmlSchemaPtr ret;
2623
2624 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2625 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002626 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002627 return (NULL);
2628 }
2629 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002630 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002631 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002632
2633 return (ret);
2634}
2635
2636/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002637 * xmlSchemaNewSchema:
2638 * @ctxt: a schema validation context
2639 *
2640 * Allocate a new Schema structure.
2641 *
2642 * Returns the newly allocated structure or NULL in case or error
2643 */
2644static xmlSchemaAssemblePtr
2645xmlSchemaNewAssemble(void)
2646{
2647 xmlSchemaAssemblePtr ret;
2648
2649 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2650 if (ret == NULL) {
2651 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2652 return (NULL);
2653 }
2654 memset(ret, 0, sizeof(xmlSchemaAssemble));
2655 ret->items = NULL;
2656 return (ret);
2657}
2658
2659/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002660 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002661 *
2662 * Allocate a new Facet structure.
2663 *
2664 * Returns the newly allocated structure or NULL in case or error
2665 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002666xmlSchemaFacetPtr
2667xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002668{
2669 xmlSchemaFacetPtr ret;
2670
2671 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2672 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002673 return (NULL);
2674 }
2675 memset(ret, 0, sizeof(xmlSchemaFacet));
2676
2677 return (ret);
2678}
2679
2680/**
2681 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002682 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002683 * @node: a node
2684 *
2685 * Allocate a new annotation structure.
2686 *
2687 * Returns the newly allocated structure or NULL in case or error
2688 */
2689static xmlSchemaAnnotPtr
2690xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2691{
2692 xmlSchemaAnnotPtr ret;
2693
2694 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2695 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002696 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002697 return (NULL);
2698 }
2699 memset(ret, 0, sizeof(xmlSchemaAnnot));
2700 ret->content = node;
2701 return (ret);
2702}
2703
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002704static xmlSchemaItemListPtr
2705xmlSchemaNewItemList(void)
2706{
2707 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002708
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002709 ret = xmlMalloc(sizeof(xmlSchemaItemList));
2710 if (ret == NULL) {
2711 xmlSchemaPErrMemory(NULL,
2712 "allocating an item list structure", NULL);
2713 return (NULL);
2714 }
2715 memset(ret, 0, sizeof(xmlSchemaItemList));
2716 return (ret);
2717}
2718
2719/**
2720 * xmlSchemaAddElementSubstitutionMember:
2721 * @pctxt: a schema parser context
2722 * @head: the head of the substitution group
2723 * @member: the new member of the substitution group
2724 *
2725 * Allocate a new annotation structure.
2726 *
2727 * Returns the newly allocated structure or NULL in case or error
2728 */
2729static int
2730xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
2731 xmlSchemaElementPtr head,
2732 xmlSchemaElementPtr member)
2733{
2734 xmlSchemaSubstGroupPtr substGroup;
2735
2736 if (pctxt == NULL)
2737 return (-1);
2738
2739 if (pctxt->substGroups == NULL) {
2740 pctxt->substGroups = xmlHashCreateDict(10, pctxt->dict);
2741 if (pctxt->substGroups == NULL)
2742 return (-1);
2743 }
2744 substGroup = xmlHashLookup2(pctxt->substGroups, head->name,
2745 head->targetNamespace);
2746 if (substGroup == NULL) {
2747 int res;
2748
2749 substGroup = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
2750 if (substGroup == NULL) {
2751 xmlSchemaPErrMemory(NULL,
2752 "xmlSchemaAddElementSubstitution, allocating a substitution "
2753 "group container",
2754 NULL);
2755 return (-1);
2756 }
2757 substGroup->members = xmlSchemaNewItemList();
2758 if (substGroup->members == NULL) {
2759 xmlFree(substGroup);
2760 return (-1);
2761 }
2762 substGroup->head = head;
2763
2764 res = xmlHashAddEntry2(pctxt->substGroups,
2765 head->name, head->targetNamespace, substGroup);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002766 if (res != 0) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002767 xmlFree(substGroup->members);
2768 xmlFree(substGroup);
2769 xmlSchemaPErr(pctxt, member->node,
2770 XML_SCHEMAP_INTERNAL,
2771 "Internal error: xmlSchemaAddElementSubstitution, "
2772 "failed to add a new substitution group container for "
2773 "'%s'.\n", head->name, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002774 return (-1);
2775 }
2776 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002777 if (substGroup->members->items == NULL) {
2778 substGroup->members->items = (void **) xmlMalloc(
2779 5 * sizeof(xmlSchemaElementPtr));
2780 if (substGroup->members->items == NULL) {
2781 xmlSchemaPErrMemory(NULL,
2782 "allocating list of substitution group members", NULL);
2783 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002784 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002785 substGroup->members->sizeItems = 5;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002786 } else if (substGroup->members->sizeItems <=
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002787 substGroup->members->nbItems) {
2788 substGroup->members->sizeItems *= 2;
2789 substGroup->members->items = (void **) xmlRealloc(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002790 substGroup->members->items,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002791 substGroup->members->sizeItems * sizeof(xmlSchemaElementPtr));
2792 if (substGroup->members->items == NULL) {
2793 xmlSchemaPErrMemory(NULL,
2794 "re-allocating list of substitution group members", NULL);
2795 substGroup->members->sizeItems = 0;
2796 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002797 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002798 }
2799 ((xmlSchemaElementPtr *) substGroup->members->items)
2800 [substGroup->members->nbItems++] = (void *) member;
2801 return (0);
2802}
2803
2804/**
2805 * xmlSchemaGetElementSubstitutionGroup:
2806 * @pctxt: a schema parser context
2807 * @head: the head of the substitution group
2808 * @member: the new member of the substitution group
2809 *
2810 * Allocate a new annotation structure.
2811 *
2812 * Returns the newly allocated structure or NULL in case or error
2813 */
2814static xmlSchemaSubstGroupPtr
2815xmlSchemaGetElementSubstitutionGroup(xmlSchemaParserCtxtPtr pctxt,
2816 xmlSchemaElementPtr head)
2817{
2818 if (pctxt == NULL)
2819 return (NULL);
2820
2821 if (pctxt->substGroups == NULL)
2822 return (NULL);
2823
2824 return ((xmlSchemaSubstGroupPtr) xmlHashLookup2(pctxt->substGroups,
2825 head->name, head->targetNamespace));
2826}
2827
2828/**
2829 * xmlSchemaFreeItemList:
2830 * @annot: a schema type structure
2831 *
2832 * Deallocate a annotation structure
2833 */
2834static void
2835xmlSchemaFreeItemList(xmlSchemaItemListPtr list)
2836{
2837 if (list == NULL)
2838 return;
2839 if (list->items != NULL)
2840 xmlFree(list->items);
2841 xmlFree(list);
2842}
2843
Daniel Veillard4255d502002-04-16 15:50:10 +00002844/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002845 * xmlSchemaFreeAnnot:
2846 * @annot: a schema type structure
2847 *
2848 * Deallocate a annotation structure
2849 */
2850static void
2851xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2852{
2853 if (annot == NULL)
2854 return;
2855 xmlFree(annot);
2856}
2857
2858/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002859 * xmlSchemaFreeImport:
2860 * @import: a schema import structure
2861 *
2862 * Deallocate an import structure
2863 */
2864static void
2865xmlSchemaFreeImport(xmlSchemaImportPtr import)
2866{
2867 if (import == NULL)
2868 return;
2869
2870 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002871 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002872 xmlFree(import);
2873}
2874
2875/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002876 * xmlSchemaFreeInclude:
2877 * @include: a schema include structure
2878 *
2879 * Deallocate an include structure
2880 */
2881static void
2882xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2883{
2884 if (include == NULL)
2885 return;
2886
2887 xmlFreeDoc(include->doc);
2888 xmlFree(include);
2889}
2890
2891/**
2892 * xmlSchemaFreeIncludeList:
2893 * @includes: a schema include list
2894 *
2895 * Deallocate an include structure
2896 */
2897static void
2898xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2899{
2900 xmlSchemaIncludePtr next;
2901
2902 while (includes != NULL) {
2903 next = includes->next;
2904 xmlSchemaFreeInclude(includes);
2905 includes = next;
2906 }
2907}
2908
2909/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002910 * xmlSchemaFreeNotation:
2911 * @schema: a schema notation structure
2912 *
2913 * Deallocate a Schema Notation structure.
2914 */
2915static void
2916xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2917{
2918 if (nota == NULL)
2919 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002920 xmlFree(nota);
2921}
2922
2923/**
2924 * xmlSchemaFreeAttribute:
2925 * @schema: a schema attribute structure
2926 *
2927 * Deallocate a Schema Attribute structure.
2928 */
2929static void
2930xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2931{
2932 if (attr == NULL)
2933 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002934 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002935 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002936 if (attr->defVal != NULL)
2937 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002938 xmlFree(attr);
2939}
2940
2941/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002942 * xmlSchemaFreeWildcardNsSet:
2943 * set: a schema wildcard namespace
2944 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002945 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002946 */
2947static void
2948xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2949{
2950 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002951
Daniel Veillard3646d642004-06-02 19:19:14 +00002952 while (set != NULL) {
2953 next = set->next;
2954 xmlFree(set);
2955 set = next;
2956 }
2957}
2958
2959/**
2960 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002961 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002962 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002963 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002964 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002965void
Daniel Veillard3646d642004-06-02 19:19:14 +00002966xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2967{
2968 if (wildcard == NULL)
2969 return;
2970 if (wildcard->annot != NULL)
2971 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002972 if (wildcard->nsSet != NULL)
2973 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2974 if (wildcard->negNsSet != NULL)
2975 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00002976 xmlFree(wildcard);
2977}
2978
2979/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002980 * xmlSchemaFreeAttributeGroup:
2981 * @schema: a schema attribute group structure
2982 *
2983 * Deallocate a Schema Attribute Group structure.
2984 */
2985static void
2986xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2987{
2988 if (attr == NULL)
2989 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002990 if (attr->annot != NULL)
2991 xmlSchemaFreeAnnot(attr->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002992 xmlFree(attr);
2993}
2994
2995/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002996 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002997 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00002998 *
2999 * Deallocate a list of schema attribute uses.
3000 */
3001static void
3002xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
3003{
3004 xmlSchemaAttributeLinkPtr next;
3005
3006 while (attrUse != NULL) {
3007 next = attrUse->next;
3008 xmlFree(attrUse);
3009 attrUse = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003010 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003011}
3012
3013/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003014 * xmlSchemaFreeQNameRef:
3015 * @item: a QName reference structure
3016 *
3017 * Deallocatea a QName reference structure.
3018 */
3019static void
3020xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3021{
3022 xmlFree(item);
3023}
3024
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003025/**
3026 * xmlSchemaFreeQNameRef:
3027 * @item: a QName reference structure
3028 *
3029 * Deallocatea a QName reference structure.
3030 */
3031static void
3032xmlSchemaFreeSubstGroup(xmlSchemaSubstGroupPtr item)
3033{
3034 if (item == NULL)
3035 return;
3036 if (item->members != NULL)
3037 xmlSchemaFreeItemList(item->members);
3038 xmlFree(item);
3039}
3040
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003041static int
3042xmlSchemaAddVolatile(xmlSchemaPtr schema,
3043 xmlSchemaBasicItemPtr item)
3044{
3045 xmlSchemaItemListPtr list;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003046
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003047 if (schema->volatiles == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003048 schema->volatiles = (void *) xmlSchemaNewItemList();
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003049 if (schema->volatiles == NULL) {
3050 xmlSchemaPErrMemory(NULL,
3051 "allocating list of volatiles", NULL);
3052 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003053 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003054 }
3055 list = (xmlSchemaItemListPtr) schema->volatiles;
3056 if (list->items == NULL) {
3057 list->items = (void **) xmlMalloc(
3058 20 * sizeof(xmlSchemaBasicItemPtr));
3059 if (list->items == NULL) {
3060 xmlSchemaPErrMemory(NULL,
3061 "allocating new volatile item buffer", NULL);
3062 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003063 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003064 list->sizeItems = 20;
3065 } else if (list->sizeItems <= list->nbItems) {
3066 list->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003067 list->items = (void **) xmlRealloc(list->items,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003068 list->sizeItems * sizeof(xmlSchemaTypePtr));
3069 if (list->items == NULL) {
3070 xmlSchemaPErrMemory(NULL,
3071 "growing volatile item buffer", NULL);
3072 list->sizeItems = 0;
3073 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003074 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003075 }
3076 ((xmlSchemaBasicItemPtr *) list->items)[list->nbItems++] = (void *) item;
3077 return (0);
3078}
3079
3080/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003081 * xmlSchemaFreeTypeLinkList:
3082 * @alink: a type link
3083 *
3084 * Deallocate a list of types.
3085 */
3086static void
3087xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3088{
3089 xmlSchemaTypeLinkPtr next;
3090
3091 while (link != NULL) {
3092 next = link->next;
3093 xmlFree(link);
3094 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003095 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003096}
3097
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003098static void
3099xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3100{
3101 xmlSchemaIDCStateObjPtr next;
3102 while (sto != NULL) {
3103 next = sto->next;
3104 if (sto->history != NULL)
3105 xmlFree(sto->history);
3106 if (sto->xpathCtxt != NULL)
3107 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3108 xmlFree(sto);
3109 sto = next;
3110 }
3111}
3112
3113/**
3114 * xmlSchemaFreeIDC:
3115 * @idc: a identity-constraint definition
3116 *
3117 * Deallocates an identity-constraint definition.
3118 */
3119static void
3120xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3121{
3122 xmlSchemaIDCSelectPtr cur, prev;
3123
3124 if (idcDef == NULL)
3125 return;
3126 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003127 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003128 /* Selector */
3129 if (idcDef->selector != NULL) {
3130 if (idcDef->selector->xpathComp != NULL)
3131 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3132 xmlFree(idcDef->selector);
3133 }
3134 /* Fields */
3135 if (idcDef->fields != NULL) {
3136 cur = idcDef->fields;
3137 do {
3138 prev = cur;
3139 cur = cur->next;
3140 if (prev->xpathComp != NULL)
3141 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003142 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003143 } while (cur != NULL);
3144 }
3145 xmlFree(idcDef);
3146}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003147
Daniel Veillard01fa6152004-06-29 17:04:39 +00003148/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003149 * xmlSchemaFreeElement:
3150 * @schema: a schema element structure
3151 *
3152 * Deallocate a Schema Element structure.
3153 */
3154static void
3155xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3156{
3157 if (elem == NULL)
3158 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003159 if (elem->annot != NULL)
3160 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003161 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003162 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003163 if (elem->defVal != NULL)
3164 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003165 xmlFree(elem);
3166}
3167
3168/**
3169 * xmlSchemaFreeFacet:
3170 * @facet: a schema facet structure
3171 *
3172 * Deallocate a Schema Facet structure.
3173 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003174void
Daniel Veillard4255d502002-04-16 15:50:10 +00003175xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3176{
3177 if (facet == NULL)
3178 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003179 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003180 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003181 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003182 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003183 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003184 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003185 xmlFree(facet);
3186}
3187
3188/**
3189 * xmlSchemaFreeType:
3190 * @type: a schema type structure
3191 *
3192 * Deallocate a Schema Type structure.
3193 */
3194void
3195xmlSchemaFreeType(xmlSchemaTypePtr type)
3196{
3197 if (type == NULL)
3198 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003199 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003200 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003201 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003202 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003203
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003204 facet = type->facets;
3205 while (facet != NULL) {
3206 next = facet->next;
3207 xmlSchemaFreeFacet(facet);
3208 facet = next;
3209 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003210 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003211 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3212 if (type->attributeUses != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003213 xmlSchemaFreeAttributeUseList(type->attributeUses);
Daniel Veillard3646d642004-06-02 19:19:14 +00003214 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003215 if (type->memberTypes != NULL)
3216 xmlSchemaFreeTypeLinkList(type->memberTypes);
3217 if (type->facetSet != NULL) {
3218 xmlSchemaFacetLinkPtr next, link;
3219
3220 link = type->facetSet;
3221 do {
3222 next = link->next;
3223 xmlFree(link);
3224 link = next;
3225 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003226 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003227 if (type->contModel != NULL)
3228 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003229 xmlFree(type);
3230}
3231
3232/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003233 * xmlSchemaFreeModelGroupDef:
3234 * @item: a schema model group definition
3235 *
3236 * Deallocates a schema model group definition.
3237 */
3238static void
3239xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3240{
3241 if (item->annot != NULL)
3242 xmlSchemaFreeAnnot(item->annot);
3243 xmlFree(item);
3244}
3245
3246/**
3247 * xmlSchemaFreeModelGroup:
3248 * @item: a schema model group
3249 *
3250 * Deallocates a schema model group structure.
3251 */
3252static void
3253xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3254{
3255 if (item->annot != NULL)
3256 xmlSchemaFreeAnnot(item->annot);
3257 xmlFree(item);
3258}
3259
3260/**
3261 * xmlSchemaFreeParticle:
3262 * @type: a schema type structure
3263 *
3264 * Deallocate a Schema Type structure.
3265 */
3266static void
3267xmlSchemaFreeParticle(xmlSchemaParticlePtr item)
3268{
3269 if (item->annot != NULL)
3270 xmlSchemaFreeAnnot(item->annot);
3271 xmlFree(item);
3272}
3273
3274/**
3275 * xmlSchemaFreeMiscComponents:
3276 * @item: a schema component
3277 *
3278 * Deallocates misc. schema component structures.
3279 */
3280static void
3281xmlSchemaFreeMiscComponents(xmlSchemaTreeItemPtr item)
3282{
3283 if (item == NULL)
3284 return;
3285 switch (item->type) {
3286 case XML_SCHEMA_TYPE_PARTICLE:
3287 xmlSchemaFreeParticle((xmlSchemaParticlePtr) item);
3288 return;
3289 case XML_SCHEMA_TYPE_SEQUENCE:
3290 case XML_SCHEMA_TYPE_CHOICE:
3291 case XML_SCHEMA_TYPE_ALL:
3292 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
3293 return;
3294 case XML_SCHEMA_TYPE_ANY:
3295 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
3296 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
3297 break;
3298 default:
3299 /* TODO: This should never be hit. */
3300 TODO
3301 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003302 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003303}
3304
3305static void
3306xmlSchemaFreeVolatiles(xmlSchemaPtr schema)
3307{
3308 if (schema->volatiles == NULL)
3309 return;
3310 {
3311 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->volatiles;
3312 xmlSchemaTreeItemPtr item;
3313 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003314
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003315 for (i = 0; i < list->nbItems; i++) {
3316 if (list->items[i] != NULL) {
3317 item = (xmlSchemaTreeItemPtr) list->items[i];
3318 switch (item->type) {
3319 case XML_SCHEMA_EXTRA_QNAMEREF:
3320 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
3321 break;
3322 default:
3323 xmlSchemaFreeMiscComponents(item);
3324 }
3325 }
3326 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003327 xmlSchemaFreeItemList(list);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003328 }
3329}
3330/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003331 * xmlSchemaFreeTypeList:
3332 * @type: a schema type structure
3333 *
3334 * Deallocate a Schema Type structure.
3335 */
3336static void
3337xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
3338{
3339 xmlSchemaTypePtr next;
3340
3341 while (type != NULL) {
3342 next = type->redef;
3343 xmlSchemaFreeType(type);
3344 type = next;
3345 }
3346}
3347
3348/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003349 * xmlSchemaFree:
3350 * @schema: a schema structure
3351 *
3352 * Deallocate a Schema structure.
3353 */
3354void
3355xmlSchemaFree(xmlSchemaPtr schema)
3356{
3357 if (schema == NULL)
3358 return;
3359
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003360 if (schema->volatiles != NULL)
3361 xmlSchemaFreeVolatiles(schema);
Daniel Veillard4255d502002-04-16 15:50:10 +00003362 if (schema->notaDecl != NULL)
3363 xmlHashFree(schema->notaDecl,
3364 (xmlHashDeallocator) xmlSchemaFreeNotation);
3365 if (schema->attrDecl != NULL)
3366 xmlHashFree(schema->attrDecl,
3367 (xmlHashDeallocator) xmlSchemaFreeAttribute);
3368 if (schema->attrgrpDecl != NULL)
3369 xmlHashFree(schema->attrgrpDecl,
3370 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
3371 if (schema->elemDecl != NULL)
3372 xmlHashFree(schema->elemDecl,
3373 (xmlHashDeallocator) xmlSchemaFreeElement);
3374 if (schema->typeDecl != NULL)
3375 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003376 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003377 if (schema->groupDecl != NULL)
3378 xmlHashFree(schema->groupDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003379 (xmlHashDeallocator) xmlSchemaFreeModelGroupDef);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003380 if (schema->idcDef != NULL)
3381 xmlHashFree(schema->idcDef,
3382 (xmlHashDeallocator) xmlSchemaFreeIDC);
Daniel Veillard1d913862003-11-21 00:28:39 +00003383 if (schema->schemasImports != NULL)
3384 xmlHashFree(schema->schemasImports,
3385 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003386 if (schema->includes != NULL) {
3387 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
3388 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003389 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003390 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00003391 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003392 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003393 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003394 xmlFree(schema);
3395}
3396
3397/************************************************************************
3398 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00003399 * Debug functions *
3400 * *
3401 ************************************************************************/
3402
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003403#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003404
Daniel Veillard4255d502002-04-16 15:50:10 +00003405/**
3406 * xmlSchemaElementDump:
3407 * @elem: an element
3408 * @output: the file output
3409 *
3410 * Dump the element
3411 */
3412static void
3413xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003414 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003415 const xmlChar * namespace ATTRIBUTE_UNUSED,
3416 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003417{
3418 if (elem == NULL)
3419 return;
3420
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003421 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
3422 fprintf(output, "Particle: %s", name);
3423 fprintf(output, ", term element: %s", elem->ref);
3424 if (elem->refNs != NULL)
3425 fprintf(output, " ns %s", elem->refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003426 } else {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003427 fprintf(output, "Element");
3428 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
3429 fprintf(output, " (global)");
3430 fprintf(output, ": %s ", elem->name);
3431 if (namespace != NULL)
3432 fprintf(output, "ns %s", namespace);
3433 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003434 fprintf(output, "\n");
3435 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003436 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003437 if (elem->maxOccurs >= UNBOUNDED)
3438 fprintf(output, "max: unbounded\n");
3439 else if (elem->maxOccurs != 1)
3440 fprintf(output, "max: %d\n", elem->maxOccurs);
3441 else
3442 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003443 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003444 /*
3445 * Misc other properties.
3446 */
3447 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
3448 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
3449 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
3450 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
3451 (elem->id != NULL)) {
3452 fprintf(output, " props: ");
3453 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
3454 fprintf(output, "[fixed] ");
3455 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
3456 fprintf(output, "[default] ");
3457 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
3458 fprintf(output, "[abstract] ");
3459 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
3460 fprintf(output, "[nillable] ");
3461 if (elem->id != NULL)
3462 fprintf(output, "[id: '%s'] ", elem->id);
3463 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003464 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003465 /*
3466 * Default/fixed value.
3467 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003468 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003469 fprintf(output, " value: '%s'\n", elem->value);
3470 /*
3471 * Type.
3472 */
3473 if (elem->namedType != NULL) {
3474 fprintf(output, " type: %s ", elem->namedType);
3475 if (elem->namedTypeNs != NULL)
3476 fprintf(output, "ns %s\n", elem->namedTypeNs);
3477 else
3478 fprintf(output, "\n");
3479 }
3480 /*
3481 * Substitution group.
3482 */
3483 if (elem->substGroup != NULL) {
3484 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
3485 if (elem->substGroupNs != NULL)
3486 fprintf(output, "ns %s\n", elem->substGroupNs);
3487 else
3488 fprintf(output, "\n");
3489 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003490}
3491
3492/**
3493 * xmlSchemaAnnotDump:
3494 * @output: the file output
3495 * @annot: a annotation
3496 *
3497 * Dump the annotation
3498 */
3499static void
3500xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
3501{
3502 xmlChar *content;
3503
3504 if (annot == NULL)
3505 return;
3506
3507 content = xmlNodeGetContent(annot->content);
3508 if (content != NULL) {
3509 fprintf(output, " Annot: %s\n", content);
3510 xmlFree(content);
3511 } else
3512 fprintf(output, " Annot: empty\n");
3513}
3514
3515/**
3516 * xmlSchemaTypeDump:
3517 * @output: the file output
3518 * @type: a type structure
3519 *
3520 * Dump a SchemaType structure
3521 */
3522static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003523xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
3524{
3525 xmlChar *str = NULL;
3526 xmlSchemaTreeItemPtr term;
3527 char shift[100];
3528 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003529
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003530 if (particle == NULL)
3531 return;
3532 for (i = 0;((i < depth) && (i < 25));i++)
3533 shift[2 * i] = shift[2 * i + 1] = ' ';
3534 shift[2 * i] = shift[2 * i + 1] = 0;
3535 fprintf(output, shift);
3536 if (particle->children == NULL) {
3537 fprintf(output, "MISSING particle term\n");
3538 return;
3539 }
3540 term = particle->children;
3541 switch (term->type) {
3542 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003543 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003544 ((xmlSchemaElementPtr)term)->targetNamespace,
3545 ((xmlSchemaElementPtr)term)->name));
3546 break;
3547 case XML_SCHEMA_TYPE_SEQUENCE:
3548 fprintf(output, "SEQUENCE");
3549 break;
3550 case XML_SCHEMA_TYPE_CHOICE:
3551 fprintf(output, "CHOICE");
3552 break;
3553 case XML_SCHEMA_TYPE_ALL:
3554 fprintf(output, "ALL");
3555 break;
3556 case XML_SCHEMA_TYPE_ANY:
3557 fprintf(output, "ANY");
3558 break;
3559 default:
3560 fprintf(output, "UNKNOWN\n");
3561 return;
3562 }
3563 if (particle->minOccurs != 1)
3564 fprintf(output, " min: %d", particle->minOccurs);
3565 if (particle->maxOccurs >= UNBOUNDED)
3566 fprintf(output, " max: unbounded");
3567 else if (particle->maxOccurs != 1)
3568 fprintf(output, " max: %d", particle->maxOccurs);
3569 fprintf(output, "\n");
3570 if (((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
3571 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
3572 (term->type == XML_SCHEMA_TYPE_ALL)) &&
3573 (term->children != NULL)) {
3574 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
3575 output, depth +1);
3576 }
3577 if (particle->next != NULL)
3578 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
3579 output, depth);
3580}
3581/**
3582 * xmlSchemaTypeDump:
3583 * @output: the file output
3584 * @type: a type structure
3585 *
3586 * Dump a SchemaType structure
3587 */
3588static void
Daniel Veillard4255d502002-04-16 15:50:10 +00003589xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
3590{
3591 if (type == NULL) {
3592 fprintf(output, "Type: NULL\n");
3593 return;
3594 }
3595 fprintf(output, "Type: ");
3596 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003597 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003598 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003599 fprintf(output, "no name ");
3600 if (type->targetNamespace != NULL)
3601 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003602 switch (type->type) {
3603 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003604 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003605 break;
3606 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003607 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003608 break;
3609 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003610 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003611 break;
3612 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003613 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003614 break;
3615 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003616 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003617 break;
3618 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003619 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003620 break;
3621 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003622 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003623 break;
3624 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003625 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003626 break;
3627 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003628 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003629 break;
3630 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003631 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003632 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003633 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003634 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003635 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003636 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003637 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003638 break;
3639 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003640 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003641 break;
3642 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003643 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003644 break;
3645 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003646 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003647 break;
3648 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003649 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003650 break;
3651 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003652 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003653 break;
3654 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003655 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003656 break;
3657 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003658 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003659 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003660 }
3661 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003662 if (type->base != NULL) {
3663 fprintf(output, " base type: %s", type->base);
3664 if (type->baseNs != NULL)
3665 fprintf(output, " ns %s\n", type->baseNs);
3666 else
3667 fprintf(output, "\n");
3668 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003669 if (type->annot != NULL)
3670 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003671#ifdef DUMP_CONTENT_MODEL
3672 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
3673 (type->subtypes != NULL)) {
3674 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
3675 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003676 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003677#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003678}
3679
3680/**
3681 * xmlSchemaDump:
3682 * @output: the file output
3683 * @schema: a schema structure
3684 *
3685 * Dump a Schema structure.
3686 */
3687void
3688xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3689{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003690 if (output == NULL)
3691 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003692 if (schema == NULL) {
3693 fprintf(output, "Schemas: NULL\n");
3694 return;
3695 }
3696 fprintf(output, "Schemas: ");
3697 if (schema->name != NULL)
3698 fprintf(output, "%s, ", schema->name);
3699 else
3700 fprintf(output, "no name, ");
3701 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00003702 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003703 else
3704 fprintf(output, "no target namespace");
3705 fprintf(output, "\n");
3706 if (schema->annot != NULL)
3707 xmlSchemaAnnotDump(output, schema->annot);
3708
3709 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
3710 output);
3711 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003712 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00003713}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003714
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003715#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003716/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003717 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003718 * @vctxt: the WXS validation context
3719 *
3720 * Displays the current IDC table for debug purposes.
3721 */
3722static void
3723xmlSchemaDebugDumpIDCTable(FILE * output,
3724 const xmlChar *namespaceName,
3725 const xmlChar *localName,
3726 xmlSchemaPSVIIDCBindingPtr bind)
3727{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003728 xmlChar *str = NULL, *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003729 xmlSchemaPSVIIDCNodePtr tab;
3730 xmlSchemaPSVIIDCKeyPtr key;
3731 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003732
3733 fprintf(output, "IDC: TABLES on %s\n",
3734 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003735 FREE_AND_NULL(str)
3736
3737 if (bind == NULL)
3738 return;
3739 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003740 fprintf(output, "IDC: BINDING %s\n",
3741 xmlSchemaFormatQName(&str, bind->definition->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003742 bind->definition->name));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003743 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003744 for (i = 0; i < bind->nbNodes; i++) {
3745 tab = bind->nodeTable[i];
3746 fprintf(output, " ( ");
3747 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003748 key = tab->keys[j];
3749 if ((key != NULL) && (key->val != NULL)) {
3750 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003751 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003752 fprintf(output, "\"%s\" ", value);
3753 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003754 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003755 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003756 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003757 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003758 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003759 else
3760 fprintf(output, "(key missing), ");
3761 }
3762 fprintf(output, ")\n");
3763 }
3764 bind = bind->next;
3765 } while (bind != NULL);
3766}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003767#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003768#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00003769
3770/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003771 * *
3772 * Utilities *
3773 * *
3774 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003775
Daniel Veillardc0826a72004-08-10 14:17:33 +00003776/**
3777 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003778 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003779 * @name: the name of the attribute
3780 *
3781 * Seeks an attribute with a name of @name in
3782 * no namespace.
3783 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003784 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003785 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003786static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003787xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003788{
3789 xmlAttrPtr prop;
3790
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003791 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003792 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003793 prop = node->properties;
3794 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003795 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003796 return(prop);
3797 prop = prop->next;
3798 }
3799 return (NULL);
3800}
3801
3802/**
3803 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003804 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003805 * @uri: the uri
3806 * @name: the name of the attribute
3807 *
3808 * Seeks an attribute with a local name of @name and
3809 * a namespace URI of @uri.
3810 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003811 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003812 */
3813static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003814xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003815{
3816 xmlAttrPtr prop;
3817
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003818 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003819 return(NULL);
3820 prop = node->properties;
3821 while (prop != NULL) {
3822 if ((prop->ns != NULL) &&
3823 xmlStrEqual(prop->name, BAD_CAST name) &&
3824 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003825 return(prop);
3826 prop = prop->next;
3827 }
3828 return (NULL);
3829}
3830
3831static const xmlChar *
3832xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3833{
3834 xmlChar *val;
3835 const xmlChar *ret;
3836
3837 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003838 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00003839 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00003840 ret = xmlDictLookup(ctxt->dict, val, -1);
3841 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003842 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003843}
3844
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003845/**
3846 * xmlSchemaGetProp:
3847 * @ctxt: the parser context
3848 * @node: the node
3849 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003850 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003851 * Read a attribute value and internalize the string
3852 *
3853 * Returns the string or NULL if not present.
3854 */
3855static const xmlChar *
3856xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3857 const char *name)
3858{
3859 xmlChar *val;
3860 const xmlChar *ret;
3861
3862 val = xmlGetProp(node, BAD_CAST name);
3863 if (val == NULL)
3864 return(NULL);
3865 ret = xmlDictLookup(ctxt->dict, val, -1);
3866 xmlFree(val);
3867 return(ret);
3868}
3869
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003870/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003871 * *
3872 * Parsing functions *
3873 * *
3874 ************************************************************************/
3875
3876/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003877 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003878 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003879 * @name: the element name
3880 * @ns: the element namespace
3881 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003882 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003883 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003884 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003885 */
3886static xmlSchemaElementPtr
3887xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003888 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003889{
3890 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003891
3892 if ((name == NULL) || (schema == NULL))
3893 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003894
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003895 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003896 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003897 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003898 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003899 } else
3900 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003901 /*
3902 * This one was removed, since top level element declarations have
3903 * the target namespace specified in targetNamespace of the <schema>
3904 * information element, even if elementFormDefault is "unqualified".
3905 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003906
William M. Bracke7091952004-05-11 15:09:58 +00003907 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003908 if (xmlStrEqual(namespace, schema->targetNamespace))
3909 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3910 else
3911 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003912 if ((ret != NULL) &&
3913 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003914 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003915 }
William M. Bracke7091952004-05-11 15:09:58 +00003916 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003917
William M. Brack2f2a6632004-08-20 23:09:47 +00003918 /*
3919 * Removed since imported components will be hold by the main schema only.
3920 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003921 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003922 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003923 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003924 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003925 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003926 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003927 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3928 return (ret);
3929 } else
3930 ret = NULL;
3931 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003932 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003933#ifdef DEBUG
3934 if (ret == NULL) {
3935 if (namespace == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003936 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003937 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003938 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003939 namespace);
3940 }
3941#endif
3942 return (ret);
3943}
3944
3945/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003946 * xmlSchemaGetType:
3947 * @schema: the schemas context
3948 * @name: the type name
3949 * @ns: the type namespace
3950 *
3951 * Lookup a type in the schemas or the predefined types
3952 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003953 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00003954 */
3955static xmlSchemaTypePtr
3956xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003957 const xmlChar * namespace)
3958{
Daniel Veillard4255d502002-04-16 15:50:10 +00003959 xmlSchemaTypePtr ret;
3960
3961 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003962 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003963 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003964 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003965 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003966 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003967 }
3968 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00003969 if (ret != NULL)
3970 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003971 /*
3972 * Removed, since the imported components will be grafted on the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003973 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00003974 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003975 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003976 else
Daniel Veillard1d913862003-11-21 00:28:39 +00003977 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003978 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003979 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003980 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
3981 return (ret);
3982 } else
3983 ret = NULL;
3984 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003985 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003986#ifdef DEBUG
3987 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003988 if (namespace == NULL)
3989 fprintf(stderr, "Unable to lookup type %s", name);
3990 else
3991 fprintf(stderr, "Unable to lookup type %s:%s", name,
3992 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003993 }
3994#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003995 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003996}
3997
Daniel Veillard3646d642004-06-02 19:19:14 +00003998/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003999 * xmlSchemaGetAttributeDecl:
4000 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004001 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004002 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004003 *
4004 * Lookup a an attribute in the schema or imported schemas
4005 *
4006 * Returns the attribute declaration or NULL if not found.
4007 */
4008static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004009xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillard3646d642004-06-02 19:19:14 +00004010 const xmlChar * namespace)
4011{
4012 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004013
4014 if ((name == NULL) || (schema == NULL))
4015 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004016
4017
Daniel Veillard3646d642004-06-02 19:19:14 +00004018 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
4019 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004020 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004021 else
4022 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004023 /*
4024 * Removed, since imported components will be hold by the main schema only.
4025 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004026 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004027 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004028 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004029 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004030 if (import != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004031 ret = xmlSchemaGetAttributeDecl(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004032 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
4033 return (ret);
4034 } else
4035 ret = NULL;
4036 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004037 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004038#ifdef DEBUG
4039 if (ret == NULL) {
4040 if (namespace == NULL)
4041 fprintf(stderr, "Unable to lookup attribute %s", name);
4042 else
4043 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4044 namespace);
4045 }
4046#endif
4047 return (ret);
4048}
4049
4050/**
4051 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004052 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004053 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004054 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004055 *
4056 * Lookup a an attribute group in the schema or imported schemas
4057 *
4058 * Returns the attribute group definition or NULL if not found.
4059 */
4060static xmlSchemaAttributeGroupPtr
4061xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4062 const xmlChar * namespace)
4063{
4064 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004065
4066 if ((name == NULL) || (schema == NULL))
4067 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004068
4069
Daniel Veillard3646d642004-06-02 19:19:14 +00004070 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
4071 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004072 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004073 else
4074 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004075 /*
4076 * Removed since imported components will be hold by the main schema only.
4077 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004078 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004079 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004080 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004081 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004082 if (import != NULL) {
4083 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
4084 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
4085 return (ret);
4086 else
4087 ret = NULL;
4088 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004089 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004090#ifdef DEBUG
4091 if (ret == NULL) {
4092 if (namespace == NULL)
4093 fprintf(stderr, "Unable to lookup attribute group %s", name);
4094 else
4095 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4096 namespace);
4097 }
4098#endif
4099 return (ret);
4100}
4101
4102/**
4103 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004104 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004105 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004106 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004107 *
4108 * Lookup a group in the schema or imported schemas
4109 *
4110 * Returns the group definition or NULL if not found.
4111 */
4112static xmlSchemaTypePtr
4113xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4114 const xmlChar * namespace)
4115{
4116 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004117
4118 if ((name == NULL) || (schema == NULL))
4119 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004120
Daniel Veillard3646d642004-06-02 19:19:14 +00004121 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
William M. Brack2f2a6632004-08-20 23:09:47 +00004122 /*
4123 * Removed since imported components will be hold by the main schema only.
4124 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004125 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004126 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004127 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004128 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004129 if (import != NULL) {
4130 ret = xmlSchemaGetGroup(import->schema, name, namespace);
4131 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
4132 return (ret);
4133 else
4134 ret = NULL;
4135 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004136 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004137#ifdef DEBUG
4138 if (ret == NULL) {
4139 if (namespace == NULL)
4140 fprintf(stderr, "Unable to lookup group %s", name);
4141 else
4142 fprintf(stderr, "Unable to lookup group %s:%s", name,
4143 namespace);
4144 }
4145#endif
4146 return (ret);
4147}
4148
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004149/**
4150 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004151 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004152 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004153 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004154 *
4155 * Lookup a group in the schema or imported schemas
4156 *
4157 * Returns the group definition or NULL if not found.
4158 */
4159static xmlSchemaTreeItemPtr
4160xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4161 xmlSchemaTypeType itemType,
4162 const xmlChar *name,
4163 const xmlChar *targetNs)
4164{
4165 switch (itemType) {
4166 case XML_SCHEMA_TYPE_GROUP:
4167 return ((xmlSchemaTreeItemPtr) xmlSchemaGetGroup(schema,
4168 name, targetNs));
4169 case XML_SCHEMA_TYPE_ELEMENT:
4170 return ((xmlSchemaTreeItemPtr) xmlSchemaGetElem(schema,
4171 name, targetNs));
4172 default:
4173 return (NULL);
4174 }
4175}
4176
Daniel Veillard4255d502002-04-16 15:50:10 +00004177/************************************************************************
4178 * *
4179 * Parsing functions *
4180 * *
4181 ************************************************************************/
4182
4183#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004184 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00004185
4186/**
4187 * xmlSchemaIsBlank:
4188 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004189 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00004190 *
4191 * Check if a string is ignorable
4192 *
4193 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4194 */
4195static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004196xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004197{
Daniel Veillard4255d502002-04-16 15:50:10 +00004198 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004199 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004200 if (len < 0) {
4201 while (*str != 0) {
4202 if (!(IS_BLANK_CH(*str)))
4203 return (0);
4204 str++;
4205 }
4206 } else while ((*str != 0) && (len != 0)) {
4207 if (!(IS_BLANK_CH(*str)))
4208 return (0);
4209 str++;
4210 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00004211 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004212
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004213 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004214}
4215
4216/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004217 * xmlSchemaAddAssembledItem:
4218 * @ctxt: a schema parser context
4219 * @schema: the schema being built
4220 * @item: the item
4221 *
4222 * Add a item to the schema's list of current items.
4223 * This is used if the schema was already constructed and
4224 * new schemata need to be added to it.
4225 * *WARNING* this interface is highly subject to change.
4226 *
4227 * Returns 0 if suceeds and -1 if an internal error occurs.
4228 */
4229static int
4230xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
4231 xmlSchemaTypePtr item)
4232{
4233 static int growSize = 100;
4234 xmlSchemaAssemblePtr ass;
4235
4236 ass = ctxt->assemble;
4237 if (ass->sizeItems < 0) {
4238 /* If disabled. */
4239 return (0);
4240 }
4241 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004242 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004243 if (ass->items == NULL) {
4244 xmlSchemaPErrMemory(ctxt,
4245 "allocating new item buffer", NULL);
4246 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004247 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004248 ass->sizeItems = growSize;
4249 } else if (ass->sizeItems <= ass->nbItems) {
4250 ass->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004251 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004252 ass->sizeItems * sizeof(xmlSchemaTypePtr));
4253 if (ass->items == NULL) {
4254 xmlSchemaPErrMemory(ctxt,
4255 "growing item buffer", NULL);
4256 ass->sizeItems = 0;
4257 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004258 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004259 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004260 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004261 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
4262 return (0);
4263}
4264
4265/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004266 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004267 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004268 * @schema: the schema being built
4269 * @name: the item name
4270 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004271 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00004272 * *WARNING* this interface is highly subject to change
4273 *
4274 * Returns the new struture or NULL in case of error
4275 */
4276static xmlSchemaNotationPtr
4277xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004278 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004279{
4280 xmlSchemaNotationPtr ret = NULL;
4281 int val;
4282
4283 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4284 return (NULL);
4285
4286 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004287 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004288 if (schema->notaDecl == NULL)
4289 return (NULL);
4290
4291 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
4292 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004293 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004294 return (NULL);
4295 }
4296 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004297 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004298 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
4299 ret);
4300 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004301 /*
4302 * TODO: This should never happen, since a unique name will be computed.
4303 * If it fails, then an other internal error must have occured.
4304 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004305 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
4306 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004307 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004308 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004309 xmlFree(ret);
4310 return (NULL);
4311 }
4312 return (ret);
4313}
4314
4315
4316/**
4317 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004318 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004319 * @schema: the schema being built
4320 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004321 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004322 *
4323 * Add an XML schema Attrribute declaration
4324 * *WARNING* this interface is highly subject to change
4325 *
4326 * Returns the new struture or NULL in case of error
4327 */
4328static xmlSchemaAttributePtr
4329xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004330 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004331 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004332{
4333 xmlSchemaAttributePtr ret = NULL;
4334 int val;
4335
4336 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4337 return (NULL);
4338
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004339#ifdef DEBUG
4340 fprintf(stderr, "Adding attribute %s\n", name);
4341 if (namespace != NULL)
4342 fprintf(stderr, " target namespace %s\n", namespace);
4343#endif
4344
Daniel Veillard4255d502002-04-16 15:50:10 +00004345 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004346 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004347 if (schema->attrDecl == NULL)
4348 return (NULL);
4349
4350 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
4351 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004352 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004353 return (NULL);
4354 }
4355 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004356 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004357 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00004358 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004359 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004360 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004361 if (topLevel) {
4362 xmlSchemaPCustomErr(ctxt,
4363 XML_SCHEMAP_REDEFINED_ATTR,
4364 NULL, NULL, node,
4365 "A global attribute declaration with the name '%s' does "
4366 "already exist", name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004367 xmlFree(ret);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004368 return (NULL);
4369 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004370 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004371 /*
4372 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
4373 * in the scenario:
4374 * 1. multiple top-level complex types have different target
4375 * namespaces but have the SAME NAME; this can happen if
4376 * schemata are imported
4377 * 2. those complex types contain attributes with an equal name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004378 * 3. those attributes are in no namespace
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004379 * We will compute a new context string.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004380 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004381 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004382 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004383 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004384
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004385 if (val != 0) {
4386 xmlSchemaPCustomErr(ctxt,
4387 XML_SCHEMAP_INTERNAL,
4388 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004389 "Internal error: xmlSchemaAddAttribute, "
4390 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004391 "could not be added to the hash.", name);
4392 xmlFree(ret);
4393 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004394 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004395 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004396 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004397 if (ctxt->assemble != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004398 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004399 return (ret);
4400}
4401
4402/**
4403 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004404 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004405 * @schema: the schema being built
4406 * @name: the item name
4407 *
4408 * Add an XML schema Attrribute Group declaration
4409 *
4410 * Returns the new struture or NULL in case of error
4411 */
4412static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004413xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00004414 xmlSchemaPtr schema, const xmlChar * name,
4415 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004416{
4417 xmlSchemaAttributeGroupPtr ret = NULL;
4418 int val;
4419
4420 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4421 return (NULL);
4422
4423 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004424 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004425 if (schema->attrgrpDecl == NULL)
4426 return (NULL);
4427
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004428 ret =
4429 (xmlSchemaAttributeGroupPtr)
4430 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00004431 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004432 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004433 return (NULL);
4434 }
4435 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004436 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004437 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004438 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004439 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004440 xmlSchemaPCustomErr(ctxt,
4441 XML_SCHEMAP_REDEFINED_ATTRGROUP,
4442 NULL, NULL, node,
4443 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004444 xmlFree(ret);
4445 return (NULL);
4446 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004447 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004448 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004449 return (ret);
4450}
4451
4452/**
4453 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004454 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004455 * @schema: the schema being built
4456 * @name: the type name
4457 * @namespace: the type namespace
4458 *
4459 * Add an XML schema Element declaration
4460 * *WARNING* this interface is highly subject to change
4461 *
4462 * Returns the new struture or NULL in case of error
4463 */
4464static xmlSchemaElementPtr
4465xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004466 const xmlChar * name, const xmlChar * namespace,
4467 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004468{
4469 xmlSchemaElementPtr ret = NULL;
4470 int val;
4471
4472 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4473 return (NULL);
4474
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004475#ifdef DEBUG
4476 fprintf(stderr, "Adding element %s\n", name);
4477 if (namespace != NULL)
4478 fprintf(stderr, " target namespace %s\n", namespace);
4479#endif
4480
Daniel Veillard4255d502002-04-16 15:50:10 +00004481 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004482 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004483 if (schema->elemDecl == NULL)
4484 return (NULL);
4485
4486 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
4487 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004488 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004489 return (NULL);
4490 }
4491 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004492 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004493 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004494 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004495 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004496 if (topLevel) {
4497 xmlSchemaPCustomErr(ctxt,
4498 XML_SCHEMAP_REDEFINED_ELEMENT,
4499 NULL, NULL, node,
4500 "A global element declaration with the name '%s' does "
4501 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004502 xmlFree(ret);
4503 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00004504 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004505 char buf[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00004506
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004507 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004508 val = xmlHashAddEntry3(schema->elemDecl, name,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004509 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004510 if (val != 0) {
4511 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004512 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00004513 NULL, NULL, node,
4514 "Internal error: xmlSchemaAddElement, "
4515 "a dublicate element declaration with the name '%s' "
4516 "could not be added to the hash.", name);
4517 xmlFree(ret);
4518 return (NULL);
4519 }
4520 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004521
Daniel Veillard4255d502002-04-16 15:50:10 +00004522 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004523 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004524 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004525 return (ret);
4526}
4527
4528/**
4529 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004530 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004531 * @schema: the schema being built
4532 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004533 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004534 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00004535 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00004536 * *WARNING* this interface is highly subject to change
4537 *
4538 * Returns the new struture or NULL in case of error
4539 */
4540static xmlSchemaTypePtr
4541xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004542 const xmlChar * name, const xmlChar * namespace,
4543 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004544{
4545 xmlSchemaTypePtr ret = NULL;
4546 int val;
4547
4548 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4549 return (NULL);
4550
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004551#ifdef DEBUG
4552 fprintf(stderr, "Adding type %s\n", name);
4553 if (namespace != NULL)
4554 fprintf(stderr, " target namespace %s\n", namespace);
4555#endif
4556
Daniel Veillard4255d502002-04-16 15:50:10 +00004557 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004558 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004559 if (schema->typeDecl == NULL)
4560 return (NULL);
4561
4562 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
4563 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004564 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004565 return (NULL);
4566 }
4567 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004568 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004569 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004570 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004571 if (val != 0) {
4572 if (ctxt->includes == 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004573 xmlSchemaPCustomErr(ctxt,
4574 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004575 NULL, NULL, node,
4576 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004577 xmlFree(ret);
4578 return (NULL);
4579 } else {
4580 xmlSchemaTypePtr prev;
4581
4582 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
4583 if (prev == NULL) {
4584 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004585 XML_ERR_INTERNAL_ERROR,
4586 "Internal error: xmlSchemaAddType, on type "
4587 "'%s'.\n",
4588 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004589 xmlFree(ret);
4590 return (NULL);
4591 }
4592 ret->redef = prev->redef;
4593 prev->redef = ret;
4594 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004595 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004596 ret->node = node;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004597 ret->minOccurs = 1;
4598 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00004599 ret->attributeUses = NULL;
4600 ret->attributeWildcard = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004601 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004602 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004603 return (ret);
4604}
4605
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004606static xmlSchemaQNameRefPtr
4607xmlSchemaNewQNameRef(xmlSchemaPtr schema,
4608 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004609 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004610 const xmlChar *refNs)
4611{
4612 xmlSchemaQNameRefPtr ret;
4613
4614 ret = (xmlSchemaQNameRefPtr)
4615 xmlMalloc(sizeof(xmlSchemaQNameRef));
4616 if (ret == NULL) {
4617 xmlSchemaPErrMemory(NULL, "allocating QName reference item",
4618 NULL);
4619 return (NULL);
4620 }
4621 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
4622 ret->name = refName;
4623 ret->targetNamespace = refNs;
4624 ret->item = NULL;
4625 ret->itemType = refType;
4626 /*
4627 * Store the reference item in the schema.
4628 */
4629 xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret);
4630 return (ret);
4631}
4632
4633/**
4634 * xmlSchemaAddModelGroup:
4635 * @ctxt: a schema parser context
4636 * @schema: the schema being built
4637 * @type: the "compositor" type of the model group
4638 * @container: the internal component name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004639 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004640 *
4641 * Adds a schema model group
4642 * *WARNING* this interface is highly subject to change
4643 *
4644 * Returns the new struture or NULL in case of error
4645 */
4646static xmlSchemaModelGroupPtr
4647xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4648 xmlSchemaTypeType type, const xmlChar **container,
4649 xmlNodePtr node)
4650{
4651 xmlSchemaModelGroupPtr ret = NULL;
4652 xmlChar buf[30];
4653
4654 if ((ctxt == NULL) || (schema == NULL))
4655 return (NULL);
4656
4657#ifdef DEBUG
4658 fprintf(stderr, "Adding model group component\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004659#endif
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004660 ret = (xmlSchemaModelGroupPtr)
4661 xmlMalloc(sizeof(xmlSchemaModelGroup));
4662 if (ret == NULL) {
4663 xmlSchemaPErrMemory(ctxt, "allocating model group component",
4664 NULL);
4665 return (NULL);
4666 }
4667 ret->type = type;
4668 ret->annot = NULL;
4669 ret->node = node;
4670 ret->children = NULL;
4671 ret->next = NULL;
4672 if (type == XML_SCHEMA_TYPE_SEQUENCE) {
4673 if (container != NULL)
4674 snprintf((char *) buf, 29, "#seq%d", ctxt->counter++ + 1);
4675 } else if (type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004676 if (container != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004677 snprintf((char *) buf, 29, "#cho%d", ctxt->counter++ + 1);
4678 } else {
4679 if (container != NULL)
4680 snprintf((char *) buf, 29, "#all%d", ctxt->counter++ + 1);
4681 }
4682 if (container != NULL)
4683 *container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
4684 /*
4685 * Add to volatile items.
4686 * TODO: this should be changed someday.
4687 */
4688 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4689 xmlFree(ret);
4690 return (NULL);
4691 }
4692 return (ret);
4693}
4694
4695
4696/**
4697 * xmlSchemaAddParticle:
4698 * @ctxt: a schema parser context
4699 * @schema: the schema being built
4700 * @node: the corresponding node in the schema doc
4701 * @min: the minOccurs
4702 * @max: the maxOccurs
4703 *
4704 * Adds an XML schema particle component.
4705 * *WARNING* this interface is highly subject to change
4706 *
4707 * Returns the new struture or NULL in case of error
4708 */
4709static xmlSchemaParticlePtr
4710xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4711 xmlNodePtr node, int min, int max)
4712{
4713 xmlSchemaParticlePtr ret = NULL;
4714 if ((ctxt == NULL) || (schema == NULL))
4715 return (NULL);
4716
4717#ifdef DEBUG
4718 fprintf(stderr, "Adding particle component\n");
4719#endif
4720 ret = (xmlSchemaParticlePtr)
4721 xmlMalloc(sizeof(xmlSchemaParticle));
4722 if (ret == NULL) {
4723 xmlSchemaPErrMemory(ctxt, "allocating particle component",
4724 NULL);
4725 return (NULL);
4726 }
4727 ret->type = XML_SCHEMA_TYPE_PARTICLE;
4728 ret->annot = NULL;
4729 ret->node = node;
4730 ret->minOccurs = min;
4731 ret->maxOccurs = max;
4732 ret->next = NULL;
4733 ret->children = NULL;
4734
4735 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4736 xmlFree(ret);
4737 return (NULL);
4738 }
4739 return (ret);
4740}
4741
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004742/**
4743 * xmlSchemaAddGroup:
4744 * @ctxt: a schema validation context
4745 * @schema: the schema being built
4746 * @name: the group name
4747 *
4748 * Add an XML schema Group definition
4749 *
4750 * Returns the new struture or NULL in case of error
4751 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004752static xmlSchemaModelGroupDefPtr
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004753xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004754 const xmlChar *name, const xmlChar *namespaceName,
4755 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004756{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004757 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004758 int val;
4759
4760 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4761 return (NULL);
4762
4763 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004764 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004765 if (schema->groupDecl == NULL)
4766 return (NULL);
4767
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004768 ret = (xmlSchemaModelGroupDefPtr) xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004769 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004770 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004771 return (NULL);
4772 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004773 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004774 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004775 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004776 ret->node = node;
4777 ret->targetNamespace = namespaceName;
4778 val = xmlHashAddEntry2(schema->groupDecl, ret->name, namespaceName, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004779 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004780 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004781 XML_SCHEMAP_REDEFINED_GROUP,
4782 NULL, NULL, node,
4783 "A global model group definition with the name '%s' does already "
4784 "exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004785 xmlFree(ret);
4786 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004787 }
4788 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004789 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004790 return (ret);
4791}
4792
Daniel Veillard3646d642004-06-02 19:19:14 +00004793/**
4794 * xmlSchemaNewWildcardNs:
4795 * @ctxt: a schema validation context
4796 *
4797 * Creates a new wildcard namespace constraint.
4798 *
4799 * Returns the new struture or NULL in case of error
4800 */
4801static xmlSchemaWildcardNsPtr
4802xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
4803{
4804 xmlSchemaWildcardNsPtr ret;
4805
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004806 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004807 xmlMalloc(sizeof(xmlSchemaWildcardNs));
4808 if (ret == NULL) {
4809 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004810 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00004811 }
4812 ret->value = NULL;
4813 ret->next = NULL;
4814 return (ret);
4815}
4816
4817/**
4818 * xmlSchemaAddWildcard:
4819 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004820 * @schema: a schema
4821 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004822 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004823 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00004824 *
4825 * Returns the new struture or NULL in case of error
4826 */
4827static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004828xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4829 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00004830{
4831 xmlSchemaWildcardPtr ret = NULL;
4832
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004833 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00004834 return (NULL);
4835
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004836#ifdef DEBUG
4837 fprintf(stderr, "Adding wildcard component\n");
4838#endif
4839
Daniel Veillard3646d642004-06-02 19:19:14 +00004840 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
4841 if (ret == NULL) {
4842 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
4843 return (NULL);
4844 }
4845 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004846 ret->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +00004847 ret->minOccurs = 1;
4848 ret->maxOccurs = 1;
4849
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004850 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4851 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, NULL, node,
4852 "Failed to add a wildcard component to the list", NULL);
4853 xmlFree(ret);
4854 return (NULL);
4855 }
Daniel Veillard3646d642004-06-02 19:19:14 +00004856 return (ret);
4857}
4858
Daniel Veillard4255d502002-04-16 15:50:10 +00004859/************************************************************************
4860 * *
4861 * Utilities for parsing *
4862 * *
4863 ************************************************************************/
4864
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004865#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004866/**
4867 * xmlGetQNameProp:
4868 * @ctxt: a schema validation context
4869 * @node: a subtree containing XML Schema informations
4870 * @name: the attribute name
4871 * @namespace: the result namespace if any
4872 *
4873 * Extract a QName Attribute value
4874 *
4875 * Returns the NCName or NULL if not found, and also update @namespace
4876 * with the namespace URI
4877 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004878static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00004879xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004880 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004881{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004882 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004883 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004884 const xmlChar *ret, *prefix;
4885 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004886 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004887
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004888 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004889 attr = xmlSchemaGetPropNode(node, name);
4890 if (attr == NULL)
4891 return (NULL);
4892 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004893
Daniel Veillard4255d502002-04-16 15:50:10 +00004894 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004895 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004896
Daniel Veillardba0153a2004-04-01 10:42:31 +00004897 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00004898 ns = xmlSearchNs(node->doc, node, 0);
4899 if (ns) {
4900 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4901 return (val);
4902 }
4903 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004904 ret = xmlSplitQName3(val, &len);
4905 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004906 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004907 }
4908 ret = xmlDictLookup(ctxt->dict, ret, -1);
4909 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00004910
4911 ns = xmlSearchNs(node->doc, node, prefix);
4912 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004913 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
4914 NULL, NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004915 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004916 "The QName value '%s' has no corresponding namespace "
4917 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004918 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004919 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004920 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004921 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004922}
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004923#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004924
4925/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004926 * xmlSchemaPValAttrNodeQNameValue:
4927 * @ctxt: a schema parser context
4928 * @schema: the schema context
4929 * @ownerDes: the designation of the parent element
4930 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004931 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00004932 * @local: the resulting local part if found, the attribute value otherwise
4933 * @uri: the resulting namespace URI if found
4934 *
4935 * Extracts the local name and the URI of a QName value and validates it.
4936 * This one is intended to be used on attribute values that
4937 * should resolve to schema components.
4938 *
4939 * Returns 0, in case the QName is valid, a positive error code
4940 * if not valid and -1 if an internal error occurs.
4941 */
4942static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004943xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004944 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004945 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004946 xmlSchemaTypePtr ownerItem,
4947 xmlAttrPtr attr,
4948 const xmlChar *value,
4949 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004950 const xmlChar **local)
4951{
4952 const xmlChar *pref;
4953 xmlNsPtr ns;
4954 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004955
Daniel Veillardc0826a72004-08-10 14:17:33 +00004956 *uri = NULL;
4957 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004958 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004959 if (ret > 0) {
4960 xmlSchemaPSimpleTypeErr(ctxt,
4961 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4962 ownerItem, (xmlNodePtr) attr,
4963 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
4964 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004965 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004966 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004967 } else if (ret < 0)
4968 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004969
4970 if (!strchr((char *) value, ':')) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004971 ns = xmlSearchNs(attr->doc, attr->parent, 0);
4972 if (ns)
4973 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4974 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
4975 /*
4976 * This one takes care of included schemas with no
4977 * target namespace.
4978 */
4979 *uri = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004980 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004981 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004982 return (0);
4983 }
4984 /*
4985 * At this point xmlSplitQName3 has to return a local name.
4986 */
4987 *local = xmlSplitQName3(value, &len);
4988 *local = xmlDictLookup(ctxt->dict, *local, -1);
4989 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004990 ns = xmlSearchNs(attr->doc, attr->parent, pref);
4991 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004992 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004993 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004994 ownerItem, (xmlNodePtr) attr,
4995 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
4996 "The value '%s' of simple type 'xs:QName' has no "
4997 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004998 return (ctxt->err);
4999 } else {
5000 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005001 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005002 return (0);
5003}
5004
5005/**
5006 * xmlSchemaPValAttrNodeQName:
5007 * @ctxt: a schema parser context
5008 * @schema: the schema context
5009 * @ownerDes: the designation of the owner element
5010 * @ownerItem: the owner as a schema object
5011 * @attr: the attribute node
5012 * @local: the resulting local part if found, the attribute value otherwise
5013 * @uri: the resulting namespace URI if found
5014 *
5015 * Extracts and validates the QName of an attribute value.
5016 * This one is intended to be used on attribute values that
5017 * should resolve to schema components.
5018 *
5019 * Returns 0, in case the QName is valid, a positive error code
5020 * if not valid and -1 if an internal error occurs.
5021 */
5022static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005023xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005024 xmlSchemaPtr schema,
5025 xmlChar **ownerDes,
5026 xmlSchemaTypePtr ownerItem,
5027 xmlAttrPtr attr,
5028 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005029 const xmlChar **local)
5030{
5031 const xmlChar *value;
5032
5033 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005034 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5035 ownerDes, ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005036}
5037
5038/**
5039 * xmlSchemaPValAttrQName:
5040 * @ctxt: a schema parser context
5041 * @schema: the schema context
5042 * @ownerDes: the designation of the parent element
5043 * @ownerItem: the owner as a schema object
5044 * @ownerElem: the parent node of the attribute
5045 * @name: the name of the attribute
5046 * @local: the resulting local part if found, the attribute value otherwise
5047 * @uri: the resulting namespace URI if found
5048 *
5049 * Extracts and validates the QName of an attribute value.
5050 *
5051 * Returns 0, in case the QName is valid, a positive error code
5052 * if not valid and -1 if an internal error occurs.
5053 */
5054static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005055xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5056 xmlSchemaPtr schema,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005057 xmlChar **ownerDes,
5058 xmlSchemaTypePtr ownerItem,
5059 xmlNodePtr ownerElem,
5060 const char *name,
5061 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005062 const xmlChar **local)
5063{
5064 xmlAttrPtr attr;
5065
5066 attr = xmlSchemaGetPropNode(ownerElem, name);
5067 if (attr == NULL) {
5068 *local = NULL;
5069 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005070 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005071 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005072 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5073 ownerDes, ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005074}
5075
5076/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005077 * xmlSchemaPValAttrID:
5078 * @ctxt: a schema parser context
5079 * @schema: the schema context
5080 * @ownerDes: the designation of the parent element
5081 * @ownerItem: the owner as a schema object
5082 * @ownerElem: the parent node of the attribute
5083 * @name: the name of the attribute
5084 *
5085 * Extracts and validates the ID of an attribute value.
5086 *
5087 * Returns 0, in case the ID is valid, a positive error code
5088 * if not valid and -1 if an internal error occurs.
5089 */
5090static int
5091xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005092 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005093 xmlSchemaTypePtr ownerItem,
5094 xmlNodePtr ownerElem,
5095 const xmlChar *name)
5096{
5097 int ret;
5098 xmlChar *value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005099 xmlAttrPtr attr;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005100
5101 value = xmlGetNoNsProp(ownerElem, name);
5102 if (value == NULL)
5103 return (0);
5104
5105 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5106 if (attr == NULL)
5107 return (-1);
5108
5109 ret = xmlValidateNCName(BAD_CAST value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005110 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005111 /*
5112 * NOTE: the IDness might have already be declared in the DTD
5113 */
5114 if (attr->atype != XML_ATTRIBUTE_ID) {
5115 xmlIDPtr res;
5116 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005117
5118 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005119 * TODO: Use xmlSchemaStrip here; it's not exported at this
5120 * moment.
5121 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005122 strip = xmlSchemaCollapseString(BAD_CAST value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005123 if (strip != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005124 value = strip;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005125 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
5126 if (res == NULL) {
5127 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005128 xmlSchemaPSimpleTypeErr(ctxt,
5129 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5130 ownerItem, (xmlNodePtr) attr,
5131 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5132 NULL, NULL, "Duplicate value '%s' of simple "
5133 "type 'xs:ID'", BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005134 } else
5135 attr->atype = XML_ATTRIBUTE_ID;
5136 if (strip != NULL)
5137 xmlFree(strip);
5138 }
5139 } else if (ret > 0) {
5140 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005141 xmlSchemaPSimpleTypeErr(ctxt,
5142 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5143 ownerItem, (xmlNodePtr) attr,
5144 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5145 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5146 "not a valid 'xs:NCName'",
5147 BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005148 }
5149 xmlFree(value);
5150
5151 return (ret);
5152}
5153
5154/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005155 * xmlGetMaxOccurs:
5156 * @ctxt: a schema validation context
5157 * @node: a subtree containing XML Schema informations
5158 *
5159 * Get the maxOccurs property
5160 *
5161 * Returns the default if not found, or the value
5162 */
5163static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005164xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5165 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005166{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005167 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005168 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005169 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005170
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005171 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5172 if (attr == NULL)
5173 return (def);
5174 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005175
5176 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005177 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005178 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005179 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5180 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005181 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005182 val, NULL, NULL, NULL);
5183 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005184 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005185 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005186 }
5187
5188 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005189 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005190 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005191 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005192 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005193 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5194 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005195 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005196 val, NULL, NULL, NULL);
5197 return (def);
5198 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005199 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005200 ret = ret * 10 + (*cur - '0');
5201 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005202 }
William M. Brack76e95df2003-10-18 16:20:14 +00005203 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005204 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005205 /*
5206 * TODO: Restrict the maximal value to Integer.
5207 */
5208 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005209 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005210 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5211 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005212 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005213 val, NULL, NULL, NULL);
5214 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005215 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005216 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005217}
5218
5219/**
5220 * xmlGetMinOccurs:
5221 * @ctxt: a schema validation context
5222 * @node: a subtree containing XML Schema informations
5223 *
5224 * Get the minOccurs property
5225 *
5226 * Returns the default if not found, or the value
5227 */
5228static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005229xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005230 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005231{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005232 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005233 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005234 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005235
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005236 attr = xmlSchemaGetPropNode(node, "minOccurs");
5237 if (attr == NULL)
5238 return (def);
5239 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005240 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005241 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005242 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005243 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005244 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005245 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5246 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005247 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005248 val, NULL, NULL, NULL);
5249 return (def);
5250 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005251 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005252 ret = ret * 10 + (*cur - '0');
5253 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005254 }
William M. Brack76e95df2003-10-18 16:20:14 +00005255 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005256 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005257 /*
5258 * TODO: Restrict the maximal value to Integer.
5259 */
5260 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005261 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005262 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5263 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005264 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005265 val, NULL, NULL, NULL);
5266 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005267 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005268 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005269}
5270
5271/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005272 * xmlSchemaPGetBoolNodeValue:
5273 * @ctxt: a schema validation context
5274 * @ownerDes: owner designation
5275 * @ownerItem: the owner as a schema item
5276 * @node: the node holding the value
5277 *
5278 * Converts a boolean string value into 1 or 0.
5279 *
5280 * Returns 0 or 1.
5281 */
5282static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005283xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
5284 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005285 xmlSchemaTypePtr ownerItem,
5286 xmlNodePtr node)
5287{
5288 xmlChar *value = NULL;
5289 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005290
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005291 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005292 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005293 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005294 * An instance of a datatype that is defined as ·boolean·
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005295 * can have the following legal literals {true, false, 1, 0}.
5296 */
5297 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
5298 res = 1;
5299 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
5300 res = 0;
5301 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
5302 res = 1;
5303 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005304 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005305 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005306 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005307 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005308 ownerItem, node,
5309 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5310 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005311 NULL, NULL, NULL);
5312 }
5313 if (value != NULL)
5314 xmlFree(value);
5315 return (res);
5316}
5317
5318/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005319 * xmlGetBooleanProp:
5320 * @ctxt: a schema validation context
5321 * @node: a subtree containing XML Schema informations
5322 * @name: the attribute name
5323 * @def: the default value
5324 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005325 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00005326 *
5327 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005328 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00005329 */
5330static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005331xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
5332 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005333 xmlSchemaTypePtr ownerItem,
5334 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005335 const char *name, int def)
5336{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005337 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00005338
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005339 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005340 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005341 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005342 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005343 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005344 * An instance of a datatype that is defined as ·boolean·
Daniel Veillardc0826a72004-08-10 14:17:33 +00005345 * can have the following legal literals {true, false, 1, 0}.
5346 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005347 if (xmlStrEqual(val, BAD_CAST "true"))
5348 def = 1;
5349 else if (xmlStrEqual(val, BAD_CAST "false"))
5350 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005351 else if (xmlStrEqual(val, BAD_CAST "1"))
5352 def = 1;
5353 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005354 def = 0;
5355 else {
5356 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005357 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005358 ownerItem,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005359 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005360 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5361 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005362 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005363 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005364}
5365
5366/************************************************************************
5367 * *
5368 * Shema extraction from an Infoset *
5369 * *
5370 ************************************************************************/
5371static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
5372 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005373 xmlNodePtr node,
5374 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005375static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
5376 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005377 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005378 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00005379 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005380static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
5381 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005382 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005383 xmlNodePtr node,
5384 xmlSchemaTypeType parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005385static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
5386 ctxt,
5387 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005388 xmlNodePtr node,
5389 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005390static xmlSchemaAttributeGroupPtr
5391xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005392 xmlSchemaPtr schema, xmlNodePtr node,
5393 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005394static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
5395 xmlSchemaPtr schema,
5396 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00005397static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005398xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5399 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005400
5401/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005402 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005403 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005404 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00005405 * @ownerDes: the designation of the parent element
5406 * @ownerItem: the schema object owner if existent
5407 * @attr: the schema attribute node being validated
5408 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005409 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00005410 *
5411 * Validates a value against the given built-in type.
5412 * This one is intended to be used internally for validation
5413 * of schema attribute values during parsing of the schema.
5414 *
5415 * Returns 0 if the value is valid, a positive error code
5416 * number otherwise and -1 in case of an internal or API error.
5417 */
5418static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005419xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
5420 xmlChar **ownerDes ATTRIBUTE_UNUSED,
5421 xmlSchemaTypePtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005422 xmlAttrPtr attr,
5423 const xmlChar *value,
5424 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005425{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005426
5427 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005428
5429 /*
5430 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
5431 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005432 */
5433 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00005434 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005435 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5436 PERROR_INT("xmlSchemaPValAttrNodeValue",
5437 "the given type is not a built-in type");
5438 return (-1);
5439 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005440 switch (type->builtInType) {
5441 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005442 case XML_SCHEMAS_QNAME:
5443 case XML_SCHEMAS_ANYURI:
5444 case XML_SCHEMAS_TOKEN:
5445 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005446 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
5447 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005448 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005449 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005450 PERROR_INT("xmlSchemaPValAttrNodeValue",
5451 "validation using the given type is not supported");
Daniel Veillard01fa6152004-06-29 17:04:39 +00005452 return (-1);
5453 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005454 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005455 /*
5456 * TODO: Should we use the S4S error codes instead?
5457 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005458 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005459 PERROR_INT("xmlSchemaPValAttrNodeValue",
5460 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005461 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005462 } else if (ret > 0) {
5463 if (VARIETY_LIST(type))
5464 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
5465 else
5466 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
5467 xmlSchemaPSimpleTypeErr(pctxt,
5468 ret, ownerItem, (xmlNodePtr) attr,
5469 type, NULL, value, NULL, NULL, NULL);
5470 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005471 return (ret);
5472}
5473
5474/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005475 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005476 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005477 * @ctxt: a schema parser context
5478 * @ownerDes: the designation of the parent element
5479 * @ownerItem: the schema object owner if existent
5480 * @attr: the schema attribute node being validated
5481 * @type: the built-in type to be validated against
5482 * @value: the resulting value if any
5483 *
5484 * Extracts and validates a value against the given built-in type.
5485 * This one is intended to be used internally for validation
5486 * of schema attribute values during parsing of the schema.
5487 *
5488 * Returns 0 if the value is valid, a positive error code
5489 * number otherwise and -1 in case of an internal or API error.
5490 */
5491static int
5492xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
5493 xmlChar **ownerDes,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005494 xmlSchemaTypePtr ownerItem,
5495 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005496 xmlSchemaTypePtr type,
5497 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005498{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005499 const xmlChar *val;
5500
5501 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005502 return (-1);
5503
Daniel Veillardc0826a72004-08-10 14:17:33 +00005504 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5505 if (value != NULL)
5506 *value = val;
5507
5508 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005509 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005510}
5511
5512/**
5513 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005514 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005515 * @ctxt: a schema parser context
5516 * @node: the element node of the attribute
5517 * @ownerDes: the designation of the parent element
5518 * @ownerItem: the schema object owner if existent
5519 * @ownerElem: the owner element node
5520 * @name: the name of the schema attribute node
5521 * @type: the built-in type to be validated against
5522 * @value: the resulting value if any
5523 *
5524 * Extracts and validates a value against the given built-in type.
5525 * This one is intended to be used internally for validation
5526 * of schema attribute values during parsing of the schema.
5527 *
5528 * Returns 0 if the value is valid, a positive error code
5529 * number otherwise and -1 in case of an internal or API error.
5530 */
5531static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005532xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005533 xmlChar **ownerDes,
5534 xmlSchemaTypePtr ownerItem,
5535 xmlNodePtr ownerElem,
5536 const char *name,
5537 xmlSchemaTypePtr type,
5538 const xmlChar **value)
5539{
5540 xmlAttrPtr attr;
5541
5542 if ((ctxt == NULL) || (type == NULL)) {
5543 if (value != NULL)
5544 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005545 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005546 }
5547 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5548 if (value != NULL)
5549 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005550 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005551 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005552 "Internal error: xmlSchemaPValAttr, the given "
5553 "type '%s' is not a built-in type.\n",
5554 type->name, NULL);
5555 return (-1);
5556 }
5557 attr = xmlSchemaGetPropNode(ownerElem, name);
5558 if (attr == NULL) {
5559 if (value != NULL)
5560 *value = NULL;
5561 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005562 }
5563 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005564 type, value));
5565}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005566
5567static int
5568xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
5569 xmlSchemaPtr schema,
5570 xmlNodePtr node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005571 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005572 const xmlChar *namespaceName)
5573{
5574 if (xmlStrEqual(schema->targetNamespace, namespaceName))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005575 return (1);
5576 if (xmlStrEqual(xmlSchemaNs, namespaceName))
5577 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005578 if (pctxt->localImports != NULL) {
5579 int i;
5580 for (i = 0; i < pctxt->nbLocalImports; i++)
5581 if (xmlStrEqual(namespaceName, pctxt->localImports[i]))
5582 return (1);
5583 }
5584 if (namespaceName == NULL)
5585 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005586 NULL, (xmlSchemaTypePtr) item, node,
5587 "References from this schema to components in no "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005588 "namespace are not valid, since not indicated by an import "
5589 "statement", NULL);
5590 else
5591 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005592 NULL, (xmlSchemaTypePtr) item, node,
5593 "References from this schema to components in the "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005594 "namespace '%s' are not valid, since not indicated by an import "
5595 "statement", namespaceName);
5596 return (0);
5597}
5598
Daniel Veillardc0826a72004-08-10 14:17:33 +00005599/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005600 * xmlSchemaParseAttrDecls:
5601 * @ctxt: a schema validation context
5602 * @schema: the schema being built
5603 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005604 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00005605 *
5606 * parse a XML schema attrDecls declaration corresponding to
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005607 * <!ENTITY % attrDecls
Daniel Veillard4255d502002-04-16 15:50:10 +00005608 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
5609 */
5610static xmlNodePtr
5611xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5612 xmlNodePtr child, xmlSchemaTypePtr type)
5613{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005614 xmlSchemaAttributePtr lastattr = NULL, attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005615
Daniel Veillard4255d502002-04-16 15:50:10 +00005616 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005617 (IS_SCHEMA(child, "attributeGroup"))) {
5618 attr = NULL;
5619 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00005620 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005621 } else if (IS_SCHEMA(child, "attributeGroup")) {
5622 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005623 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005624 }
5625 if (attr != NULL) {
5626 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005627 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
5628 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
5629 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005630 type->attributes = attr;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005631 lastattr = attr;
5632 } else {
5633 lastattr->next = attr;
5634 lastattr = attr;
5635 }
5636 }
5637 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005638 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005639 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005640}
5641
5642/**
5643 * xmlSchemaParseAnnotation:
5644 * @ctxt: a schema validation context
5645 * @schema: the schema being built
5646 * @node: a subtree containing XML Schema informations
5647 *
5648 * parse a XML schema Attrribute declaration
5649 * *WARNING* this interface is highly subject to change
5650 *
William M. Bracke7091952004-05-11 15:09:58 +00005651 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005652 * 1 in case of success.
5653 */
5654static xmlSchemaAnnotPtr
5655xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5656 xmlNodePtr node)
5657{
5658 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005659 xmlNodePtr child = NULL;
5660 xmlAttrPtr attr;
5661 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005662
Daniel Veillardc0826a72004-08-10 14:17:33 +00005663 /*
5664 * INFO: S4S completed.
5665 */
5666 /*
5667 * id = ID
5668 * {any attributes with non-schema namespace . . .}>
5669 * Content: (appinfo | documentation)*
5670 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005671 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5672 return (NULL);
5673 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005674 attr = node->properties;
5675 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005676 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005677 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005678 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005679 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005680
5681 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005682 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5683 NULL, NULL, attr);
5684 }
5685 attr = attr->next;
5686 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005687 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005688 /*
5689 * And now for the children...
5690 */
5691 child = node->children;
5692 while (child != NULL) {
5693 if (IS_SCHEMA(child, "appinfo")) {
5694 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005695 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005696 * source = anyURI
5697 * {any attributes with non-schema namespace . . .}>
5698 * Content: ({any})*
5699 */
5700 attr = child->properties;
5701 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005702 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005703 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005704 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005705 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005706
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005707 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005708 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5709 NULL, NULL, attr);
5710 }
5711 attr = attr->next;
5712 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005713 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
5714 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005715 child = child->next;
5716 } else if (IS_SCHEMA(child, "documentation")) {
5717 /* TODO: make available the content of "documentation". */
5718 /*
5719 * source = anyURI
5720 * {any attributes with non-schema namespace . . .}>
5721 * Content: ({any})*
5722 */
5723 attr = child->properties;
5724 while (attr != NULL) {
5725 if (attr->ns == NULL) {
5726 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005727 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005728 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5729 NULL, NULL, attr);
5730 }
5731 } else {
5732 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
5733 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
5734 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005735
5736 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005737 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5738 NULL, NULL, attr);
5739 }
5740 }
5741 attr = attr->next;
5742 }
5743 /*
5744 * Attribute "xml:lang".
5745 */
5746 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
5747 if (attr != NULL)
5748 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005749 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005750 child = child->next;
5751 } else {
5752 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005753 xmlSchemaPContentErr(ctxt,
5754 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005755 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
5756 barked = 1;
5757 child = child->next;
5758 }
5759 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005760
Daniel Veillard4255d502002-04-16 15:50:10 +00005761 return (ret);
5762}
5763
5764/**
5765 * xmlSchemaParseFacet:
5766 * @ctxt: a schema validation context
5767 * @schema: the schema being built
5768 * @node: a subtree containing XML Schema informations
5769 *
5770 * parse a XML schema Facet declaration
5771 * *WARNING* this interface is highly subject to change
5772 *
5773 * Returns the new type structure or NULL in case of error
5774 */
5775static xmlSchemaFacetPtr
5776xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005777 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005778{
5779 xmlSchemaFacetPtr facet;
5780 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005781 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00005782
5783 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5784 return (NULL);
5785
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005786 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005787 if (facet == NULL) {
5788 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
5789 return (NULL);
5790 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005791 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005792 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00005793 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005794 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
5795 "Facet %s has no value\n", node->name, NULL);
5796 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00005797 return (NULL);
5798 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005799 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005800 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005801 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005802 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005803 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005804 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005805 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005806 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005807 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005808 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005809 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005810 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005811 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005812 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005813 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005814 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005815 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005816 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005817 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005818 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005819 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005820 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
5821 } else if (IS_SCHEMA(node, "minLength")) {
5822 facet->type = XML_SCHEMA_FACET_MINLENGTH;
5823 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005824 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
5825 "Unknown facet type %s\n", node->name, NULL);
5826 xmlSchemaFreeFacet(facet);
5827 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005828 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005829 xmlSchemaPValAttrID(ctxt, NULL,
5830 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005831 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005832 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
5833 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
5834 const xmlChar *fixed;
5835
5836 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
5837 if (fixed != NULL) {
5838 if (xmlStrEqual(fixed, BAD_CAST "true"))
5839 facet->fixed = 1;
5840 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005841 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005842 child = node->children;
5843
5844 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005845 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5846 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005847 }
5848 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005849 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
5850 "Facet %s has unexpected child content\n",
5851 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005852 }
5853 return (facet);
5854}
5855
5856/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005857 * xmlSchemaParseWildcardNs:
5858 * @ctxt: a schema parser context
5859 * @wildc: the wildcard, already created
5860 * @node: a subtree containing XML Schema informations
5861 *
5862 * Parses the attribute "processContents" and "namespace"
5863 * of a xsd:anyAttribute and xsd:any.
5864 * *WARNING* this interface is highly subject to change
5865 *
5866 * Returns 0 if everything goes fine, a positive error code
5867 * if something is not valid and -1 if an internal error occurs.
5868 */
5869static int
5870xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
5871 xmlSchemaPtr schema,
5872 xmlSchemaWildcardPtr wildc,
5873 xmlNodePtr node)
5874{
5875 const xmlChar *pc, *ns, *dictnsItem;
5876 int ret = 0;
5877 xmlChar *nsItem;
5878 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
5879 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005880
Daniel Veillardc0826a72004-08-10 14:17:33 +00005881 pc = xmlSchemaGetProp(ctxt, node, "processContents");
5882 if ((pc == NULL)
5883 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
5884 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5885 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
5886 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
5887 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
5888 wildc->processContents = XML_SCHEMAS_ANY_LAX;
5889 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005890 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005891 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005892 NULL, node,
5893 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005894 NULL, NULL, NULL);
5895 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005896 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005897 }
5898 /*
5899 * Build the namespace constraints.
5900 */
5901 attr = xmlSchemaGetPropNode(node, "namespace");
5902 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00005903 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00005904 wildc->any = 1;
5905 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
5906 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005907 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005908 return (-1);
5909 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005910 wildc->negNsSet->value = schema->targetNamespace;
5911 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005912 const xmlChar *end, *cur;
5913
5914 cur = ns;
5915 do {
5916 while (IS_BLANK_CH(*cur))
5917 cur++;
5918 end = cur;
5919 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5920 end++;
5921 if (end == cur)
5922 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005923 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005924 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
5925 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005926 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005927 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005928 NULL, (xmlNodePtr) attr,
5929 NULL,
5930 "((##any | ##other) | List of (xs:anyURI | "
5931 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005932 nsItem, NULL, NULL, NULL);
5933 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
5934 } else {
5935 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
5936 dictnsItem = schema->targetNamespace;
5937 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
5938 dictnsItem = NULL;
5939 } else {
5940 /*
5941 * Validate the item (anyURI).
5942 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005943 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005944 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
5945 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
5946 }
5947 /*
5948 * Avoid dublicate namespaces.
5949 */
5950 tmp = wildc->nsSet;
5951 while (tmp != NULL) {
5952 if (dictnsItem == tmp->value)
5953 break;
5954 tmp = tmp->next;
5955 }
5956 if (tmp == NULL) {
5957 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
5958 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005959 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005960 return (-1);
5961 }
5962 tmp->value = dictnsItem;
5963 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005964 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00005965 wildc->nsSet = tmp;
5966 else
5967 lastNs->next = tmp;
5968 lastNs = tmp;
5969 }
5970
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005971 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005972 xmlFree(nsItem);
5973 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005974 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005975 }
5976 return (ret);
5977}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005978
5979static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005980xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
5981 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005982 xmlNodePtr node,
5983 int minOccurs,
5984 int maxOccurs) {
5985
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005986 if ((maxOccurs == 0) && ( minOccurs == 0))
5987 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005988 if (maxOccurs != UNBOUNDED) {
5989 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005990 * TODO: Maybe we should better not create the particle,
5991 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005992 * content model.
5993 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005994 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005995 * 3.9.6 Schema Component Constraint: Particle Correct
5996 *
5997 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005998 if (maxOccurs < 1) {
5999 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006000 * 2.2 {max occurs} must be greater than or equal to 1.
6001 */
6002 xmlSchemaPCustomAttrErr(ctxt,
6003 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006004 NULL, NULL,
6005 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006006 "The value must be greater than or equal to 1");
6007 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6008 } else if (minOccurs > maxOccurs) {
6009 /*
6010 * 2.1 {min occurs} must not be greater than {max occurs}.
6011 */
6012 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006013 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006014 NULL, NULL,
6015 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006016 "The value must not be greater than the value of 'maxOccurs'");
6017 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6018 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006019 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006020 return (0);
6021}
6022
Daniel Veillardc0826a72004-08-10 14:17:33 +00006023/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006024 * xmlSchemaParseAny:
6025 * @ctxt: a schema validation context
6026 * @schema: the schema being built
6027 * @node: a subtree containing XML Schema informations
6028 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006029 * Parsea a XML schema <any> element. A particle and wildcard
6030 * will be created (except if minOccurs==maxOccurs==0, in this case
6031 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006032 * *WARNING* this interface is highly subject to change
6033 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006034 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006035 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006036static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006037xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6038 xmlNodePtr node)
6039{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006040 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006041 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006042 xmlSchemaWildcardPtr wild;
6043 int min, max;
6044 xmlAttrPtr attr;
6045 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006046
6047 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6048 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006049 /*
6050 * Check for illegal attributes.
6051 */
6052 attr = node->properties;
6053 while (attr != NULL) {
6054 if (attr->ns == NULL) {
6055 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6056 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6057 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6058 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6059 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006060 xmlSchemaPIllegalAttrErr(ctxt,
6061 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6062 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006063 }
6064 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006065 xmlSchemaPIllegalAttrErr(ctxt,
6066 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6067 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006068 }
6069 attr = attr->next;
6070 }
6071 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
6072 /*
6073 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006074 */
6075 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6076 "(xs:nonNegativeInteger | unbounded)");
6077 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6078 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006079 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6080 /*
6081 * Create & parse the wildcard.
6082 */
6083 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6084 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006085 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006086 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006087 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006088 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006089 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006090 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006091 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006092 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006093 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006094 }
6095 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006096 xmlSchemaPContentErr(ctxt,
6097 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006098 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006099 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006100 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006101 /*
6102 * No component if minOccurs==maxOccurs==0.
6103 */
6104 if ((min == 0) && (max == 0)) {
6105 /* Don't free the wildcard, since it's already on the list. */
6106 return (NULL);
6107 }
6108 /*
6109 * Create the particle.
6110 */
6111 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6112 if (particle == NULL)
6113 return (NULL);
6114 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006115 wild->minOccurs = min;
6116 wild->maxOccurs = max;
6117 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006118
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006119 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006120}
6121
6122/**
6123 * xmlSchemaParseNotation:
6124 * @ctxt: a schema validation context
6125 * @schema: the schema being built
6126 * @node: a subtree containing XML Schema informations
6127 *
6128 * parse a XML schema Notation declaration
6129 *
6130 * Returns the new structure or NULL in case of error
6131 */
6132static xmlSchemaNotationPtr
6133xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006134 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006135{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006136 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006137 xmlSchemaNotationPtr ret;
6138 xmlNodePtr child = NULL;
6139
6140 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6141 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006142 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006143 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006144 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6145 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006146 return (NULL);
6147 }
6148 ret = xmlSchemaAddNotation(ctxt, schema, name);
6149 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006150 return (NULL);
6151 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006152 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006153
6154 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6155 node, BAD_CAST "id");
6156
6157 if (IS_SCHEMA(child, "annotation")) {
6158 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6159 child = child->next;
6160 }
6161
Daniel Veillard4255d502002-04-16 15:50:10 +00006162 child = node->children;
6163 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006164 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6165 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006166 }
6167 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006168 xmlSchemaPContentErr(ctxt,
6169 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006170 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006171 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006172 }
6173
6174 return (ret);
6175}
6176
6177/**
6178 * xmlSchemaParseAnyAttribute:
6179 * @ctxt: a schema validation context
6180 * @schema: the schema being built
6181 * @node: a subtree containing XML Schema informations
6182 *
6183 * parse a XML schema AnyAttrribute declaration
6184 * *WARNING* this interface is highly subject to change
6185 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006186 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006187 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006188static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006189xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6190 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006191{
Daniel Veillard3646d642004-06-02 19:19:14 +00006192 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006193 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006194 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006195
6196 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6197 return (NULL);
6198
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006199 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6200 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006201 if (ret == NULL) {
6202 return (NULL);
6203 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006204 /*
6205 * Check for illegal attributes.
6206 */
6207 attr = node->properties;
6208 while (attr != NULL) {
6209 if (attr->ns == NULL) {
6210 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6211 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6212 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006213 xmlSchemaPIllegalAttrErr(ctxt,
6214 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6215 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006216 }
6217 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006218 xmlSchemaPIllegalAttrErr(ctxt,
6219 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6220 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006221 }
6222 attr = attr->next;
6223 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006224 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6225 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006226 /*
6227 * Parse the namespace list.
6228 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006229 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006230 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006231 /*
6232 * And now for the children...
6233 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006234 child = node->children;
6235 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006236 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6237 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006238 }
6239 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006240 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006241 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006242 NULL, NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006243 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006244 }
6245
6246 return (ret);
6247}
6248
6249
6250/**
6251 * xmlSchemaParseAttribute:
6252 * @ctxt: a schema validation context
6253 * @schema: the schema being built
6254 * @node: a subtree containing XML Schema informations
6255 *
6256 * parse a XML schema Attrribute declaration
6257 * *WARNING* this interface is highly subject to change
6258 *
William M. Bracke7091952004-05-11 15:09:58 +00006259 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006260 */
6261static xmlSchemaAttributePtr
6262xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00006263 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006264{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006265 const xmlChar *name, *attrValue;
6266 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00006267 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006268 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006269 xmlAttrPtr attr, nameAttr;
6270 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00006271
6272 /*
6273 * Note that the w3c spec assumes the schema to be validated with schema
6274 * for schemas beforehand.
6275 *
6276 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00006277 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006278
6279 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6280 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006281 attr = xmlSchemaGetPropNode(node, "ref");
6282 nameAttr = xmlSchemaGetPropNode(node, "name");
6283
6284 if ((attr == NULL) && (nameAttr == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006285 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006286 * 3.2.3 : 3.1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006287 * One of ref or name must be present, but not both
Daniel Veillardc0826a72004-08-10 14:17:33 +00006288 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006289 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6290 NULL, node, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006291 "One of the attributes 'ref' or 'name' must be present");
6292 return (NULL);
6293 }
6294 if ((topLevel) || (attr == NULL)) {
6295 if (nameAttr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006296 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
6297 NULL, node, "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006298 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006299 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006300 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006301 isRef = 1;
6302
Daniel Veillardc0826a72004-08-10 14:17:33 +00006303 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006304 char buf[50];
6305 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006306
6307 /*
6308 * Parse as attribute reference.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006309 */
6310 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
6311 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
6312 &ref) != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006313 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006314 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006315 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006316 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006317 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006318 if (ret == NULL) {
6319 if (repName != NULL)
6320 xmlFree(repName);
6321 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006322 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006323 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
6324 ret->node = node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006325 ret->refNs = refNs;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006326 ret->ref = ref;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006327 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) ret,
6328 refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006329 /*
6330 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
6331 */
6332 if (nameAttr != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006333 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6334 &repName, (xmlSchemaTypePtr) ret, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006335 "ref", "name");
6336 /*
6337 * Check for illegal attributes.
6338 */
6339 attr = node->properties;
6340 while (attr != NULL) {
6341 if (attr->ns == NULL) {
6342 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
6343 xmlStrEqual(attr->name, BAD_CAST "form")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006344 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006345 * 3.2.3 : 3.2
6346 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006347 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006348 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006349 xmlSchemaPIllegalAttrErr(ctxt,
6350 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006351 (xmlSchemaTypePtr) ret, attr);
6352 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
6353 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
6354 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006355 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6356 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006357 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006358 xmlSchemaPIllegalAttrErr(ctxt,
6359 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6360 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006361 }
6362 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006363 xmlSchemaPIllegalAttrErr(ctxt,
6364 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6365 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006366 }
6367 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006368 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006369 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006370 const xmlChar *ns = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006371
Daniel Veillardc0826a72004-08-10 14:17:33 +00006372 /*
6373 * Parse as attribute declaration.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006374 */
6375 if (xmlSchemaPValAttrNode(ctxt,
6376 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006377 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6378 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006379 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006380 /*
6381 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
6382 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006383 /*
6384 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
6385 * TODO: Move this to the component layer.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006386 */
6387 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006388 xmlSchemaPSimpleTypeErr(ctxt,
6389 XML_SCHEMAP_NO_XMLNS,
6390 NULL, (xmlNodePtr) nameAttr,
6391 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
6392 "The value of type 'xs:NCName' must not match 'xmlns'",
6393 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006394 if (repName != NULL)
6395 xmlFree(repName);
6396 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006397 }
6398 /*
6399 * Evaluate the target namespace
6400 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006401 if (topLevel) {
6402 ns = schema->targetNamespace;
6403 } else {
6404 attr = xmlSchemaGetPropNode(node, "form");
6405 if (attr != NULL) {
6406 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6407 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
6408 ns = schema->targetNamespace;
6409 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006410 xmlSchemaPSimpleTypeErr(ctxt,
6411 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6412 NULL, (xmlNodePtr) attr,
6413 NULL, "(qualified | unqualified)",
6414 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006415 }
6416 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006417 ns = schema->targetNamespace;
6418 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006419 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006420 if (ret == NULL) {
6421 if (repName != NULL)
6422 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00006423 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006424 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006425 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006426 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006427 if (topLevel)
6428 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006429 /*
6430 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
6431 * TODO: Move this to the component layer.
6432 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006433 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006434 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006435 XML_SCHEMAP_NO_XSI,
6436 &repName, (xmlSchemaTypePtr) ret, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006437 "The target namespace must not match '%s'",
6438 xmlSchemaInstanceNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006439 }
6440 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006441 * Check for illegal attributes.
6442 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006443 attr = node->properties;
6444 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006445 if (attr->ns == NULL) {
6446 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6447 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6448 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006449 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6450 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006451 if ((topLevel) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006452 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
6453 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006454 xmlSchemaPIllegalAttrErr(ctxt,
6455 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6456 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006457 }
6458 }
6459 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006460 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6461 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006462 }
6463 attr = attr->next;
6464 }
6465 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006466 node, "type", &ret->typeNs, &ret->typeName);
6467 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006468 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6469 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00006470 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006471 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00006472 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006473 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
6474 if (ret->defValue != NULL)
6475 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006476 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006477 * Attribute "default".
6478 */
6479 attr = xmlSchemaGetPropNode(node, "default");
6480 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006481 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006482 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006483 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006484 */
6485 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
6486 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
6487 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
6488 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006489 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6490 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006491 if (topLevel == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006492 /*
6493 * Attribute "use".
Daniel Veillardc0826a72004-08-10 14:17:33 +00006494 */
6495 attr = xmlSchemaGetPropNode(node, "use");
6496 if (attr != NULL) {
6497 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6498 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
6499 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6500 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
6501 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
6502 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
6503 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
6504 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006505 xmlSchemaPSimpleTypeErr(ctxt,
6506 XML_SCHEMAP_INVALID_ATTR_USE,
6507 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6508 NULL, "(optional | prohibited | required)",
6509 attrValue, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006510 } else
6511 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006512 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006513 * 3.2.3 : 2
6514 * If default and use are both present, use must have
6515 * the actual value optional.
6516 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006517 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6518 (ret->defValue != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006519 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006520 xmlSchemaPSimpleTypeErr(ctxt,
6521 XML_SCHEMAP_SRC_ATTRIBUTE_2,
6522 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6523 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006524 "The value must be 'optional' if the attribute "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006525 "'default' is present as well", NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006526 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006527 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006528 /*
6529 * And now for the children...
6530 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006531 child = node->children;
6532 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006533 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6534 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006535 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006536 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006537 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006538 if (IS_SCHEMA(child, "simpleType"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006539 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006540 * 3.2.3 : 3.2
6541 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006542 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006543 */
6544 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
6545 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6546 "(annotation?)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006547 else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006548 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6549 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006550 "(annotation?)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006551 }
6552 } else {
6553 if (IS_SCHEMA(child, "simpleType")) {
6554 if (ret->typeName != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006555 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006556 * 3.2.3 : 4
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006557 * type and <simpleType> must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006558 */
6559 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
6560 &repName, (xmlSchemaTypePtr) ret, node, child,
6561 "The attribute 'type' and the <simpleType> child "
6562 "are mutually exclusive", NULL);
6563 } else
6564 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6565 child = child->next;
6566 }
6567 if (child != NULL)
6568 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6569 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6570 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006571 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006572 /*
6573 * Cleanup.
6574 */
6575 if (repName != NULL)
6576 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00006577 return (ret);
6578}
6579
6580/**
6581 * xmlSchemaParseAttributeGroup:
6582 * @ctxt: a schema validation context
6583 * @schema: the schema being built
6584 * @node: a subtree containing XML Schema informations
6585 *
6586 * parse a XML schema Attribute Group declaration
6587 * *WARNING* this interface is highly subject to change
6588 *
6589 * Returns the attribute group or NULL in case of error.
6590 */
6591static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006592xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00006593 xmlSchemaPtr schema, xmlNodePtr node,
6594 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006595{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006596 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006597 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006598 xmlNodePtr child = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006599 const xmlChar *oldcontainer;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006600 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006601
6602 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6603 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006604
6605 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006606 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006607 if ((topLevel) || (attr == NULL)) {
6608 /*
6609 * Parse as an attribute group definition.
6610 * Note that those are allowed at top level only.
6611 */
6612 if (nameAttr == NULL) {
6613 xmlSchemaPMissingAttrErr(ctxt,
6614 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006615 NULL, node, "name", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006616 return (NULL);
6617 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006618 /* REDUNDANT: name = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006619 * (xmlNodePtr) nameAttr);
6620 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006621 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006622 * The name is crucial, exit if invalid.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006623 */
6624 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006625 NULL, NULL, nameAttr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006626 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6627 return (NULL);
6628 }
6629 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6630 if (ret == NULL)
6631 return (NULL);
6632 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6633 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
6634 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006635 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006636 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006637 char buf[50];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006638 const xmlChar *refNs = NULL, *ref = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006639
6640 /*
6641 * Parse as an attribute group definition reference.
6642 */
6643 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006644 xmlSchemaPMissingAttrErr(ctxt,
6645 XML_SCHEMAP_S4S_ATTR_MISSING,
6646 NULL, node, "ref", NULL);
6647 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006648 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006649 NULL, NULL, attr, &refNs,&ref);
6650
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006651 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006652 name = (const xmlChar *) buf;
6653 if (name == NULL) {
6654 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
6655 "attribute group definition reference", node);
6656 return (NULL);
6657 }
6658 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6659 if (ret == NULL)
6660 return (NULL);
6661 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6662 ret->ref = ref;
6663 ret->refNs = refNs;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006664 ret->node = node;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006665 xmlSchemaCheckReference(ctxt, schema, node,
6666 (xmlSchemaBasicItemPtr) ret, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006667 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006668 /*
6669 * Check for illegal attributes.
6670 */
6671 attr = node->properties;
6672 while (attr != NULL) {
6673 if (attr->ns == NULL) {
6674 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
6675 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006676 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006677 {
6678 xmlSchemaPIllegalAttrErr(ctxt,
6679 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6680 NULL, NULL, attr);
6681 }
6682 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6683 xmlSchemaPIllegalAttrErr(ctxt,
6684 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6685 NULL, NULL, attr);
6686 }
6687 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006688 }
6689 /* TODO: Validate "id" ? */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006690 /*
6691 * And now for the children...
6692 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006693 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00006694 ctxt->container = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006695 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006696 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006697 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6698 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006699 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006700 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006701 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006702 if (IS_SCHEMA(child, "anyAttribute")) {
6703 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
6704 child = child->next;
6705 }
6706 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006707 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006708 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006709 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6710 NULL, NULL, node, child, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006711 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006712 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006713 ctxt->container = oldcontainer;
6714 return (ret);
6715}
6716
6717/**
William M. Brack2f2a6632004-08-20 23:09:47 +00006718 * xmlSchemaPValAttrFormDefault:
6719 * @value: the value
6720 * @flags: the flags to be modified
6721 * @flagQualified: the specific flag for "qualified"
6722 *
6723 * Returns 0 if the value is valid, 1 otherwise.
6724 */
6725static int
6726xmlSchemaPValAttrFormDefault(const xmlChar *value,
6727 int *flags,
6728 int flagQualified)
6729{
6730 if (xmlStrEqual(value, BAD_CAST "qualified")) {
6731 if ((*flags & flagQualified) == 0)
6732 *flags |= flagQualified;
6733 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006734 return (1);
6735
William M. Brack2f2a6632004-08-20 23:09:47 +00006736 return (0);
6737}
6738
6739/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006740 * xmlSchemaPValAttrBlockFinal:
6741 * @value: the value
6742 * @flags: the flags to be modified
6743 * @flagAll: the specific flag for "#all"
6744 * @flagExtension: the specific flag for "extension"
6745 * @flagRestriction: the specific flag for "restriction"
6746 * @flagSubstitution: the specific flag for "substitution"
6747 * @flagList: the specific flag for "list"
6748 * @flagUnion: the specific flag for "union"
6749 *
6750 * Validates the value of the attribute "final" and "block". The value
6751 * is converted into the specified flag values and returned in @flags.
6752 *
6753 * Returns 0 if the value is valid, 1 otherwise.
6754 */
6755
6756static int
6757xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006758 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006759 int flagAll,
6760 int flagExtension,
6761 int flagRestriction,
6762 int flagSubstitution,
6763 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006764 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006765{
6766 int ret = 0;
6767
6768 /*
6769 * TODO: This does not check for dublicate entries.
6770 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006771 if ((flags == NULL) || (value == NULL))
6772 return (-1);
6773 if (value[0] == 0)
6774 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006775 if (xmlStrEqual(value, BAD_CAST "#all")) {
6776 if (flagAll != -1)
6777 *flags |= flagAll;
6778 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006779 if (flagExtension != -1)
6780 *flags |= flagExtension;
6781 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006782 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006783 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006784 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006785 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006786 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006787 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006788 *flags |= flagUnion;
6789 }
6790 } else {
6791 const xmlChar *end, *cur = value;
6792 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006793
Daniel Veillardc0826a72004-08-10 14:17:33 +00006794 do {
6795 while (IS_BLANK_CH(*cur))
6796 cur++;
6797 end = cur;
6798 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6799 end++;
6800 if (end == cur)
6801 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006802 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006803 if (xmlStrEqual(item, BAD_CAST "extension")) {
6804 if (flagExtension != -1) {
6805 if ((*flags & flagExtension) == 0)
6806 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006807 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006808 ret = 1;
6809 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
6810 if (flagRestriction != -1) {
6811 if ((*flags & flagRestriction) == 0)
6812 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006813 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006814 ret = 1;
6815 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
6816 if (flagSubstitution != -1) {
6817 if ((*flags & flagSubstitution) == 0)
6818 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006819 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006820 ret = 1;
6821 } else if (xmlStrEqual(item, BAD_CAST "list")) {
6822 if (flagList != -1) {
6823 if ((*flags & flagList) == 0)
6824 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006825 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006826 ret = 1;
6827 } else if (xmlStrEqual(item, BAD_CAST "union")) {
6828 if (flagUnion != -1) {
6829 if ((*flags & flagUnion) == 0)
6830 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006831 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006832 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006833 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006834 ret = 1;
6835 if (item != NULL)
6836 xmlFree(item);
6837 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006838 } while ((ret == 0) && (*cur != 0));
6839 }
6840
Daniel Veillardc0826a72004-08-10 14:17:33 +00006841 return (ret);
6842}
6843
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006844static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006845xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006846 xmlSchemaIDCPtr idc,
6847 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006848 xmlAttrPtr attr,
6849 int isField)
6850{
6851 xmlNodePtr node;
6852
6853 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006854 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006855 * Schema Component Constraint: Selector Value OK
6856 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006857 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006858 * in [XPath].
6859 */
6860 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006861 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006862 XML_SCHEMAP_INTERNAL,
6863 "Internal error: xmlSchemaCheckCSelectorXPath, "
6864 "the selector is not specified.\n", NULL, NULL);
6865 return (-1);
6866 }
6867 if (attr == NULL)
6868 node = idc->node;
6869 else
6870 node = (xmlNodePtr) attr;
6871 if (selector->xpath == NULL) {
6872 xmlSchemaPCustomErr(ctxt,
6873 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006874 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6875 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006876 "The XPath expression of the selector is not valid", NULL);
6877 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6878 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006879 const xmlChar **nsArray = NULL;
6880 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006881 /*
6882 * Compile the XPath expression.
6883 */
6884 /*
6885 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006886 * TODO: Call xmlPatterncompile with different options for selector/
6887 * field.
6888 */
6889 nsList = xmlGetNsList(attr->doc, attr->parent);
6890 /*
6891 * Build an array of prefixes and namespaces.
6892 */
6893 if (nsList != NULL) {
6894 int i, count = 0;
6895 xmlNsPtr ns;
6896
6897 for (i = 0; nsList[i] != NULL; i++)
6898 count++;
6899
6900 nsArray = (const xmlChar **) xmlMalloc(
6901 (count * 2 + 1) * sizeof(const xmlChar *));
6902 if (nsArray == NULL) {
6903 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
6904 NULL);
6905 return (-1);
6906 }
6907 for (i = 0; i < count; i++) {
6908 ns = nsList[i];
6909 nsArray[2 * i] = nsList[i]->href;
6910 nsArray[2 * i + 1] = nsList[i]->prefix;
6911 }
6912 nsArray[count * 2] = NULL;
6913 xmlFree(nsList);
6914 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006915 /*
6916 * TODO: Differentiate between "selector" and "field".
6917 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006918 if (isField)
6919 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00006920 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006921 else
6922 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00006923 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006924 if (nsArray != NULL)
6925 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006926
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006927 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006928 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006929 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006930 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6931 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006932 "The XPath expression '%s' could not be "
6933 "compiled", selector->xpath);
6934 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006935 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006936 }
6937 return (0);
6938}
6939
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006940#define ADD_ANNOTATION(annot) \
6941 xmlSchemaAnnotPtr cur = item->annot; \
6942 if (item->annot == NULL) { \
6943 item->annot = annot; \
6944 return (annot); \
6945 } \
6946 cur = item->annot; \
6947 if (cur->next != NULL) { \
6948 cur = cur->next; \
6949 } \
6950 cur->next = annot;
6951
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006952/**
6953 * xmlSchemaAssignAnnotation:
6954 * @item: the schema component
6955 * @annot: the annotation
6956 *
6957 * Adds the annotation to the given schema component.
6958 *
6959 * Returns the given annotaion.
6960 */
6961static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006962xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
6963 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006964{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006965 if ((annItem == NULL) || (annot == NULL))
6966 return (NULL);
6967 switch (annItem->type) {
6968 case XML_SCHEMA_TYPE_ELEMENT: {
6969 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
6970 ADD_ANNOTATION(annot)
6971 }
6972 break;
6973 case XML_SCHEMA_TYPE_ATTRIBUTE: {
6974 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
6975 ADD_ANNOTATION(annot)
6976 }
6977 break;
6978 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
6979 case XML_SCHEMA_TYPE_ANY: {
6980 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
6981 ADD_ANNOTATION(annot)
6982 }
6983 break;
6984 case XML_SCHEMA_TYPE_PARTICLE:
6985 case XML_SCHEMA_TYPE_IDC_KEY:
6986 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006987 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006988 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
6989 ADD_ANNOTATION(annot)
6990 }
6991 break;
6992 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
6993 xmlSchemaAttributeGroupPtr item =
6994 (xmlSchemaAttributeGroupPtr) annItem;
6995 ADD_ANNOTATION(annot)
6996 }
6997 break;
6998 case XML_SCHEMA_TYPE_NOTATION: {
6999 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
7000 ADD_ANNOTATION(annot)
7001 }
7002 break;
7003 case XML_SCHEMA_FACET_MININCLUSIVE:
7004 case XML_SCHEMA_FACET_MINEXCLUSIVE:
7005 case XML_SCHEMA_FACET_MAXINCLUSIVE:
7006 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
7007 case XML_SCHEMA_FACET_TOTALDIGITS:
7008 case XML_SCHEMA_FACET_FRACTIONDIGITS:
7009 case XML_SCHEMA_FACET_PATTERN:
7010 case XML_SCHEMA_FACET_ENUMERATION:
7011 case XML_SCHEMA_FACET_WHITESPACE:
7012 case XML_SCHEMA_FACET_LENGTH:
7013 case XML_SCHEMA_FACET_MAXLENGTH:
7014 case XML_SCHEMA_FACET_MINLENGTH: {
7015 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
7016 ADD_ANNOTATION(annot)
7017 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007018 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007019 case XML_SCHEMA_TYPE_SIMPLE:
7020 case XML_SCHEMA_TYPE_COMPLEX: {
7021 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
7022 ADD_ANNOTATION(annot)
7023 }
7024 break;
7025 case XML_SCHEMA_TYPE_GROUP: {
7026 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
7027 ADD_ANNOTATION(annot)
7028 }
7029 break;
7030 case XML_SCHEMA_TYPE_SEQUENCE:
7031 case XML_SCHEMA_TYPE_CHOICE:
7032 case XML_SCHEMA_TYPE_ALL: {
7033 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
7034 ADD_ANNOTATION(annot)
7035 }
7036 break;
7037 default:
7038 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007039 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007040 NULL, NULL, NULL,
7041 "Internal error: xmlSchemaAddAnnotation, "
7042 "The item is not a annotated schema component", NULL);
7043 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007044 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007045 return (annot);
7046}
7047
7048/**
7049 * xmlSchemaParseIDCSelectorAndField:
7050 * @ctxt: a schema validation context
7051 * @schema: the schema being built
7052 * @node: a subtree containing XML Schema informations
7053 *
7054 * Parses a XML Schema identity-contraint definition's
7055 * <selector> and <field> elements.
7056 *
7057 * Returns the parsed identity-constraint definition.
7058 */
7059static xmlSchemaIDCSelectPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007060xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007061 xmlSchemaPtr schema,
7062 xmlSchemaIDCPtr idc,
7063 xmlNodePtr node,
7064 int isField)
7065{
7066 xmlSchemaIDCSelectPtr item;
7067 xmlNodePtr child = NULL;
7068 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007069
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007070 /*
7071 * Check for illegal attributes.
7072 */
7073 attr = node->properties;
7074 while (attr != NULL) {
7075 if (attr->ns == NULL) {
7076 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7077 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007078 xmlSchemaPIllegalAttrErr(ctxt,
7079 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7080 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007081 }
7082 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007083 xmlSchemaPIllegalAttrErr(ctxt,
7084 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7085 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007086 }
7087 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007088 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007089 /*
7090 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007091 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007092 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
7093 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007094 xmlSchemaPErrMemory(ctxt,
7095 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007096 NULL);
7097 return (NULL);
7098 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007099 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007100 /*
7101 * Attribute "xpath" (mandatory).
7102 */
7103 attr = xmlSchemaGetPropNode(node, "xpath");
7104 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007105 xmlSchemaPMissingAttrErr(ctxt,
7106 XML_SCHEMAP_S4S_ATTR_MISSING,
7107 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007108 "name", NULL);
7109 } else {
7110 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7111 /*
7112 * URGENT TODO: "field"s have an other syntax than "selector"s.
7113 */
7114
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007115 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
7116 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007117 xmlSchemaPErr(ctxt,
7118 (xmlNodePtr) attr,
7119 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007120 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007121 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007122 NULL, NULL);
7123 }
7124
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007125 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007126 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007127 /*
7128 * And now for the children...
7129 */
7130 child = node->children;
7131 if (IS_SCHEMA(child, "annotation")) {
7132 /*
7133 * Add the annotation to the parent IDC.
7134 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007135 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007136 xmlSchemaParseAnnotation(ctxt, schema, child));
7137 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007138 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007139 if (child != NULL) {
7140 xmlSchemaPContentErr(ctxt,
7141 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007142 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007143 NULL, "(annotation?)");
7144 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007145
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007146 return (item);
7147}
7148
7149/**
7150 * xmlSchemaParseIDC:
7151 * @ctxt: a schema validation context
7152 * @schema: the schema being built
7153 * @node: a subtree containing XML Schema informations
7154 *
7155 * Parses a XML Schema identity-contraint definition.
7156 *
7157 * Returns the parsed identity-constraint definition.
7158 */
7159static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007160xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007161 xmlSchemaPtr schema,
7162 xmlNodePtr node,
7163 xmlSchemaTypeType idcCategory,
7164 const xmlChar *targetNamespace)
7165{
7166 xmlSchemaIDCPtr item = NULL;
7167 xmlNodePtr child = NULL;
7168 xmlAttrPtr attr;
7169 const xmlChar *name = NULL;
7170 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
7171 int resAdd;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007172
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007173 /*
7174 * Check for illegal attributes.
7175 */
7176 attr = node->properties;
7177 while (attr != NULL) {
7178 if (attr->ns == NULL) {
7179 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7180 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7181 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
7182 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007183 xmlSchemaPIllegalAttrErr(ctxt,
7184 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7185 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007186 }
7187 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007188 xmlSchemaPIllegalAttrErr(ctxt,
7189 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7190 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007191 }
7192 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007193 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007194 /*
7195 * Attribute "name" (mandatory).
7196 */
7197 attr = xmlSchemaGetPropNode(node, "name");
7198 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007199 xmlSchemaPMissingAttrErr(ctxt,
7200 XML_SCHEMAP_S4S_ATTR_MISSING,
7201 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007202 "name", NULL);
7203 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007204 } else if (xmlSchemaPValAttrNode(ctxt,
7205 NULL, NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007206 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7207 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007208 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007209 /*
7210 * Create the component.
7211 */
7212 if (schema->idcDef == NULL)
7213 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007214 if (schema->idcDef == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007215 return (NULL);
7216
7217 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
7218 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007219 xmlSchemaPErrMemory(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007220 "allocating an identity-constraint definition", NULL);
7221 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007222 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007223 /*
7224 * Add the IDC to the list of IDCs on the schema component.
7225 */
7226 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007227 if (resAdd != 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007228 xmlSchemaPCustomErrExt(ctxt,
7229 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007230 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007231 "An identity-constraint definition with the name '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007232 "and targetNamespace '%s' does already exist",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007233 name, targetNamespace, NULL);
7234 xmlFree(item);
7235 return (NULL);
7236 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007237 memset(item, 0, sizeof(xmlSchemaIDC));
7238 item->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007239 item->type = idcCategory;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007240 item->node = node;
7241 /*
7242 * The target namespace of the parent element declaration.
7243 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007244 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007245 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
7246 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007247 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
7248 /*
7249 * Attribute "refer" (mandatory).
7250 */
7251 attr = xmlSchemaGetPropNode(node, "refer");
7252 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007253 xmlSchemaPMissingAttrErr(ctxt,
7254 XML_SCHEMAP_S4S_ATTR_MISSING,
7255 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007256 "refer", NULL);
7257 } else {
7258 /*
7259 * Create a reference item.
7260 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007261 item->ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007262 NULL, NULL);
7263 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007264 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007265 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007266 NULL, NULL, attr,
7267 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007268 &(item->ref->name));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007269 xmlSchemaCheckReference(ctxt, schema, node,
7270 (xmlSchemaBasicItemPtr) item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007271 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007272 }
7273 }
7274 /*
7275 * And now for the children...
7276 */
7277 child = node->children;
7278 if (IS_SCHEMA(child, "annotation")) {
7279 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7280 child = child->next;
7281 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007282 if (child == NULL) {
7283 xmlSchemaPContentErr(ctxt,
7284 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007285 NULL, NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007286 "A child element is missing",
7287 "(annotation?, (selector, field+))");
7288 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007289 /*
7290 * Child element <selector>.
7291 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007292 if (IS_SCHEMA(child, "selector")) {
7293 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007294 item, child, 0);
7295 child = child->next;
7296 /*
7297 * Child elements <field>.
7298 */
7299 if (IS_SCHEMA(child, "field")) {
7300 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007301 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007302 item, child, 1);
7303 if (field != NULL) {
7304 field->index = item->nbFields;
7305 item->nbFields++;
7306 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007307 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007308 else
7309 item->fields = field;
7310 lastField = field;
7311 }
7312 child = child->next;
7313 } while (IS_SCHEMA(child, "field"));
7314 } else {
7315 xmlSchemaPContentErr(ctxt,
7316 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007317 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007318 NULL, "(annotation?, (selector, field+))");
7319 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007320 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007321 if (child != NULL) {
7322 xmlSchemaPContentErr(ctxt,
7323 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007324 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007325 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007326 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007327
7328 return (item);
7329}
7330
Daniel Veillardc0826a72004-08-10 14:17:33 +00007331/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007332 * xmlSchemaParseElement:
7333 * @ctxt: a schema validation context
7334 * @schema: the schema being built
7335 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007336 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00007337 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007338 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007339 * *WARNING* this interface is highly subject to change
7340 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007341 * Returns the element declaration or a particle; NULL in case
7342 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00007343 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007344static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00007345xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007346 xmlNodePtr node, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007347{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007348 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007349 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007350 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007351 xmlNodePtr child = NULL;
7352 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007353 int min, max, isRef = 0;
7354 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007355
7356 /* 3.3.3 Constraints on XML Representations of Element Declarations */
7357 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007358
Daniel Veillard4255d502002-04-16 15:50:10 +00007359 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007360 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007361 /*
7362 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007363 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007364 * robust.
7365 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007366 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007367 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007368 if ((topLevel) || (attr == NULL)) {
7369 if (nameAttr == NULL) {
7370 xmlSchemaPMissingAttrErr(ctxt,
7371 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007372 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007373 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007374 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007375 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007376 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007377
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007378 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007379 child = node->children;
7380 if (IS_SCHEMA(child, "annotation")) {
7381 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7382 child = child->next;
7383 }
7384 /*
7385 * Skip particle part if a global declaration.
7386 */
7387 if (topLevel)
7388 goto declaration_part;
7389 /*
7390 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007391 */
7392 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
7393 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
7394 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007395 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
7396 if (particle == NULL)
7397 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007398
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007399 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
7400
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007401 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007402 const xmlChar *refNs = NULL, *ref = NULL;
7403 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007404 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007405 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00007406 */
7407 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007408 NULL, NULL, attr, &refNs, &ref);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007409 xmlSchemaCheckReference(ctxt, schema, node, NULL, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007410 /*
7411 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00007412 */
7413 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007414 xmlSchemaPMutualExclAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007415 XML_SCHEMAP_SRC_ELEMENT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007416 NULL, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007417 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007418 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007419 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007420 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007421 attr = node->properties;
7422 while (attr != NULL) {
7423 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007424 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
7425 xmlStrEqual(attr->name, BAD_CAST "name") ||
7426 xmlStrEqual(attr->name, BAD_CAST "id") ||
7427 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
7428 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
7429 {
7430 attr = attr->next;
7431 continue;
7432 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007433 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007434 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007435 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007436 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007437 "Only the attributes 'minOccurs', 'maxOccurs' and "
7438 "'id' are allowed in addition to 'ref'");
7439 break;
7440 }
7441 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7442 xmlSchemaPIllegalAttrErr(ctxt,
7443 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007444 NULL, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007445 }
7446 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007447 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007448 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007449 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007450 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007451 if (child != NULL) {
7452 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7453 NULL, NULL, node, child, NULL, "(annotation?)");
7454 }
7455 if ((min == 0) && (max == 0))
7456 goto return_null;
7457 /*
7458 * Create the reference item.
7459 */
7460 refer = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_ELEMENT,
7461 ref, refNs);
7462 if (refer == NULL)
7463 goto return_null;
7464 particle->children = (xmlSchemaTreeItemPtr) refer;
7465 particle->annot = annot;
7466 /*
7467 * Add to assembled items; the reference need to be resolved.
7468 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007469 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007470 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) particle);
7471
7472 return ((xmlSchemaBasicItemPtr) particle);
7473 }
7474 /*
7475 * The declaration part ===============================================
7476 */
7477declaration_part:
7478 {
7479 const xmlChar *ns = NULL, *fixed, *name, *oldcontainer, *attrValue;
7480 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
7481
7482 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007483 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007484 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007485 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007486 * Evaluate the target namespace.
7487 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007488 if (topLevel) {
7489 ns = schema->targetNamespace;
7490 } else {
7491 attr = xmlSchemaGetPropNode(node, "form");
7492 if (attr != NULL) {
7493 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7494 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00007495 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007496 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007497 xmlSchemaPSimpleTypeErr(ctxt,
7498 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7499 NULL, (xmlNodePtr) attr,
7500 NULL, "(qualified | unqualified)",
7501 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007502 }
7503 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007504 ns = schema->targetNamespace;
7505 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007506 decl = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007507 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007508 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00007509 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007510 decl->type = XML_SCHEMA_TYPE_ELEMENT;
7511 decl->node = node;
7512 decl->targetNamespace = ns;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007513 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007514 * Check for illegal attributes.
7515 */
William M. Bracke7091952004-05-11 15:09:58 +00007516 attr = node->properties;
7517 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007518 if (attr->ns == NULL) {
7519 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7520 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007521 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007522 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007523 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007524 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007525 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
7526 {
7527 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007528 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007529 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007530 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007531 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007532 xmlSchemaPIllegalAttrErr(ctxt,
7533 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7534 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007535 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007536 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
7537 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007538 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
7539
7540 xmlSchemaPIllegalAttrErr(ctxt,
7541 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007542 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007543 }
7544 }
7545 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007546
Daniel Veillardc0826a72004-08-10 14:17:33 +00007547 xmlSchemaPIllegalAttrErr(ctxt,
7548 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007549 NULL, (xmlSchemaTypePtr) decl, attr);
William M. Bracke7091952004-05-11 15:09:58 +00007550 }
7551 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007552 }
William M. Bracke7091952004-05-11 15:09:58 +00007553 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007554 * Extract/validate attributes.
7555 */
7556 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007557 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007558 * Process top attributes of global element declarations here.
7559 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007560 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
7561 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007562 xmlSchemaPValAttrQName(ctxt, schema, NULL,
7563 (xmlSchemaTypePtr) decl, node, "substitutionGroup",
7564 &(decl->substGroupNs), &(decl->substGroup));
7565 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007566 node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007567 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007568 /*
7569 * Attribute "final".
7570 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007571 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007572 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007573 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7574 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
7575 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7576 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007577 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007578 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7579 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007580 -1,
7581 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
7582 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007583 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007584 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007585 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
7586 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007587 attrValue, NULL, NULL, NULL);
7588 }
7589 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007590 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007591 /*
7592 * Attribute "block".
7593 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007594 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007595 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007596 /*
7597 * Apply default "block" values.
7598 */
7599 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7600 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
7601 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7602 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
7603 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7604 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007605 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007606 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7607 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007608 -1,
7609 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007610 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007611 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
7612 xmlSchemaPSimpleTypeErr(ctxt,
7613 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007614 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007615 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007616 "restriction | substitution))", attrValue,
7617 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007618 }
7619 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007620 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007621 node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007622 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007623
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007624 attr = xmlSchemaGetPropNode(node, "type");
7625 if (attr != NULL) {
7626 xmlSchemaPValAttrNodeQName(ctxt, schema,
7627 NULL, (xmlSchemaTypePtr) decl, attr,
7628 &(decl->namedTypeNs), &(decl->namedType));
7629 xmlSchemaCheckReference(ctxt, schema, node,
7630 (xmlSchemaBasicItemPtr) decl, decl->namedTypeNs);
7631 }
7632 decl->value = xmlSchemaGetProp(ctxt, node, "default");
7633 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007634 if (attr != NULL) {
7635 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007636 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007637 /*
7638 * 3.3.3 : 1
7639 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007640 */
7641 xmlSchemaPMutualExclAttrErr(ctxt,
7642 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007643 NULL, (xmlSchemaTypePtr) decl, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007644 "default", "fixed");
7645 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007646 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
7647 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007648 }
William M. Bracke7091952004-05-11 15:09:58 +00007649 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007650 /*
7651 * And now for the children...
7652 */
7653 oldcontainer = ctxt->container;
7654 ctxt->container = decl->name;
William M. Bracke7091952004-05-11 15:09:58 +00007655 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007656 /*
7657 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007658 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007659 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007660 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007661 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007662 xmlSchemaPContentErr(ctxt,
7663 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007664 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007665 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007666 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007667 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007668 ELEM_TYPE(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007669 child = child->next;
7670 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007671 /*
7672 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007673 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007674 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007675 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007676 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007677 xmlSchemaPContentErr(ctxt,
7678 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007679 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007680 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007681 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007682 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007683 ELEM_TYPE(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007684 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007685 }
William M. Bracke7091952004-05-11 15:09:58 +00007686 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00007687 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007688 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007689 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007690 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007691 } else if (IS_SCHEMA(child, "key")) {
7692 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007693 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007694 } else if (IS_SCHEMA(child, "keyref")) {
7695 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007696 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007697 }
7698 if (lastIDC != NULL)
7699 lastIDC->next = curIDC;
7700 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007701 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007702 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007703 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00007704 }
7705 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007706 xmlSchemaPContentErr(ctxt,
7707 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007708 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007709 NULL, "(annotation?, ((simpleType | complexType)?, "
7710 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007711 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007712 ctxt->container = oldcontainer;
7713 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007714 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007715 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007716 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00007717 * different layer.
7718 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007719 FREE_AND_NULL(des)
7720 if (topLevel)
7721 return ((xmlSchemaBasicItemPtr) decl);
7722 else {
7723 particle->children = (xmlSchemaTreeItemPtr) decl;
7724 return ((xmlSchemaBasicItemPtr) particle);
7725 }
7726
7727return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007728 FREE_AND_NULL(des);
7729 if (annot != NULL) {
7730 if (particle != NULL)
7731 particle->annot = NULL;
7732 if (decl != NULL)
7733 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007734 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007735 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007736 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007737}
7738
7739/**
7740 * xmlSchemaParseUnion:
7741 * @ctxt: a schema validation context
7742 * @schema: the schema being built
7743 * @node: a subtree containing XML Schema informations
7744 *
7745 * parse a XML schema Union definition
7746 * *WARNING* this interface is highly subject to change
7747 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007748 * Returns -1 in case of internal error, 0 in case of success and a positive
7749 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00007750 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007751static int
Daniel Veillard4255d502002-04-16 15:50:10 +00007752xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007753 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007754{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007755 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007756 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007757 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007758 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007759
7760 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007761 return (-1);
7762 /* Not a component, don't create it. */
7763 type = ctxt->ctxtType;
7764 /*
7765 * Mark the simple type as being of variety "union".
7766 */
7767 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007768 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007769 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7770 * then the ·simple ur-type definition·."
7771 */
7772 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007773 /*
7774 * Check for illegal attributes.
7775 */
7776 attr = node->properties;
7777 while (attr != NULL) {
7778 if (attr->ns == NULL) {
7779 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7780 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007781 xmlSchemaPIllegalAttrErr(ctxt,
7782 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7783 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007784 }
7785 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007786 xmlSchemaPIllegalAttrErr(ctxt,
7787 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7788 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007789 }
7790 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007791 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007792 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007793 /*
7794 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007795 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00007796 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007797 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007798 if (attr != NULL) {
7799 const xmlChar *end;
7800 xmlChar *tmp;
7801 const xmlChar *localName, *nsName;
7802 xmlSchemaTypeLinkPtr link, lastLink = NULL;
7803 xmlSchemaQNameRefPtr ref;
7804
7805 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007806 type->ref = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007807 do {
7808 while (IS_BLANK_CH(*cur))
7809 cur++;
7810 end = cur;
7811 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7812 end++;
7813 if (end == cur)
7814 break;
7815 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007816 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, NULL,
7817 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007818 /*
7819 * Create the member type link.
7820 */
7821 link = (xmlSchemaTypeLinkPtr)
7822 xmlMalloc(sizeof(xmlSchemaTypeLink));
7823 if (link == NULL) {
7824 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
7825 "allocating a type link", NULL);
7826 return (-1);
7827 }
7828 link->type = NULL;
7829 link->next = NULL;
7830 if (lastLink == NULL)
7831 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007832 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007833 lastLink->next = link;
7834 lastLink = link;
7835 /*
7836 * Create a reference item.
7837 */
7838 ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_SIMPLE,
7839 localName, nsName);
7840 if (ref == NULL) {
7841 FREE_AND_NULL(tmp)
7842 return (-1);
7843 }
7844 /*
7845 * Assign the reference to the link, it will be resolved
7846 * later during fixup of the union simple type.
7847 */
7848 link->type = (xmlSchemaTypePtr) ref;
7849 }
7850 FREE_AND_NULL(tmp)
7851 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007852 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007853
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007854 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007855 /*
7856 * And now for the children...
7857 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007858 child = node->children;
7859 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007860 /*
7861 * Add the annotation to the simple type ancestor.
7862 */
7863 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7864 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007865 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007866 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007867 if (IS_SCHEMA(child, "simpleType")) {
7868 xmlSchemaTypePtr subtype, last = NULL;
7869
7870 /*
7871 * Anchor the member types in the "subtypes" field of the
7872 * simple type.
7873 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007874 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007875 subtype = (xmlSchemaTypePtr)
7876 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7877 if (subtype != NULL) {
7878 if (last == NULL) {
7879 type->subtypes = subtype;
7880 last = subtype;
7881 } else {
7882 last->next = subtype;
7883 last = subtype;
7884 }
7885 last->next = NULL;
7886 }
7887 child = child->next;
7888 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007889 }
7890 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007891 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007892 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007893 NULL, NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007894 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007895 if ((attr == NULL) && (type->subtypes == NULL)) {
7896 /*
7897 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007898 * Either the memberTypes [attribute] of the <union> element must
7899 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007900 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007901 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007902 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
7903 NULL, NULL, node,
7904 "Either the attribute 'memberTypes' or "
7905 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007906 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007907 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00007908}
7909
7910/**
7911 * xmlSchemaParseList:
7912 * @ctxt: a schema validation context
7913 * @schema: the schema being built
7914 * @node: a subtree containing XML Schema informations
7915 *
7916 * parse a XML schema List definition
7917 * *WARNING* this interface is highly subject to change
7918 *
William M. Bracke7091952004-05-11 15:09:58 +00007919 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007920 * 1 in case of success.
7921 */
7922static xmlSchemaTypePtr
7923xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007924 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007925{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007926 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007927 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007928 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007929
7930 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7931 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007932 /* Not a component, don't create it. */
7933 type = ctxt->ctxtType;
7934 /*
7935 * Mark the type as being of variety "list".
7936 */
7937 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007938 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007939 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7940 * then the ·simple ur-type definition·."
7941 */
7942 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007943 /*
7944 * Check for illegal attributes.
7945 */
7946 attr = node->properties;
7947 while (attr != NULL) {
7948 if (attr->ns == NULL) {
7949 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7950 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007951 xmlSchemaPIllegalAttrErr(ctxt,
7952 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7953 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007954 }
7955 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007956 xmlSchemaPIllegalAttrErr(ctxt,
7957 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7958 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007959 }
7960 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007961 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007962
7963 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
7964
William M. Brack2f2a6632004-08-20 23:09:47 +00007965 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007966 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
7967 * fields for holding the reference to the itemType.
William M. Brack2f2a6632004-08-20 23:09:47 +00007968 */
7969 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007970 node, "itemType", &(type->refNs), &(type->ref));
William M. Brack2f2a6632004-08-20 23:09:47 +00007971 /*
7972 * And now for the children...
7973 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007974 child = node->children;
7975 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007976 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7977 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007978 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007979 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007980 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007981 /*
7982 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007983 * Either the itemType [attribute] or the <simpleType> [child] of
7984 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007985 */
7986 if (type->ref != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007987 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00007988 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007989 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00007990 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007991 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007992 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007993 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00007994 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007995 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007996 } else if (type->ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007997 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007998 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007999 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008000 "Either the attribute 'itemType' or the <simpleType> child "
8001 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008002 }
8003 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008004 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008005 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008006 NULL, NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008007 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008008 if ((type->ref == NULL) &&
8009 (type->subtypes == NULL) &&
8010 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008011 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008012 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008013 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008014 "Either the attribute 'itemType' or the <simpleType> child "
8015 "must be present", NULL);
8016 }
8017 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008018}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008019
Daniel Veillard4255d502002-04-16 15:50:10 +00008020/**
8021 * xmlSchemaParseSimpleType:
8022 * @ctxt: a schema validation context
8023 * @schema: the schema being built
8024 * @node: a subtree containing XML Schema informations
8025 *
8026 * parse a XML schema Simple Type definition
8027 * *WARNING* this interface is highly subject to change
8028 *
William M. Bracke7091952004-05-11 15:09:58 +00008029 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00008030 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00008031 */
8032static xmlSchemaTypePtr
8033xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008034 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008035{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008036 xmlSchemaTypePtr type, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008037 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008038 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008039 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008040
8041 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8042 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008043
Daniel Veillardc0826a72004-08-10 14:17:33 +00008044 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008045 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008046 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008047 xmlSchemaPMissingAttrErr(ctxt,
8048 XML_SCHEMAP_S4S_ATTR_MISSING,
8049 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008050 "name", NULL);
8051 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008052 } else {
8053 if (xmlSchemaPValAttrNode(ctxt,
8054 NULL, NULL, attr,
8055 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
8056 return (NULL);
8057 /*
8058 * Skip built-in types.
8059 */
8060 if (ctxt->isS4S) {
8061 xmlSchemaTypePtr biType;
8062
8063 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
8064 if (biType != NULL)
8065 return (biType);
8066 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008067 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008068 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008069
Daniel Veillardc0826a72004-08-10 14:17:33 +00008070 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008071 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00008072
Daniel Veillard01fa6152004-06-29 17:04:39 +00008073 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008074 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008075 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008076 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008077 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008078 if (type == NULL)
8079 return (NULL);
8080 type->node = node;
8081 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008082 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008083 /*
8084 * Check for illegal attributes.
8085 */
8086 attr = node->properties;
8087 while (attr != NULL) {
8088 if (attr->ns == NULL) {
8089 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008090 xmlSchemaPIllegalAttrErr(ctxt,
8091 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8092 NULL, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008093 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008094 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008095 xmlSchemaPIllegalAttrErr(ctxt,
8096 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8097 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008098 }
8099 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008100 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008101 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008102 /*
8103 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008104 *
8105 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008106 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008107 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008108 if (type == NULL)
8109 return (NULL);
8110 type->node = node;
8111 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008112 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008113 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8114 /*
8115 * Check for illegal attributes.
8116 */
8117 attr = node->properties;
8118 while (attr != NULL) {
8119 if (attr->ns == NULL) {
8120 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8121 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008122 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008123 xmlSchemaPIllegalAttrErr(ctxt,
8124 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8125 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008126 }
8127 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008128 xmlSchemaPIllegalAttrErr(ctxt,
8129 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8130 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008131 }
8132 attr = attr->next;
8133 }
8134 /*
8135 * Attribute "final".
8136 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008137 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008138 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008139 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8140 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
8141 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8142 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
8143 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8144 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008145 } else {
8146 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008147 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8148 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008149 XML_SCHEMAS_TYPE_FINAL_LIST,
8150 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
8151
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008152 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008153 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008154 type, (xmlNodePtr) attr,
8155 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008156 attrValue, NULL, NULL, NULL);
8157 }
8158 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008159 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008160 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008161 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008162 /*
8163 * And now for the children...
8164 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008165 oldCtxtType = ctxt->ctxtType;
8166 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008167 ctxt->ctxtType = type;
8168 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008169 child = node->children;
8170 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008171 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8172 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008173 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008174 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008175 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
8176 NULL, type, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008177 "(annotation?, (restriction | list | union))");
8178 } else if (IS_SCHEMA(child, "restriction")) {
8179 xmlSchemaParseRestriction(ctxt, schema, child,
8180 XML_SCHEMA_TYPE_SIMPLE);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008181 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008182 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008183 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008184 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008185 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008186 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008187 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008188 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008189 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008190 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8191 NULL, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008192 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008193 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008194 ctxt->parentItem = oldParentItem;
8195 ctxt->ctxtType = oldCtxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008196
Daniel Veillard4255d502002-04-16 15:50:10 +00008197 return (type);
8198}
8199
Daniel Veillard4255d502002-04-16 15:50:10 +00008200/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008201 * xmlSchemaParseModelGroupDefRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00008202 * @ctxt: a schema validation context
8203 * @schema: the schema being built
8204 * @node: a subtree containing XML Schema informations
8205 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008206 * Parses a XML schema particle (reference to a model group definition).
Daniel Veillard4255d502002-04-16 15:50:10 +00008207 * *WARNING* this interface is highly subject to change
8208 *
William M. Bracke7091952004-05-11 15:09:58 +00008209 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008210 * 1 in case of success.
8211 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008212static xmlSchemaTreeItemPtr
8213xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
8214 xmlSchemaPtr schema,
8215 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008216{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008217 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008218 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008219 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008220 const xmlChar *ref = NULL, *refNs = NULL;
8221 int min, max;
8222
8223 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008224 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008225
8226 attr = xmlSchemaGetPropNode(node, "ref");
8227 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008228 xmlSchemaPMissingAttrErr(ctxt,
8229 XML_SCHEMAP_S4S_ATTR_MISSING,
8230 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008231 "ref", NULL);
8232 return (NULL);
8233 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008234 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008235 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008236 }
8237 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008238 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008239 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008240 /*
8241 * Check for illegal attributes.
8242 */
8243 attr = node->properties;
8244 while (attr != NULL) {
8245 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008246 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008247 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8248 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8249 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008250 xmlSchemaPIllegalAttrErr(ctxt,
8251 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8252 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008253 }
8254 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008255 xmlSchemaPIllegalAttrErr(ctxt,
8256 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8257 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008258 }
8259 attr = attr->next;
8260 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008261 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008262 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8263 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008264 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008265 /*
8266 * Create a reference item as the term; it will be substituted for
8267 * the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008268 */
8269 item->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008270 xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_GROUP, ref, refNs);
8271 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) item, refNs);
8272 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
8273 /*
8274 * And now for the children...
8275 */
8276 child = node->children;
8277 /* TODO: Is annotation even allowed for a model group reference? */
8278 if (IS_SCHEMA(child, "annotation")) {
8279 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008280 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008281 */
8282 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8283 child = child->next;
8284 }
8285 if (child != NULL) {
8286 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008287 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008288 NULL, NULL, node, child, NULL,
8289 "(annotation?)");
8290 }
8291 /*
8292 * Corresponds to no component at all if minOccurs==maxOccurs==0.
8293 */
8294 if ((min == 0) && (max == 0))
8295 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008296 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008297 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
8298 return ((xmlSchemaTreeItemPtr) item);
8299}
8300
8301/**
8302 * xmlSchemaParseModelGroupDefinition:
8303 * @ctxt: a schema validation context
8304 * @schema: the schema being built
8305 * @node: a subtree containing XML Schema informations
8306 *
8307 * Parses a XML schema model group definition.
8308 * *WARNING* this interface is highly subject to change
8309 *
8310 * Returns -1 in case of error, 0 if the declaration is improper and
8311 * 1 in case of success.
8312 */
8313static xmlSchemaModelGroupDefPtr
8314xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
8315 xmlSchemaPtr schema,
8316 xmlNodePtr node)
8317{
8318 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008319 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008320 xmlAttrPtr attr;
8321 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008322
8323 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008324 return (NULL);
8325
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008326 attr = xmlSchemaGetPropNode(node, "name");
8327 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008328 xmlSchemaPMissingAttrErr(ctxt,
8329 XML_SCHEMAP_S4S_ATTR_MISSING,
8330 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008331 "name", NULL);
8332 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008333 } else if (xmlSchemaPValAttrNode(ctxt,
8334 NULL, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008335 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8336 return (NULL);
8337 }
8338 item = xmlSchemaAddGroup(ctxt, schema, name, schema->targetNamespace, node);
8339 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008340 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008341 /*
8342 * Check for illegal attributes.
8343 */
8344 attr = node->properties;
8345 while (attr != NULL) {
8346 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008347 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008348 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008349 xmlSchemaPIllegalAttrErr(ctxt,
8350 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8351 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008352 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008353 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008354 xmlSchemaPIllegalAttrErr(ctxt,
8355 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8356 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008357 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008358 attr = attr->next;
8359 }
8360 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8361 /*
8362 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008363 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008364 child = node->children;
8365 if (IS_SCHEMA(child, "annotation")) {
8366 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8367 child = child->next;
8368 }
8369 if (IS_SCHEMA(child, "all")) {
8370 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8371 XML_SCHEMA_TYPE_ALL, 0);
8372 child = child->next;
8373 } else if (IS_SCHEMA(child, "choice")) {
8374 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8375 XML_SCHEMA_TYPE_CHOICE, 0);
8376 child = child->next;
8377 } else if (IS_SCHEMA(child, "sequence")) {
8378 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8379 XML_SCHEMA_TYPE_SEQUENCE, 0);
8380 child = child->next;
8381 }
8382 if (child != NULL) {
8383 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008384 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8385 NULL, NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008386 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008387 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008388
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008389 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00008390}
8391
8392/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008393 * xmlSchemaCleanupDoc:
8394 * @ctxt: a schema validation context
8395 * @node: the root of the document.
8396 *
8397 * removes unwanted nodes in a schemas document tree
8398 */
8399static void
8400xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
8401{
8402 xmlNodePtr delete, cur;
8403
8404 if ((ctxt == NULL) || (root == NULL)) return;
8405
8406 /*
8407 * Remove all the blank text nodes
8408 */
8409 delete = NULL;
8410 cur = root;
8411 while (cur != NULL) {
8412 if (delete != NULL) {
8413 xmlUnlinkNode(delete);
8414 xmlFreeNode(delete);
8415 delete = NULL;
8416 }
8417 if (cur->type == XML_TEXT_NODE) {
8418 if (IS_BLANK_NODE(cur)) {
8419 if (xmlNodeGetSpacePreserve(cur) != 1) {
8420 delete = cur;
8421 }
8422 }
8423 } else if ((cur->type != XML_ELEMENT_NODE) &&
8424 (cur->type != XML_CDATA_SECTION_NODE)) {
8425 delete = cur;
8426 goto skip_children;
8427 }
8428
8429 /*
8430 * Skip to next node
8431 */
8432 if (cur->children != NULL) {
8433 if ((cur->children->type != XML_ENTITY_DECL) &&
8434 (cur->children->type != XML_ENTITY_REF_NODE) &&
8435 (cur->children->type != XML_ENTITY_NODE)) {
8436 cur = cur->children;
8437 continue;
8438 }
8439 }
8440 skip_children:
8441 if (cur->next != NULL) {
8442 cur = cur->next;
8443 continue;
8444 }
8445
8446 do {
8447 cur = cur->parent;
8448 if (cur == NULL)
8449 break;
8450 if (cur == root) {
8451 cur = NULL;
8452 break;
8453 }
8454 if (cur->next != NULL) {
8455 cur = cur->next;
8456 break;
8457 }
8458 } while (cur != NULL);
8459 }
8460 if (delete != NULL) {
8461 xmlUnlinkNode(delete);
8462 xmlFreeNode(delete);
8463 delete = NULL;
8464 }
8465}
8466
William M. Brack2f2a6632004-08-20 23:09:47 +00008467
8468/**
8469 * xmlSchemaImportSchema
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008470 *
William M. Brack2f2a6632004-08-20 23:09:47 +00008471 * @ctxt: a schema validation context
8472 * @schemaLocation: an URI defining where to find the imported schema
8473 *
8474 * import a XML schema
8475 * *WARNING* this interface is highly subject to change
8476 *
8477 * Returns -1 in case of error and 1 in case of success.
8478 */
8479#if 0
8480static xmlSchemaImportPtr
8481xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
8482 const xmlChar *schemaLocation)
8483{
8484 xmlSchemaImportPtr import;
8485 xmlSchemaParserCtxtPtr newctxt;
8486
8487 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8488 if (newctxt == NULL) {
8489 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
8490 NULL);
8491 return (NULL);
8492 }
8493 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
8494 /* Keep the same dictionnary for parsing, really */
8495 xmlDictReference(ctxt->dict);
8496 newctxt->dict = ctxt->dict;
8497 newctxt->includes = 0;
8498 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
8499
8500 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
8501 ctxt->userData);
8502
8503 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8504 if (import == NULL) {
8505 xmlSchemaPErrMemory(NULL, "allocating imported schema",
8506 NULL);
8507 xmlSchemaFreeParserCtxt(newctxt);
8508 return (NULL);
8509 }
8510
8511 memset(import, 0, sizeof(xmlSchemaImport));
8512 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8513 import->schema = xmlSchemaParse(newctxt);
8514
8515 if (import->schema == NULL) {
8516 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008517 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008518 "Failed to import schema from location \"%s\".\n",
8519 schemaLocation, NULL);
8520
8521 xmlSchemaFreeParserCtxt(newctxt);
8522 /* The schemaLocation is held by the dictionary.
8523 if (import->schemaLocation != NULL)
8524 xmlFree((xmlChar *)import->schemaLocation);
8525 */
8526 xmlFree(import);
8527 return NULL;
8528 }
8529
8530 xmlSchemaFreeParserCtxt(newctxt);
8531 return import;
8532}
8533#endif
8534
8535static void
8536xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
8537{
8538 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8539 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
8540
8541 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
8542 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
8543
8544 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8545 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
8546 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8547 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
8548 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8549 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
8550 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8551 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
8552
8553 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8554 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
8555 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8556 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
8557 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8558 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
8559}
8560
8561static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008562xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008563 xmlSchemaPtr schema,
8564 xmlNodePtr node)
8565{
8566 xmlAttrPtr attr;
8567 const xmlChar *val;
8568
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008569 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8570 if (schema->version == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008571 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008572 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8573 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008574 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008575 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), NULL);
8576
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008577 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008578 if (attr != NULL) {
8579 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008580 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008581 XML_SCHEMAS_QUALIF_ELEM) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008582 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008583 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008584 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008585 "(qualified | unqualified)", val, NULL, NULL, NULL);
8586 }
8587 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008588
8589 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008590 if (attr != NULL) {
8591 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008592 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008593 XML_SCHEMAS_QUALIF_ATTR) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008594 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008595 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008596 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008597 "(qualified | unqualified)", val, NULL, NULL, NULL);
8598 }
8599 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008600
8601 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008602 if (attr != NULL) {
8603 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8604 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8605 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
8606 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
8607 -1,
8608 XML_SCHEMAS_FINAL_DEFAULT_LIST,
8609 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
8610 xmlSchemaPSimpleTypeErr(ctxt,
8611 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008612 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008613 "(#all | List of (extension | restriction | list | union))",
8614 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008615 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008616 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008617
8618 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008619 if (attr != NULL) {
8620 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8621 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8622 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
8623 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
8624 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
8625 xmlSchemaPSimpleTypeErr(ctxt,
8626 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008627 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008628 "(#all | List of (extension | restriction | substitution))",
8629 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008630 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008631 }
8632}
8633
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008634/**
8635 * xmlSchemaParseSchemaTopLevel:
8636 * @ctxt: a schema validation context
8637 * @schema: the schemas
8638 * @nodes: the list of top level nodes
8639 *
8640 * Returns the internal XML Schema structure built from the resource or
8641 * NULL in case of error
8642 */
8643static void
8644xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
8645 xmlSchemaPtr schema, xmlNodePtr nodes)
8646{
8647 xmlNodePtr child;
8648 xmlSchemaAnnotPtr annot;
8649
8650 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
8651 return;
8652
8653 child = nodes;
8654 while ((IS_SCHEMA(child, "include")) ||
8655 (IS_SCHEMA(child, "import")) ||
8656 (IS_SCHEMA(child, "redefine")) ||
8657 (IS_SCHEMA(child, "annotation"))) {
8658 if (IS_SCHEMA(child, "annotation")) {
8659 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8660 if (schema->annot == NULL)
8661 schema->annot = annot;
8662 else
8663 xmlSchemaFreeAnnot(annot);
8664 } else if (IS_SCHEMA(child, "import")) {
8665 xmlSchemaParseImport(ctxt, schema, child);
8666 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008667 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008668 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008669 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008670 } else if (IS_SCHEMA(child, "redefine")) {
8671 TODO
8672 }
8673 child = child->next;
8674 }
8675 while (child != NULL) {
8676 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008677 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008678 child = child->next;
8679 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008680 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008681 child = child->next;
8682 } else if (IS_SCHEMA(child, "element")) {
8683 xmlSchemaParseElement(ctxt, schema, child, 1);
8684 child = child->next;
8685 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00008686 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008687 child = child->next;
8688 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008689 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008690 child = child->next;
8691 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008692 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008693 child = child->next;
8694 } else if (IS_SCHEMA(child, "notation")) {
8695 xmlSchemaParseNotation(ctxt, schema, child);
8696 child = child->next;
8697 } else {
8698 xmlSchemaPErr2(ctxt, NULL, child,
8699 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008700 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008701 child->name, NULL);
8702 child = child->next;
8703 }
8704 while (IS_SCHEMA(child, "annotation")) {
8705 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8706 if (schema->annot == NULL)
8707 schema->annot = annot;
8708 else
8709 xmlSchemaFreeAnnot(annot);
8710 child = child->next;
8711 }
8712 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008713 ctxt->parentItem = NULL;
8714 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008715}
8716
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008717static xmlSchemaImportPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008718xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008719 xmlHashTablePtr *imports,
8720 const xmlChar *nsName)
8721{
8722 xmlSchemaImportPtr ret;
8723
8724 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00008725 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008726 if (*imports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008727 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008728 XML_SCHEMAP_FAILED_BUILD_IMPORT,
8729 NULL, NULL, (xmlNodePtr) ctxt->doc,
8730 "Internal error: failed to build the import table",
8731 NULL);
8732 return (NULL);
8733 }
8734 }
8735 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8736 if (ret == NULL) {
8737 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
8738 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008739 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008740 memset(ret, 0, sizeof(xmlSchemaImport));
8741 if (nsName == NULL)
8742 nsName = XML_SCHEMAS_NO_NAMESPACE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008743 xmlHashAddEntry(*imports, nsName, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008744
8745 return (ret);
8746}
8747
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008748/**
8749 * xmlSchemaNewParserCtxtUseDict:
8750 * @URL: the location of the schema
8751 * @dict: the dictionary to be used
8752 *
8753 * Create an XML Schemas parse context for that file/resource expected
8754 * to contain an XML Schemas file.
8755 *
8756 * Returns the parser context or NULL in case of error
8757 */
8758static xmlSchemaParserCtxtPtr
8759xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
8760{
8761 xmlSchemaParserCtxtPtr ret;
8762 /*
8763 if (URL == NULL)
8764 return (NULL);
8765 */
8766
8767 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8768 if (ret == NULL) {
8769 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8770 NULL);
8771 return (NULL);
8772 }
8773 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8774 ret->dict = dict;
8775 xmlDictReference(dict);
8776 if (URL != NULL)
8777 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
8778 ret->includes = 0;
8779 return (ret);
8780}
8781
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008782static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008783xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
8784{
8785 if (vctxt->pctxt == NULL) {
8786 if (vctxt->schema != NULL)
8787 vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
8788 else
8789 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
8790 if (vctxt->pctxt == NULL) {
8791 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
8792 "failed to create a temp. parser context");
8793 return (-1);
8794 }
8795 /* TODO: Pass user data. */
8796 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
8797 }
8798 return (0);
8799}
8800
8801static int
8802xmlSchemaAcquireSchemaDoc(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008803 xmlSchemaPtr schema,
8804 xmlNodePtr node,
8805 const xmlChar *nsName,
8806 const xmlChar *location,
8807 xmlDocPtr *doc,
8808 const xmlChar **targetNamespace,
8809 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008810{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008811 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008812 xmlParserCtxtPtr parserCtxt;
8813 xmlSchemaImportPtr import;
8814 const xmlChar *ns;
8815 xmlNodePtr root;
8816
8817 /*
8818 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
8819 * <xsi:noNamespaceSchemaLocation>.
8820 */
8821 *doc = NULL;
8822 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008823 * Given that the schemaLocation [attribute] is only a hint, it is open
8824 * to applications to ignore all but the first <import> for a given
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008825 * namespace, regardless of the ·actual value· of schemaLocation, but
8826 * such a strategy risks missing useful information when new
8827 * schemaLocations are offered.
8828 *
8829 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
8830 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
8831 * valid or not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008832 * We will follow XSV here.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008833 */
8834 if (location == NULL) {
8835 /*
8836 * Schema Document Location Strategy:
8837 *
8838 * 3 Based on the namespace name, identify an existing schema document,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008839 * either as a resource which is an XML document or a <schema> element
8840 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008841 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008842 * 5 Attempt to resolve the namespace name to locate such a resource.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008843 *
8844 * NOTE: Those stategies are not supported, so we will skip.
8845 */
8846 return (0);
8847 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008848 if (nsName == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008849 ns = XML_SCHEMAS_NO_NAMESPACE;
8850 else
8851 ns = nsName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008852
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008853 import = xmlHashLookup(schema->schemasImports, ns);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008854 if (import != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008855 /*
8856 * There was a valid resource for the specified namespace already
8857 * defined, so skip.
8858 * TODO: This might be changed someday to allow import of
8859 * components from multiple documents for a single target namespace.
8860 */
8861 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008862 }
8863 if (actxt->type == XML_SCHEMA_CTXT_PARSER)
8864 pctxt = (xmlSchemaParserCtxtPtr) actxt;
8865 else {
8866 xmlSchemaCreatePCtxtOnVCtxt((xmlSchemaValidCtxtPtr) actxt);
8867 pctxt = ((xmlSchemaValidCtxtPtr) actxt)->pctxt;
8868 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008869 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008870 * Schema Document Location Strategy:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008871 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008872 * 2 Based on the location URI, identify an existing schema document,
8873 * either as a resource which is an XML document or a <schema> element
8874 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008875 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008876 * 4 Attempt to resolve the location URI, to locate a resource on the
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008877 * web which is or contains or references a <schema> element;
8878 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
8879 *
8880 */
8881 if ((absolute == 0) && (node != NULL)) {
8882 xmlChar *base, *URI;
8883
8884 base = xmlNodeGetBase(node->doc, node);
8885 if (base == NULL) {
8886 URI = xmlBuildURI(location, node->doc->URL);
8887 } else {
8888 URI = xmlBuildURI(location, base);
8889 xmlFree(base);
8890 }
8891 if (URI != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008892 location = xmlDictLookup(pctxt->dict, URI, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008893 xmlFree(URI);
8894 }
8895 }
8896 parserCtxt = xmlNewParserCtxt();
8897 if (parserCtxt == NULL) {
8898 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
8899 "allocating a parser context", NULL);
8900 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008901 }
8902 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008903 xmlDictFree(parserCtxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008904 parserCtxt->dict = pctxt->dict;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008905 xmlDictReference(parserCtxt->dict);
8906 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008907 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008908 NULL, SCHEMAS_PARSE_OPTIONS);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008909 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008910 * 2.1 The referent is (a fragment of) a resource which is an
8911 * XML document (see clause 1.1), which in turn corresponds to
8912 * a <schema> element information item in a well-formed information
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008913 * set, which in turn corresponds to a valid schema.
8914 * TODO: What to do with the "fragment" stuff?
8915 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008916 * 2.2 The referent is a <schema> element information item in
8917 * a well-formed information set, which in turn corresponds
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008918 * to a valid schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008919 * NOTE: 2.2 won't apply, since only XML documents will be processed
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008920 * here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008921 */
8922 if (*doc == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008923 xmlErrorPtr lerr;
8924 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008925 * It is *not* an error for the application schema reference
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008926 * strategy to fail.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008927 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008928 * If the doc is NULL and the parser error is an IO error we
8929 * will assume that the resource could not be located or accessed.
8930 *
8931 * TODO: Try to find specific error codes to react only on
8932 * localisation failures.
8933 *
8934 * TODO, FIXME: Check the spec: is a namespace added to the imported
8935 * namespaces, even if the schemaLocation did not provide
8936 * a resource? I guess so, since omitting the "schemaLocation"
8937 * attribute, imports a namespace as well.
8938 */
8939 lerr = xmlGetLastError();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008940 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008941 xmlFreeParserCtxt(parserCtxt);
8942 return(0);
8943 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008944 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008945 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008946 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008947 "Failed to parse the resource '%s' for import",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008948 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008949 xmlFreeParserCtxt(parserCtxt);
8950 return(XML_SCHEMAP_SRC_IMPORT_2_1);
8951 }
8952 xmlFreeParserCtxt(parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008953
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008954 root = xmlDocGetRootElement(*doc);
8955 if (root == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008956 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008957 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008958 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008959 "The XML document '%s' to be imported has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008960 "element", location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008961 xmlFreeDoc(*doc);
8962 *doc = NULL;
8963 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008964 }
8965
8966 xmlSchemaCleanupDoc(pctxt, root);
8967
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008968 if (!IS_SCHEMA(root, "schema")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008969 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008970 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008971 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008972 "The XML document '%s' to be imported is not a XML schema document",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008973 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008974 xmlFreeDoc(*doc);
8975 *doc = NULL;
8976 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008977 }
8978 *targetNamespace = xmlSchemaGetProp(pctxt, root, "targetNamespace");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008979 /*
8980 * Schema Representation Constraint: Import Constraints and Semantics
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008981 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008982 if (nsName == NULL) {
8983 if (*targetNamespace != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008984 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008985 XML_SCHEMAP_SRC_IMPORT_3_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008986 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008987 "The XML schema to be imported is not expected "
8988 "to have a target namespace; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008989 "its target namespace of '%s'", *targetNamespace, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008990 xmlFreeDoc(*doc);
8991 *doc = NULL;
8992 return (XML_SCHEMAP_SRC_IMPORT_3_2);
8993 }
8994 } else {
8995 if (*targetNamespace == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008996 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008997 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008998 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008999 "The XML schema to be imported is expected to have a target "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009000 "namespace of '%s'", nsName, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009001 xmlFreeDoc(*doc);
9002 *doc = NULL;
9003 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9004 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009005 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009006 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009007 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009008 "The XML schema to be imported is expected to have a "
9009 "target namespace of '%s'; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009010 "its target namespace of '%s'",
9011 nsName, *targetNamespace);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009012 xmlFreeDoc(*doc);
9013 *doc = NULL;
9014 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9015 }
9016 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009017 import = xmlSchemaAddImport(pctxt, &(schema->schemasImports), nsName);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009018 if (import == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009019 AERROR_INT("xmlSchemaAcquireSchemaDoc",
9020 "failed to build import table");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009021 xmlFreeDoc(*doc);
9022 *doc = NULL;
9023 return (-1);
9024 }
9025 import->schemaLocation = location;
9026 import->doc = *doc;
9027 return (0);
9028}
William M. Brack2f2a6632004-08-20 23:09:47 +00009029
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009030static void
9031xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
9032 xmlSchemaPtr schema,
9033 const xmlChar *targetNamespace,
9034 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009035{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009036 const xmlChar *oldURL, **oldLocImps, *oldTNS;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009037 int oldFlags, oldNumLocImps, oldSizeLocImps, oldIsS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009038
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009039 /*
9040 * Save and reset the context & schema.
9041 */
9042 oldURL = pctxt->URL;
9043 /* TODO: Is using the doc->URL here correct? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009044 pctxt->URL = node->doc->URL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009045 oldLocImps = pctxt->localImports;
9046 pctxt->localImports = NULL;
9047 oldNumLocImps = pctxt->nbLocalImports;
9048 pctxt->nbLocalImports = 0;
9049 oldSizeLocImps = pctxt->sizeLocalImports;
9050 pctxt->sizeLocalImports = 0;
9051 oldFlags = schema->flags;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009052 oldIsS4S = pctxt->isS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009053 xmlSchemaClearSchemaDefaults(schema);
9054 oldTNS = schema->targetNamespace;
9055 schema->targetNamespace = targetNamespace;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009056 if ((targetNamespace != NULL) &&
9057 xmlStrEqual(targetNamespace, xmlSchemaNs)) {
9058 /*
9059 * We are parsing the schema for schema!
9060 */
9061 pctxt->isS4S = 1;
9062 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009063 /*
9064 * Parse the schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009065 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009066 xmlSchemaParseSchemaDefaults(pctxt, schema, node);
9067 xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
9068 /*
9069 * Restore the context & schema.
9070 */
9071 schema->flags = oldFlags;
9072 schema->targetNamespace = oldTNS;
9073 if (pctxt->localImports != NULL)
9074 xmlFree((xmlChar *) pctxt->localImports);
9075 pctxt->localImports = oldLocImps;
9076 pctxt->nbLocalImports = oldNumLocImps;
9077 pctxt->sizeLocalImports = oldSizeLocImps;
9078 pctxt->URL = oldURL;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009079 pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009080}
9081
William M. Brack2f2a6632004-08-20 23:09:47 +00009082/**
9083 * xmlSchemaParseImport:
9084 * @ctxt: a schema validation context
9085 * @schema: the schema being built
9086 * @node: a subtree containing XML Schema informations
9087 *
9088 * parse a XML schema Import definition
9089 * *WARNING* this interface is highly subject to change
9090 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009091 * Returns 0 in case of success, a positive error code if
9092 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +00009093 */
9094static int
9095xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9096 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009097{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009098 xmlNodePtr child;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009099 const xmlChar *namespaceName = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009100 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009101 const xmlChar *targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00009102 xmlAttrPtr attr;
9103 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009104 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009105
9106 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9107 return (-1);
9108
9109 /*
9110 * Check for illegal attributes.
9111 */
9112 attr = node->properties;
9113 while (attr != NULL) {
9114 if (attr->ns == NULL) {
9115 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9116 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
9117 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009118 xmlSchemaPIllegalAttrErr(ctxt,
9119 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9120 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009121 }
9122 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009123 xmlSchemaPIllegalAttrErr(ctxt,
9124 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9125 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009126 }
9127 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009128 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009129 /*
9130 * Extract and validate attributes.
9131 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009132 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9133 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009134 &namespaceName) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009135 xmlSchemaPSimpleTypeErr(ctxt,
9136 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
9137 NULL, node,
9138 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009139 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009140 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
9141 }
9142
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009143 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9144 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +00009145 &schemaLocation) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009146 xmlSchemaPSimpleTypeErr(ctxt,
9147 XML_SCHEMAP_IMPORT_SCHEMA_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_SCHEMA_NOT_URI);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009152 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009153 /*
9154 * And now for the children...
9155 */
9156 child = node->children;
9157 if (IS_SCHEMA(child, "annotation")) {
9158 /*
9159 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009160 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +00009161 */
9162 child = child->next;
9163 }
9164 if (child != NULL) {
9165 xmlSchemaPContentErr(ctxt,
9166 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
9167 NULL, NULL, node, child, NULL,
9168 "(annotation?)");
9169 }
9170 /*
9171 * Apply additional constraints.
9172 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009173 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009174 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009175 * 1.1 If the namespace [attribute] is present, then its ·actual value·
9176 * must not match the ·actual value· of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +00009177 * targetNamespace [attribute].
9178 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009179 if (xmlStrEqual(schema->targetNamespace, namespaceName)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009180 xmlSchemaPCustomErr(ctxt,
9181 XML_SCHEMAP_SRC_IMPORT_1_1,
9182 NULL, NULL, node,
9183 "The value of the attribute 'namespace' must not match "
9184 "the target namespace '%s' of the importing schema",
9185 schema->targetNamespace);
9186 return (XML_SCHEMAP_SRC_IMPORT_1_1);
9187 }
9188 } else {
9189 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009190 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +00009191 * <schema> must have a targetNamespace [attribute].
9192 */
9193 if (schema->targetNamespace == NULL) {
9194 xmlSchemaPCustomErr(ctxt,
9195 XML_SCHEMAP_SRC_IMPORT_1_2,
9196 NULL, NULL, node,
9197 "The attribute 'namespace' must be existent if "
9198 "the importing schema has no target namespace",
9199 NULL);
9200 return (XML_SCHEMAP_SRC_IMPORT_1_2);
9201 }
9202 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009203 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009204 * Add the namespace to the list of locally imported namespace.
9205 */
9206 if (ctxt->localImports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009207 ctxt->localImports = (const xmlChar **) xmlMalloc(10 *
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009208 sizeof(const xmlChar*));
9209 ctxt->sizeLocalImports = 10;
9210 ctxt->nbLocalImports = 0;
9211 } else if (ctxt->sizeLocalImports <= ctxt->nbLocalImports) {
9212 ctxt->sizeLocalImports *= 2;
9213 ctxt->localImports = (const xmlChar **) xmlRealloc(
9214 (xmlChar **) ctxt->localImports,
9215 ctxt->sizeLocalImports * sizeof(const xmlChar*));
9216 }
9217 ctxt->localImports[ctxt->nbLocalImports++] = namespaceName;
9218 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009219 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00009220 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009221 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) ctxt,
9222 schema, node, namespaceName,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009223 schemaLocation, &doc, &targetNamespace, 0);
9224 if (ret != 0) {
9225 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00009226 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009227 return (ret);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009228 } else if (doc != NULL) {
9229 xmlSchemaParseForImpInc(ctxt, schema, targetNamespace,
9230 xmlDocGetRootElement(doc));
William M. Brack2f2a6632004-08-20 23:09:47 +00009231 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009232
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009233 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009234}
9235
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009236/**
9237 * xmlSchemaParseInclude:
9238 * @ctxt: a schema validation context
9239 * @schema: the schema being built
9240 * @node: a subtree containing XML Schema informations
9241 *
9242 * parse a XML schema Include definition
9243 *
William M. Bracke7091952004-05-11 15:09:58 +00009244 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009245 * 1 in case of success.
9246 */
9247static int
9248xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9249 xmlNodePtr node)
9250{
9251 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009252 const xmlChar *schemaLocation, *targetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009253 xmlDocPtr doc = NULL;
9254 xmlNodePtr root = NULL;
Daniel Veillardcffc1c72005-03-12 18:54:55 +00009255 xmlSchemaIncludePtr include = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009256 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009257 xmlAttrPtr attr;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009258 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009259
9260
9261 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9262 return (-1);
9263
9264 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009265 * Check for illegal attributes.
9266 */
9267 attr = node->properties;
9268 while (attr != NULL) {
9269 if (attr->ns == NULL) {
9270 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9271 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009272 xmlSchemaPIllegalAttrErr(ctxt,
9273 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9274 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009275 }
9276 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009277 xmlSchemaPIllegalAttrErr(ctxt,
9278 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9279 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009280 }
9281 attr = attr->next;
9282 }
9283 /*
9284 * Extract and validate attributes.
9285 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009286 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009287 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009288 * Preliminary step, extract the URI-Reference for the include and
9289 * make an URI from the base.
9290 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009291 attr = xmlSchemaGetPropNode(node, "schemaLocation");
9292 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009293 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009294 xmlChar *uri = NULL;
9295
9296 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9297 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009298 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009299 base = xmlNodeGetBase(node->doc, node);
9300 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009301 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009302 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00009303 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009304 xmlFree(base);
9305 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009306 if (uri == NULL) {
9307 xmlSchemaPErr(ctxt,
9308 node,
9309 XML_SCHEMAP_INTERNAL,
9310 "Internal error: xmlSchemaParseInclude, "
9311 "could not build an URI from the schemaLocation.\n",
9312 NULL, NULL);
9313 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009314 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009315 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
9316 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009317 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009318 xmlSchemaPMissingAttrErr(ctxt,
9319 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
9320 NULL, node, "schemaLocation", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009321 goto exit_invalid;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009322 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009323 /*
9324 * And now for the children...
9325 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009326 child = node->children;
9327 while (IS_SCHEMA(child, "annotation")) {
9328 /*
9329 * the annotations here are simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009330 * TODO: really?
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009331 */
9332 child = child->next;
9333 }
9334 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009335 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009336 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
9337 NULL, NULL, node, child, NULL,
9338 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009339 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009340 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009341 * Report self-inclusion.
9342 */
9343 if (xmlStrEqual(schemaLocation, ctxt->URL)) {
9344 xmlSchemaPCustomErr(ctxt,
9345 XML_SCHEMAP_SRC_INCLUDE,
9346 NULL, NULL, node,
9347 "The schema document '%s' cannot include itself.",
9348 schemaLocation);
9349 return (XML_SCHEMAP_SRC_INCLUDE);
9350 }
9351 /*
9352 * Check if this one was already processed to avoid incorrect
9353 * duplicate component errors and infinite circular inclusion.
9354 */
9355 include = schema->includes;
9356 while (include != NULL) {
9357 if (xmlStrEqual(include->schemaLocation, schemaLocation)) {
9358 targetNamespace = include->origTargetNamespace;
9359 if (targetNamespace == NULL) {
9360 /*
9361 * Chameleon include: skip only if it was build for
9362 * the targetNamespace of the including schema.
9363 */
9364 if (xmlStrEqual(schema->targetNamespace,
9365 include->targetNamespace)) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009366 goto check_targetNamespace;
9367 }
9368 } else {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009369 goto check_targetNamespace;
9370 }
9371 }
9372 include = include->next;
9373 }
9374 /*
9375 * First step is to parse the input document into an DOM/Infoset
9376 * TODO: Use xmlCtxtReadFile to share the dictionary?
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009377 */
9378 parserCtxt = xmlNewParserCtxt();
9379 if (parserCtxt == NULL) {
9380 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
9381 "allocating a parser context", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009382 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009383 }
9384
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009385 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
9386 xmlDictFree(parserCtxt->dict);
9387 parserCtxt->dict = ctxt->dict;
9388 xmlDictReference(parserCtxt->dict);
9389 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009390
9391 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009392 NULL, SCHEMAS_PARSE_OPTIONS);
9393 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009394 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009395 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009396 * TODO: It is not an error for the ·actual value· of the
9397 * schemaLocation [attribute] to fail to resolve it all, in which
9398 * case no corresponding inclusion is performed.
William M. Brack2f2a6632004-08-20 23:09:47 +00009399 * So do we need a warning report here?
9400 */
9401 xmlSchemaPCustomErr(ctxt,
9402 XML_SCHEMAP_FAILED_LOAD,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009403 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00009404 "Failed to load the document '%s' for inclusion", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009405 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009406 }
9407
9408 /*
9409 * Then extract the root of the schema
9410 */
9411 root = xmlDocGetRootElement(doc);
9412 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009413 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009414 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00009415 NULL, NULL, node,
9416 "The included document '%s' has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009417 "element", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009418 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009419 }
9420
9421 /*
9422 * Remove all the blank text nodes
9423 */
9424 xmlSchemaCleanupDoc(ctxt, root);
9425
9426 /*
9427 * Check the schemas top level element
9428 */
9429 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009430 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009431 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00009432 NULL, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009433 "The document '%s' to be included is not a schema document",
William M. Brack2f2a6632004-08-20 23:09:47 +00009434 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009435 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009436 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009437
William M. Brack2f2a6632004-08-20 23:09:47 +00009438 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009439 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009440 * 2.1 SII has a targetNamespace [attribute], and its ·actual
9441 * value· is identical to the ·actual value· of the targetNamespace
Daniel Veillardc0826a72004-08-10 14:17:33 +00009442 * [attribute] of SIIÂ’ (which must have such an [attribute]).
9443 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009444check_targetNamespace:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009445 if (targetNamespace != NULL) {
9446 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009447 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009448 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009449 NULL, NULL, node,
9450 "The target namespace of the included schema "
9451 "'%s' has to be absent, since the including schema "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009452 "has no target namespace",
9453 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009454 goto exit_invalid;
William M. Brack2f2a6632004-08-20 23:09:47 +00009455 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
9456 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009457 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009458 NULL, NULL, node,
9459 "The target namespace '%s' of the included schema '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009460 "differs from '%s' of the including schema",
William M. Brack2f2a6632004-08-20 23:09:47 +00009461 targetNamespace, schemaLocation, schema->targetNamespace);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009462 goto exit_invalid;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009463 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009464 } else if (schema->targetNamespace != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009465 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009466 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009467 } else
9468 wasConvertingNs = 1;
9469 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009470
9471 if (include != NULL)
9472 goto exit;
9473
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009474 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009475 * URGENT TODO: If the schema is a chameleon-include then copy the
9476 * components into the including schema and modify the targetNamespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009477 * of those components, do nothing otherwise.
9478 * NOTE: This is currently worked-around by compiling the chameleon
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009479 * for every destinct including targetNamespace; thus not performant at
9480 * the moment.
9481 * TODO: Check when the namespace in wildcards for chameleons needs
9482 * to be converted: before we built wildcard intersections or after.
9483 */
9484 /*
9485 * Register the include.
9486 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009487 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
9488 if (include == NULL) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009489 xmlSchemaPErrMemory(ctxt, "allocating include entry", NULL);
9490 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009491 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009492 memset(include, 0, sizeof(xmlSchemaInclude));
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009493 include->next = schema->includes;
9494 schema->includes = include;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009495 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009496 * TODO: Use the resolved URI for the this location, since it might
9497 * differ if using filenames/URIs simultaneosly.
Daniel Veillardc0826a72004-08-10 14:17:33 +00009498 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009499 include->schemaLocation = schemaLocation;
9500 include->doc = doc;
9501 /*
9502 * In case of chameleons, the original target namespace will differ
9503 * from the resulting namespace.
9504 */
9505 include->origTargetNamespace = targetNamespace;
9506 include->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009507#ifdef DEBUG_INCLUDES
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009508 if (targetNamespace != schema->targetNamespace)
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009509 xmlGenericError(xmlGenericErrorContext,
9510 "INCLUDING CHAMELEON '%s'\n orig TNS '%s'\n"
9511 " into TNS '%s'\n", schemaLocation,
9512 targetNamespace, schema->targetNamespace);
9513 else
9514 xmlGenericError(xmlGenericErrorContext,
9515 "INCLUDING '%s'\n orig-TNS '%s'\n", schemaLocation,
9516 targetNamespace);
9517#endif
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009518 /*
9519 * Compile the included schema.
9520 */
9521 xmlSchemaParseForImpInc(ctxt, schema, schema->targetNamespace, root);
9522
9523exit:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009524 /*
9525 * Remove the converting flag.
9526 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009527 if ((wasConvertingNs == 0) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00009528 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00009529 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009530 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009531
9532exit_invalid:
9533 if (doc != NULL) {
9534 if (include != NULL)
9535 include->doc = NULL;
9536 xmlFreeDoc(doc);
9537 }
9538 return (ctxt->err);
9539
9540exit_failure:
9541 if (doc != NULL) {
9542 if (include != NULL)
9543 include->doc = NULL;
9544 xmlFreeDoc(doc);
9545 }
9546 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009547}
9548
9549/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009550 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +00009551 * @ctxt: a schema validation context
9552 * @schema: the schema being built
9553 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009554 * @type: the "compositor" type
9555 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +00009556 *
9557 * parse a XML schema Sequence definition
9558 * *WARNING* this interface is highly subject to change
9559 *
William M. Bracke7091952004-05-11 15:09:58 +00009560 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00009561 * 1 in case of success.
9562 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009563static xmlSchemaTreeItemPtr
9564xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9565 xmlNodePtr node, xmlSchemaTypeType type,
9566 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +00009567{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009568 xmlSchemaModelGroupPtr item;
9569 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009570 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009571 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009572 const xmlChar *oldcontainer, *container;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009573 int min = 0, max = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009574
9575 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009576 return (NULL);
9577 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009578 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +00009579 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009580 item = xmlSchemaAddModelGroup(ctxt, schema, type, &container, node);
9581 if (item == NULL)
9582 return (NULL);
9583
9584 if (withParticle) {
9585 if (type == XML_SCHEMA_TYPE_ALL) {
9586 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009587 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009588 } else {
9589 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009590 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9591 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9592 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009593 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009594 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
9595 /*
9596 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009597 */
9598 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
9599 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009600 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009601 particle->children = (xmlSchemaTreeItemPtr) item;
9602 /*
9603 * Check for illegal attributes.
9604 */
9605 attr = node->properties;
9606 while (attr != NULL) {
9607 if (attr->ns == NULL) {
9608 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9609 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
9610 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009611 xmlSchemaPIllegalAttrErr(ctxt,
9612 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9613 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009614 }
9615 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009616 xmlSchemaPIllegalAttrErr(ctxt,
9617 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9618 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009619 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009620 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00009621 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009622 } else {
9623 /*
9624 * Check for illegal attributes.
9625 */
9626 attr = node->properties;
9627 while (attr != NULL) {
9628 if (attr->ns == NULL) {
9629 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009630 xmlSchemaPIllegalAttrErr(ctxt,
9631 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9632 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009633 }
9634 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009635 xmlSchemaPIllegalAttrErr(ctxt,
9636 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9637 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009638 }
9639 attr = attr->next;
9640 }
9641
William M. Brack2f2a6632004-08-20 23:09:47 +00009642 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009643
William M. Brack2f2a6632004-08-20 23:09:47 +00009644 /*
9645 * Extract and validate attributes.
9646 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009647 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009648 /*
9649 * And now for the children...
9650 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009651 child = node->children;
9652 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009653 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009654 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009655 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009656 oldcontainer = ctxt->container;
9657 ctxt->container = container;
9658 if (type == XML_SCHEMA_TYPE_ALL) {
9659 xmlSchemaParticlePtr part, last = NULL;
9660
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009661 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009662 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
9663 schema, child, 0);
9664 if (part != NULL) {
9665 if (part->minOccurs > 1)
9666 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MINOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009667 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009668 "Invalid value for minOccurs (must be 0 or 1)", NULL);
9669 if (part->maxOccurs > 1)
9670 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MAXOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009671 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009672 "Invalid value for maxOccurs (must be 0 or 1)",
9673 NULL);
9674 if (last == NULL)
9675 item->children = (xmlSchemaTreeItemPtr) part;
9676 else
9677 last->next = (xmlSchemaTreeItemPtr) part;
9678 last = part;
9679 }
9680 child = child->next;
9681 }
9682 if (child != NULL) {
9683 xmlSchemaPContentErr(ctxt,
9684 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9685 NULL, NULL, node, child, NULL,
9686 "(annotation?, (annotation?, element*)");
9687 }
9688 } else {
9689 /* choice + sequence */
9690 xmlSchemaTreeItemPtr part = NULL, last = NULL;
9691
9692 while ((IS_SCHEMA(child, "element")) ||
9693 (IS_SCHEMA(child, "group")) ||
9694 (IS_SCHEMA(child, "any")) ||
9695 (IS_SCHEMA(child, "choice")) ||
9696 (IS_SCHEMA(child, "sequence"))) {
9697
9698 if (IS_SCHEMA(child, "element")) {
9699 part = (xmlSchemaTreeItemPtr)
9700 xmlSchemaParseElement(ctxt, schema, child, 0);
9701 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009702 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009703 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9704 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009705 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009706 xmlSchemaParseAny(ctxt, schema, child);
9707 } else if (IS_SCHEMA(child, "choice")) {
9708 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9709 XML_SCHEMA_TYPE_CHOICE, 1);
9710 } else if (IS_SCHEMA(child, "sequence")) {
9711 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9712 XML_SCHEMA_TYPE_SEQUENCE, 1);
9713 }
9714 if (part != NULL) {
9715 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009716 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009717 else
9718 last->next = part;
9719 last = part;
9720 }
9721 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009722 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009723 if (child != NULL) {
9724 xmlSchemaPContentErr(ctxt,
9725 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9726 NULL, NULL, node, child, NULL,
9727 "(annotation?, (element | group | choice | sequence | any)*)");
9728 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009729 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009730 ctxt->container = oldcontainer;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009731 if (withParticle) {
9732 if ((min == 0) && (max == 0))
9733 return (NULL);
9734 else
9735 return ((xmlSchemaTreeItemPtr) particle);
9736 } else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009737 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009738}
9739
9740/**
9741 * xmlSchemaParseRestriction:
9742 * @ctxt: a schema validation context
9743 * @schema: the schema being built
9744 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00009745 *
9746 * parse a XML schema Restriction definition
9747 * *WARNING* this interface is highly subject to change
9748 *
9749 * Returns the type definition or NULL in case of error
9750 */
9751static xmlSchemaTypePtr
9752xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009753 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00009754{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009755 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009756 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009757 char buf[30];
9758 const xmlChar *oldcontainer, *container;
William M. Brack2f2a6632004-08-20 23:09:47 +00009759 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009760
9761 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9762 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009763 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009764 type = ctxt->ctxtType;
9765 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009766
9767 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009768 * TODO: Is the container needed at all? the anonymous
9769 * items inside should generate unique names already.
9770 */
9771 snprintf(buf, 29, "#restr%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009772 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009773 /*
9774 * Check for illegal attributes.
9775 */
9776 attr = node->properties;
9777 while (attr != NULL) {
9778 if (attr->ns == NULL) {
9779 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9780 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009781 xmlSchemaPIllegalAttrErr(ctxt,
9782 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9783 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009784 }
9785 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009786 xmlSchemaPIllegalAttrErr(ctxt,
9787 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9788 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009789 }
9790 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009791 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009792 /*
9793 * Extract and validate attributes.
9794 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009795 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009796 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009797 * Attribute "base" - mandatory if inside a complex type.
William M. Brack2f2a6632004-08-20 23:09:47 +00009798 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009799 /*
9800 * SPEC (1.2) "otherwise (<restriction> has no <simpleType> "
9801 * among its [children]), the simple type definition which is
9802 * the {content type} of the type definition ·resolved· to by
9803 * the ·actual value· of the base [attribute]"
9804 */
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009805 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009806 NULL, NULL, node, "base",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009807 &(type->baseNs), &(type->base)) == 0) &&
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009808 (type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009809 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009810 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009811 XML_SCHEMAP_S4S_ATTR_MISSING,
9812 type, node, "base", NULL);
9813 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009814 /*
9815 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009816 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009817 child = node->children;
9818 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009819 /*
9820 * Add the annotation to the simple type ancestor.
9821 */
9822 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9823 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009824 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009825 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009826 oldcontainer = ctxt->container;
9827 ctxt->container = container;
9828 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
9829 /*
9830 * Corresponds to <simpleType><restriction><simpleType>.
9831 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009832 if (IS_SCHEMA(child, "simpleType")) {
9833 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009834 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009835 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009836 * Either the base [attribute] or the simpleType [child] of the
9837 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +00009838 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009839 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009840 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009841 NULL, NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +00009842 "The attribute 'base' and the <simpleType> child are "
9843 "mutually exclusive", NULL);
9844 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009845 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +00009846 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009847 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009848 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009849 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009850 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009851 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
9852 NULL, NULL, node, child,
9853 "Either the attribute 'base' or a <simpleType> child "
9854 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009855 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009856 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9857 /*
9858 * Corresponds to <complexType><complexContent><restriction>...
9859 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009860 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009861 * Model groups <all>, <choice> and <sequence>.
9862 */
9863 if (IS_SCHEMA(child, "all")) {
9864 type->subtypes = (xmlSchemaTypePtr)
9865 xmlSchemaParseModelGroup(ctxt, schema, child,
9866 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009867 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009868 } else if (IS_SCHEMA(child, "choice")) {
9869 type->subtypes = (xmlSchemaTypePtr)
9870 xmlSchemaParseModelGroup(ctxt,
9871 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
9872 child = child->next;
9873 } else if (IS_SCHEMA(child, "sequence")) {
9874 type->subtypes = (xmlSchemaTypePtr)
9875 xmlSchemaParseModelGroup(ctxt, schema, child,
9876 XML_SCHEMA_TYPE_SEQUENCE, 1);
9877 child = child->next;
9878 /*
9879 * Model group reference <group>.
9880 */
9881 } else if (IS_SCHEMA(child, "group")) {
9882 type->subtypes = (xmlSchemaTypePtr)
9883 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9884 child = child->next;
9885 }
9886 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009887 /*
9888 * Corresponds to <complexType><simpleContent><restriction>...
9889 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009890 * "1.1 the simple type definition corresponding to the <simpleType>
9891 * among the [children] of <restriction> if there is one;"
9892 */
9893 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009894 /*
9895 * We will store the to-be-restricted simple type in
9896 * type->contentTypeDef *temporarily*.
9897 */
9898 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009899 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009900 if ( type->contentTypeDef == NULL)
9901 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009902 child = child->next;
9903 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009904 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009905
9906 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009907 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009908 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009909 /*
9910 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009911 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009912 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009913
Daniel Veillard01fa6152004-06-29 17:04:39 +00009914 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009915 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009916 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009917 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009918 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
9919 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009920 * *Single Facet Value*
9921 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009922 while ((IS_SCHEMA(child, "minInclusive")) ||
9923 (IS_SCHEMA(child, "minExclusive")) ||
9924 (IS_SCHEMA(child, "maxInclusive")) ||
9925 (IS_SCHEMA(child, "maxExclusive")) ||
9926 (IS_SCHEMA(child, "totalDigits")) ||
9927 (IS_SCHEMA(child, "fractionDigits")) ||
9928 (IS_SCHEMA(child, "pattern")) ||
9929 (IS_SCHEMA(child, "enumeration")) ||
9930 (IS_SCHEMA(child, "whiteSpace")) ||
9931 (IS_SCHEMA(child, "length")) ||
9932 (IS_SCHEMA(child, "maxLength")) ||
9933 (IS_SCHEMA(child, "minLength"))) {
9934 facet = xmlSchemaParseFacet(ctxt, schema, child);
9935 if (facet != NULL) {
9936 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009937 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009938 else
9939 lastfacet->next = facet;
9940 lastfacet = facet;
9941 lastfacet->next = NULL;
9942 }
9943 child = child->next;
9944 }
9945 /*
9946 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009947 */
9948 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009949 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
9950
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009951 facet = type->facets;
9952 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009953 facetLink = (xmlSchemaFacetLinkPtr)
9954 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +00009955 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009956 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009957 xmlFree(facetLink);
9958 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009959 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009960 facetLink->facet = facet;
9961 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009962 if (lastFacetLink == NULL)
9963 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009964 else
9965 lastFacetLink->next = facetLink;
9966 lastFacetLink = facetLink;
9967 facet = facet->next;
9968 } while (facet != NULL);
9969 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009970 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009971 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
9972 /*
9973 * Attribute uses/declarations.
9974 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009975 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009976 /*
9977 * Attribute wildcard.
9978 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009979 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009980 type->attributeWildcard =
9981 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009982 child = child->next;
9983 }
9984 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009985 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009986 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9987 xmlSchemaPContentErr(ctxt,
9988 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009989 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009990 "annotation?, (group | all | choice | sequence)?, "
9991 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009992 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009993 xmlSchemaPContentErr(ctxt,
9994 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009995 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009996 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
9997 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
9998 "length | minLength | maxLength | enumeration | whiteSpace | "
9999 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
10000 } else {
10001 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010002 xmlSchemaPContentErr(ctxt,
10003 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010004 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010005 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10006 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10007 "length | minLength | maxLength | enumeration | whiteSpace | "
10008 "pattern)*))");
10009 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010010 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010011 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010012 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010013}
10014
10015/**
10016 * xmlSchemaParseExtension:
10017 * @ctxt: a schema validation context
10018 * @schema: the schema being built
10019 * @node: a subtree containing XML Schema informations
10020 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010021 * Parses an <extension>, which is found inside a
10022 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010023 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000010024 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010025 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000010026 */
10027static xmlSchemaTypePtr
10028xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010029 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000010030{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010031 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010032 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010033 char buf[30];
10034 const xmlChar *oldcontainer, *container;
10035 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010036
10037 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10038 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010039 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010040 type = ctxt->ctxtType;
10041 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000010042
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010043 snprintf(buf, 29, "#ext%d", ctxt->counter++ + 1);
10044 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
10045 /*
10046 * Check for illegal attributes.
10047 */
10048 attr = node->properties;
10049 while (attr != NULL) {
10050 if (attr->ns == NULL) {
10051 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10052 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010053 xmlSchemaPIllegalAttrErr(ctxt,
10054 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10055 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010056 }
10057 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010058 xmlSchemaPIllegalAttrErr(ctxt,
10059 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10060 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010061 }
10062 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010063 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010064
10065 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010066
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010067 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010068 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010069 */
10070 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010071 NULL, NULL, node, "base", &(type->baseNs), &(type->base)) == 0) &&
10072 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010073 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010074 XML_SCHEMAP_S4S_ATTR_MISSING,
10075 NULL, node, "base", NULL);
10076 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010077 /*
10078 * And now for the children...
10079 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010080 child = node->children;
10081 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010082 /*
10083 * Add the annotation to the type ancestor.
10084 */
10085 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10086 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010087 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010088 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010089 oldcontainer = ctxt->container;
10090 ctxt->container = container;
10091 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10092 /*
10093 * Corresponds to <complexType><complexContent><extension>... and:
10094 *
10095 * Model groups <all>, <choice>, <sequence> and <group>.
10096 */
10097 if (IS_SCHEMA(child, "all")) {
10098 type->subtypes = (xmlSchemaTypePtr)
10099 xmlSchemaParseModelGroup(ctxt, schema,
10100 child, XML_SCHEMA_TYPE_ALL, 1);
10101 child = child->next;
10102 } else if (IS_SCHEMA(child, "choice")) {
10103 type->subtypes = (xmlSchemaTypePtr)
10104 xmlSchemaParseModelGroup(ctxt, schema,
10105 child, XML_SCHEMA_TYPE_CHOICE, 1);
10106 child = child->next;
10107 } else if (IS_SCHEMA(child, "sequence")) {
10108 type->subtypes = (xmlSchemaTypePtr)
10109 xmlSchemaParseModelGroup(ctxt, schema,
10110 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
10111 child = child->next;
10112 } else if (IS_SCHEMA(child, "group")) {
10113 type->subtypes = (xmlSchemaTypePtr)
10114 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
10115 child = child->next;
10116 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010117 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010118 if (child != NULL) {
10119 /*
10120 * Attribute uses/declarations.
10121 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010122 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010123 /*
10124 * Attribute wildcard.
10125 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010126 if (IS_SCHEMA(child, "anyAttribute")) {
10127 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010128 xmlSchemaParseAnyAttribute(ctxt, schema, child);
10129 child = child->next;
10130 }
10131 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010132 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010133 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10134 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010135 xmlSchemaPContentErr(ctxt,
10136 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010137 NULL, NULL, node, child, NULL,
10138 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010139 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010140 } else {
10141 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010142 xmlSchemaPContentErr(ctxt,
10143 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010144 NULL, NULL, node, child, NULL,
10145 "(annotation?, ((attribute | attributeGroup)*, "
10146 "anyAttribute?))");
10147 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010148 }
10149 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010150 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010151}
10152
10153/**
10154 * xmlSchemaParseSimpleContent:
10155 * @ctxt: a schema validation context
10156 * @schema: the schema being built
10157 * @node: a subtree containing XML Schema informations
10158 *
10159 * parse a XML schema SimpleContent definition
10160 * *WARNING* this interface is highly subject to change
10161 *
10162 * Returns the type definition or NULL in case of error
10163 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010164static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010165xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
10166 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010167{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010168 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010169 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010170 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010171
10172 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010173 return (-1);
10174 /* Not a component, don't create it. */
10175 type = ctxt->ctxtType;
10176 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
10177 /*
10178 * Check for illegal attributes.
10179 */
10180 attr = node->properties;
10181 while (attr != NULL) {
10182 if (attr->ns == NULL) {
10183 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010184 xmlSchemaPIllegalAttrErr(ctxt,
10185 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10186 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010187 }
10188 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010189 xmlSchemaPIllegalAttrErr(ctxt,
10190 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10191 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010192 }
10193 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010194 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010195
10196 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000010197
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010198 /*
10199 * And now for the children...
10200 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010201 child = node->children;
10202 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010203 /*
10204 * Add the annotation to the complex type ancestor.
10205 */
10206 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10207 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010208 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010209 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010210 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010211 xmlSchemaParseRestriction(ctxt, schema, child,
10212 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010213 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010214 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010215 xmlSchemaParseExtension(ctxt, schema, child,
10216 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010217 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010218 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010219 if (child != NULL) {
10220 xmlSchemaPContentErr(ctxt,
10221 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010222 NULL, NULL, node, child, NULL,
10223 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010224 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010225 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010226}
10227
10228/**
10229 * xmlSchemaParseComplexContent:
10230 * @ctxt: a schema validation context
10231 * @schema: the schema being built
10232 * @node: a subtree containing XML Schema informations
10233 *
10234 * parse a XML schema ComplexContent definition
10235 * *WARNING* this interface is highly subject to change
10236 *
10237 * Returns the type definition or NULL in case of error
10238 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010239static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010240xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
10241 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010242{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010243 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010244 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010245 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010246
10247 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010248 return (-1);
10249 /* Not a component, don't create it. */
10250 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010251 /*
10252 * Check for illegal attributes.
10253 */
10254 attr = node->properties;
10255 while (attr != NULL) {
10256 if (attr->ns == NULL) {
10257 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010258 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010259 {
10260 xmlSchemaPIllegalAttrErr(ctxt,
10261 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10262 NULL, NULL, attr);
10263 }
10264 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10265 xmlSchemaPIllegalAttrErr(ctxt,
10266 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10267 NULL, NULL, attr);
10268 }
10269 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010270 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010271
10272 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
10273
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010274 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010275 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010276 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010277 if (xmlGetBooleanProp(ctxt, NULL, NULL, node, "mixed", 0)) {
10278 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
10279 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010280 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010281 child = node->children;
10282 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010283 /*
10284 * Add the annotation to the complex type ancestor.
10285 */
10286 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10287 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010288 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010289 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010290 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010291 xmlSchemaParseRestriction(ctxt, schema, child,
10292 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010293 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010294 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010295 xmlSchemaParseExtension(ctxt, schema, child,
10296 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010297 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010298 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010299 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010300 xmlSchemaPContentErr(ctxt,
10301 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10302 NULL, NULL, node, child,
10303 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010304 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010305 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010306}
10307
10308/**
10309 * xmlSchemaParseComplexType:
10310 * @ctxt: a schema validation context
10311 * @schema: the schema being built
10312 * @node: a subtree containing XML Schema informations
10313 *
10314 * parse a XML schema Complex Type definition
10315 * *WARNING* this interface is highly subject to change
10316 *
10317 * Returns the type definition or NULL in case of error
10318 */
10319static xmlSchemaTypePtr
10320xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000010321 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000010322{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010323 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010324 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010325 const xmlChar *oldcontainer, *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010326 xmlAttrPtr attr;
10327 const xmlChar *attrValue;
10328 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +000010329 char buf[40];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010330 int final = 0, block = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000010331
Daniel Veillard4255d502002-04-16 15:50:10 +000010332
10333 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10334 return (NULL);
10335
Daniel Veillard01fa6152004-06-29 17:04:39 +000010336 ctxtType = ctxt->ctxtType;
10337
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010338 if (topLevel) {
10339 attr = xmlSchemaGetPropNode(node, "name");
10340 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010341 xmlSchemaPMissingAttrErr(ctxt,
10342 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010343 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010344 } else if (xmlSchemaPValAttrNode(ctxt,
10345 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010346 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
10347 return (NULL);
10348 }
10349 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010350
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010351 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010352 /*
10353 * Parse as local complex type definition.
10354 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000010355 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010356 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
10357 if (type == NULL)
10358 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010359 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010360 type->node = node;
10361 type->type = XML_SCHEMA_TYPE_COMPLEX;
10362 /*
10363 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010364 */
10365 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010366 /*
10367 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010368 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010369 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010370 if (type == NULL)
10371 return (NULL);
10372 type->node = node;
10373 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010374 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000010375 }
10376 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010377 /*
10378 * Handle attributes.
10379 */
10380 attr = node->properties;
10381 while (attr != NULL) {
10382 if (attr->ns == NULL) {
10383 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
10384 /*
10385 * Attribute "id".
10386 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010387 xmlSchemaPValAttrID(ctxt, NULL, type, node,
10388 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010389 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
10390 /*
10391 * Attribute "mixed".
10392 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010393 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010394 (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010395 type->flags |= XML_SCHEMAS_TYPE_MIXED;
10396 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010397 /*
10398 * Attributes of global complex type definitions.
10399 */
10400 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
10401 /* Pass. */
10402 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
10403 /*
10404 * Attribute "abstract".
10405 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010406 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
10407 (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010408 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
10409 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
10410 /*
10411 * Attribute "final".
10412 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010413 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010414 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010415 if (xmlSchemaPValAttrBlockFinal(attrValue,
10416 &(type->flags),
10417 -1,
10418 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
10419 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
10420 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010421 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010422 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010423 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010424 type, (xmlNodePtr) attr, NULL,
10425 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010426 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010427 } else
10428 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010429 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
10430 /*
10431 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010432 */
10433 attrValue = xmlSchemaGetNodeContent(ctxt,
10434 (xmlNodePtr) attr);
10435 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010436 -1,
10437 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010438 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010439 -1, -1, -1) != 0) {
10440 xmlSchemaPSimpleTypeErr(ctxt,
10441 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010442 type, (xmlNodePtr) attr, NULL,
10443 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010444 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010445 } else
10446 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010447 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010448 xmlSchemaPIllegalAttrErr(ctxt,
10449 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010450 &des, type, attr);
10451 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010452 } else {
10453 xmlSchemaPIllegalAttrErr(ctxt,
10454 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010455 &des, type, attr);
10456 }
10457 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010458 xmlSchemaPIllegalAttrErr(ctxt,
10459 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10460 &des, type, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010461 }
10462 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010463 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010464 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000010465 /*
10466 * Apply default "block" values.
10467 */
10468 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
10469 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
10470 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
10471 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
10472 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010473 if (! final) {
10474 /*
10475 * Apply default "block" values.
10476 */
10477 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
10478 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
10479 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
10480 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
10481 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010482 /*
10483 * And now for the children...
10484 */
10485 oldcontainer = ctxt->container;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010486 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +000010487 child = node->children;
10488 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010489 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
10490 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010491 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010492 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010493 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010494 /*
10495 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010496 * Specifying mixed='true' when the <simpleContent>
10497 * alternative is chosen has no effect
10498 */
William M. Bracke7091952004-05-11 15:09:58 +000010499 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
10500 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010501 xmlSchemaParseSimpleContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010502 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010503 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010504 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
10505 xmlSchemaParseComplexContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010506 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010507 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010508 /*
10509 * SPEC
10510 * "...the third alternative (neither <simpleContent> nor
10511 * <complexContent>) is chosen. This case is understood as shorthand
10512 * for complex content restricting the ·ur-type definition·, and the
10513 * details of the mappings should be modified as necessary.
10514 */
10515 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10516 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010517 /*
10518 * Parse model groups.
10519 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010520 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010521 type->subtypes = (xmlSchemaTypePtr)
10522 xmlSchemaParseModelGroup(ctxt, schema, child,
10523 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010524 child = child->next;
10525 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010526 type->subtypes = (xmlSchemaTypePtr)
10527 xmlSchemaParseModelGroup(ctxt, schema, child,
10528 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010529 child = child->next;
10530 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010531 type->subtypes = (xmlSchemaTypePtr)
10532 xmlSchemaParseModelGroup(ctxt, schema, child,
10533 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010534 child = child->next;
10535 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010536 type->subtypes = (xmlSchemaTypePtr)
10537 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010538 child = child->next;
10539 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010540 /*
10541 * Parse attribute decls/refs.
10542 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010543 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010544 /*
10545 * Parse attribute wildcard.
10546 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010547 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010548 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
10549 child = child->next;
10550 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010551 }
10552 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010553 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010554 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010555 &des, type, node, child,
10556 NULL, "(annotation?, (simpleContent | complexContent | "
10557 "((group | all | choice | sequence)?, ((attribute | "
10558 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010559 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010560 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +000010561 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010562 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010563 return (type);
10564}
10565
Daniel Veillard4255d502002-04-16 15:50:10 +000010566/**
10567 * xmlSchemaParseSchema:
10568 * @ctxt: a schema validation context
10569 * @node: a subtree containing XML Schema informations
10570 *
10571 * parse a XML schema definition from a node set
10572 * *WARNING* this interface is highly subject to change
10573 *
10574 * Returns the internal XML Schema structure built from the resource or
10575 * NULL in case of error
10576 */
10577static xmlSchemaPtr
10578xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
10579{
10580 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010581 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010582 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010583 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010584
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010585 /*
10586 * This one is called by xmlSchemaParse only and is used if
10587 * the schema to be parsed was specified via the API; i.e. not
10588 * automatically by the validated instance document.
10589 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010590 if ((ctxt == NULL) || (node == NULL))
10591 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010592 nberrors = ctxt->nberrors;
10593 ctxt->nberrors = 0;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010594 ctxt->isS4S = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010595 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010596 xmlSchemaImportPtr import;
10597
Daniel Veillard4255d502002-04-16 15:50:10 +000010598 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010599 if (schema == NULL)
10600 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010601 attr = xmlSchemaGetPropNode(node, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +000010602 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010603 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010604 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
10605 /*
10606 * TODO: Should we proceed with an invalid target namespace?
10607 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010608 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010609 if (xmlStrEqual(schema->targetNamespace, xmlSchemaNs)) {
10610 /*
10611 * We are parsing the schema for schema!
10612 */
10613 ctxt->isS4S = 1;
10614 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010615 } else {
10616 schema->targetNamespace = NULL;
10617 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010618 /*
10619 * Add the current ns name and location to the import table;
10620 * this is needed to have a consistent mechanism, regardless
10621 * if all schemata are constructed dynamically fired by the
10622 * instance or if the schema to be used was specified via
10623 * the API.
10624 */
10625 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
10626 schema->targetNamespace);
10627 if (import == NULL) {
10628 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
10629 NULL, NULL, (xmlNodePtr) ctxt->doc,
10630 "Internal error: xmlSchemaParseSchema, "
10631 "failed to add an import entry", NULL);
10632 xmlSchemaFree(schema);
10633 schema = NULL;
10634 return (NULL);
10635 }
10636 import->schemaLocation = ctxt->URL;
10637 /*
10638 * NOTE: We won't set the doc here, otherwise it will be freed
10639 * if the import struct is freed.
10640 * import->doc = ctxt->doc;
10641 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010642 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010643 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
10644 } else {
10645 xmlDocPtr doc;
10646
10647 doc = node->doc;
10648
10649 if ((doc != NULL) && (doc->URL != NULL)) {
10650 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10651 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010652 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010653 } else {
10654 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10655 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010656 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010657 }
10658 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010659 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010660 if (ctxt->nberrors != 0) {
10661 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010662 xmlSchemaFree(schema);
10663 schema = NULL;
10664 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010665 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010666 if (schema != NULL)
10667 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010668 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +000010669#ifdef DEBUG
10670 if (schema == NULL)
10671 xmlGenericError(xmlGenericErrorContext,
10672 "xmlSchemaParse() failed\n");
10673#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000010674 return (schema);
10675}
10676
10677/************************************************************************
10678 * *
10679 * Validating using Schemas *
10680 * *
10681 ************************************************************************/
10682
10683/************************************************************************
10684 * *
10685 * Reading/Writing Schemas *
10686 * *
10687 ************************************************************************/
10688
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010689#if 0 /* Will be enabled if it is clear what options are needed. */
10690/**
10691 * xmlSchemaParserCtxtSetOptions:
10692 * @ctxt: a schema parser context
10693 * @options: a combination of xmlSchemaParserOption
10694 *
10695 * Sets the options to be used during the parse.
10696 *
10697 * Returns 0 in case of success, -1 in case of an
10698 * API error.
10699 */
10700static int
10701xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
10702 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010703
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010704{
10705 int i;
10706
10707 if (ctxt == NULL)
10708 return (-1);
10709 /*
10710 * WARNING: Change the start value if adding to the
10711 * xmlSchemaParseOption.
10712 */
10713 for (i = 1; i < (int) sizeof(int) * 8; i++) {
10714 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010715 return (-1);
10716 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010717 }
10718 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010719 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010720}
10721
10722/**
10723 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010724 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010725 *
10726 * Returns the option combination of the parser context.
10727 */
10728static int
10729xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010730
10731{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010732 if (ctxt == NULL)
10733 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010734 else
10735 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010736}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010737#endif
10738
Daniel Veillard4255d502002-04-16 15:50:10 +000010739/**
10740 * xmlSchemaNewParserCtxt:
10741 * @URL: the location of the schema
10742 *
10743 * Create an XML Schemas parse context for that file/resource expected
10744 * to contain an XML Schemas file.
10745 *
10746 * Returns the parser context or NULL in case of error
10747 */
10748xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010749xmlSchemaNewParserCtxt(const char *URL)
10750{
Daniel Veillard4255d502002-04-16 15:50:10 +000010751 xmlSchemaParserCtxtPtr ret;
10752
10753 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010754 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010755
10756 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10757 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010758 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010759 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010760 return (NULL);
10761 }
10762 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010763 ret->type = XML_SCHEMA_CTXT_PARSER;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010764 ret->dict = xmlDictCreate();
10765 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010766 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010767 return (ret);
10768}
10769
10770/**
Daniel Veillard6045c902002-10-09 21:13:59 +000010771 * xmlSchemaNewMemParserCtxt:
10772 * @buffer: a pointer to a char array containing the schemas
10773 * @size: the size of the array
10774 *
10775 * Create an XML Schemas parse context for that memory buffer expected
10776 * to contain an XML Schemas file.
10777 *
10778 * Returns the parser context or NULL in case of error
10779 */
10780xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010781xmlSchemaNewMemParserCtxt(const char *buffer, int size)
10782{
Daniel Veillard6045c902002-10-09 21:13:59 +000010783 xmlSchemaParserCtxtPtr ret;
10784
10785 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010786 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010787
10788 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10789 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010790 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010791 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010792 return (NULL);
10793 }
10794 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10795 ret->buffer = buffer;
10796 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010797 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000010798 return (ret);
10799}
10800
10801/**
Daniel Veillard9d751502003-10-29 13:21:47 +000010802 * xmlSchemaNewDocParserCtxt:
10803 * @doc: a preparsed document tree
10804 *
10805 * Create an XML Schemas parse context for that document.
10806 * NB. The document may be modified during the parsing process.
10807 *
10808 * Returns the parser context or NULL in case of error
10809 */
10810xmlSchemaParserCtxtPtr
10811xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
10812{
10813 xmlSchemaParserCtxtPtr ret;
10814
10815 if (doc == NULL)
10816 return (NULL);
10817
10818 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10819 if (ret == NULL) {
10820 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10821 NULL);
10822 return (NULL);
10823 }
10824 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10825 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010826 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000010827 /* The application has responsibility for the document */
10828 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000010829
10830 return (ret);
10831}
10832
10833/**
Daniel Veillard4255d502002-04-16 15:50:10 +000010834 * xmlSchemaFreeParserCtxt:
10835 * @ctxt: the schema parser context
10836 *
10837 * Free the resources associated to the schema parser context
10838 */
10839void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010840xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
10841{
Daniel Veillard4255d502002-04-16 15:50:10 +000010842 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010843 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000010844 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010845 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010846 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010847 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010848 xmlFree(ctxt->assemble);
10849 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010850 if (ctxt->vctxt != NULL) {
10851 xmlSchemaFreeValidCtxt(ctxt->vctxt);
10852 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010853 if (ctxt->localImports != NULL)
10854 xmlFree((xmlChar *) ctxt->localImports);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010855 if (ctxt->substGroups != NULL)
10856 xmlHashFree(ctxt->substGroups,
10857 (xmlHashDeallocator) xmlSchemaFreeSubstGroup);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010858 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000010859 xmlFree(ctxt);
10860}
10861
10862/************************************************************************
10863 * *
10864 * Building the content models *
10865 * *
10866 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010867
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010868static void
10869xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010870 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010871{
10872 xmlAutomataStatePtr start;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010873 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010874 xmlAutomataStatePtr end;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010875 xmlSchemaSubstGroupPtr substGroup;
10876 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010877
10878 elemDecl = (xmlSchemaElementPtr) particle->children;
10879 /*
10880 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010881 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010882 start = pctxt->state;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010883 end = xmlAutomataNewState(pctxt->am);
10884 substGroup = xmlSchemaGetElementSubstitutionGroup(pctxt, elemDecl);
10885 if (substGroup == NULL) {
10886 xmlSchemaPErr(pctxt, GET_NODE(particle),
10887 XML_SCHEMAP_INTERNAL,
10888 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
10889 "declaration is marked having a subst. group but none "
10890 "available.\n", elemDecl->name, NULL);
10891 return;
10892 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010893 if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010894 /*
10895 * NOTE that we put the declaration in, even if it's abstract,
10896 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010897 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010898 xmlAutomataNewTransition2(pctxt->am,
10899 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010900 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
10901 /*
10902 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010903 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010904 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010905 member = (xmlSchemaElementPtr) substGroup->members->items[i];
10906 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010907 xmlAutomataNewTransition2(pctxt->am,
10908 start, NULL,
10909 member->name, member->targetNamespace, member),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010910 end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010911 }
10912 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010913 int counter;
10914 xmlAutomataStatePtr hop;
10915 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
10916 UNBOUNDED : particle->maxOccurs - 1;
10917 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
10918
10919 counter =
10920 xmlAutomataNewCounter(pctxt->am, minOccurs,
10921 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010922 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010923
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010924 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010925 xmlAutomataNewTransition2(pctxt->am,
10926 start, NULL,
10927 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010928 hop);
10929 /*
10930 * Add subst. group members.
10931 */
10932 for (i = 0; i < substGroup->members->nbItems; i++) {
10933 member = (xmlSchemaElementPtr) substGroup->members->items[i];
10934 xmlAutomataNewEpsilon(pctxt->am,
10935 xmlAutomataNewTransition2(pctxt->am,
10936 start, NULL,
10937 member->name, member->targetNamespace, member),
10938 hop);
10939 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010940 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
10941 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
10942 }
10943 if (particle->minOccurs == 0)
10944 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010945 pctxt->state = end;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010946}
10947
10948static void
10949xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
10950 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010951{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010952 if (((xmlSchemaElementPtr) particle->children)->flags &
10953 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010954 /*
10955 * Substitution groups.
10956 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010957 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010958 } else {
10959 xmlSchemaElementPtr elemDecl;
10960 xmlAutomataStatePtr start;
10961
10962 elemDecl = (xmlSchemaElementPtr) particle->children;
10963
10964 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010965 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010966 if (particle->maxOccurs == 1) {
10967 start = ctxt->state;
10968 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
10969 elemDecl->name, elemDecl->targetNamespace, elemDecl);
10970 } else if ((particle->maxOccurs >= UNBOUNDED) && (particle->minOccurs < 2)) {
10971 /* Special case. */
10972 start = ctxt->state;
10973 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
10974 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010975 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, start);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010976 } else {
10977 int counter;
10978 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
10979 UNBOUNDED : particle->maxOccurs - 1;
10980 int minOccurs = particle->minOccurs < 1 ?
10981 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010982
10983 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010984 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
10985 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
10986 elemDecl->name, elemDecl->targetNamespace, elemDecl);
10987 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
10988 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
10989 NULL, counter);
10990 }
10991 if (particle->minOccurs == 0)
10992 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
10993 }
10994}
10995
Daniel Veillard4255d502002-04-16 15:50:10 +000010996/**
10997 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000010998 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010999 * @particle: the particle component
11000 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000011001 *
11002 * Generate the automata sequence needed for that type
11003 */
11004static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011005xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011006 xmlSchemaParticlePtr particle,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011007 const xmlChar * name)
11008{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011009 if (particle == NULL) {
11010 xmlSchemaPErr(ctxt, NULL,
11011 XML_SCHEMAP_INTERNAL,
11012 "Internal error: xmlSchemaBuildAContentModel, "
11013 "particle is NULL.\n", NULL, NULL);
11014 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011015 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011016 if (particle->children == NULL) {
11017 xmlSchemaPErr(ctxt, GET_NODE(particle),
11018 XML_SCHEMAP_INTERNAL,
11019 "Internal error: xmlSchemaBuildAContentModel, "
11020 "no term on particle.\n", NULL, NULL);
11021 return;
11022 }
11023
11024 switch (particle->children->type) {
11025 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011026 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011027 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011028 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000011029
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011030 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011031
Daniel Veillardc0826a72004-08-10 14:17:33 +000011032 start = ctxt->state;
11033 end = xmlAutomataNewState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011034
11035 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011036 if (wild->any == 1) {
11037 /*
11038 * We need to add both transitions:
11039 *
11040 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011041 */
11042 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011043 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011044 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011045 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11046 /*
11047 * 2. the {"*"} for elements in no namespace.
11048 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011049 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011050 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011051 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011052 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11053
11054 } else if (wild->nsSet != NULL) {
11055 ns = wild->nsSet;
11056 do {
11057 ctxt->state = start;
11058 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011059 ctxt->state, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011060 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11061 ns = ns->next;
11062 } while (ns != NULL);
11063
11064 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011065
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011066 /*
11067 * Lead nodes with the negated namespace to the sink-state
11068 * {"*", "##other"}.
11069 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011070 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011071 BAD_CAST "*", wild->negNsSet->value, wild);
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011072 /*
11073 * Open a door for nodes with any other namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011074 * {"*", "*"}
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011075 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011076 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011077 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011078 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011079 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011080 } else {
11081 int counter;
11082 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011083 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011084 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011085 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011086 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011087
Daniel Veillardc0826a72004-08-10 14:17:33 +000011088 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011089 hop = xmlAutomataNewState(ctxt->am);
11090 if (wild->any == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011091 ctxt->state =
11092 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011093 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011094 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011095 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011096 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011097 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011098 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011099 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011100 ns = wild->nsSet;
11101 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011102 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011103 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011104 start, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011105 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
11106 ns = ns->next;
11107 } while (ns != NULL);
11108
11109 } else if (wild->negNsSet != NULL) {
11110 xmlAutomataStatePtr deadEnd;
11111
11112 deadEnd = xmlAutomataNewState(ctxt->am);
11113 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011114 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011115 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011116 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011117 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011118 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011119 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
11120 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
11121 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011122 if (particle->minOccurs == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011123 xmlAutomataNewEpsilon(ctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011124 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011125 ctxt->state = end;
11126 break;
11127 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011128 case XML_SCHEMA_TYPE_ELEMENT:
11129 xmlSchemaBuildContentModelForElement(ctxt, particle);
11130 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011131 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011132 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011133
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011134 /*
11135 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011136 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011137 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011138 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
11139 sub = particle->children->children;
11140 while (sub != NULL) {
11141 xmlSchemaBuildAContentModel(ctxt,
11142 (xmlSchemaParticlePtr) sub, name);
11143 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011144 }
11145 } else {
11146 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011147
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011148 if (particle->maxOccurs >= UNBOUNDED) {
11149 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011150 xmlAutomataStatePtr tmp;
11151 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011152
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011153 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011154 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011155 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011156
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011157 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011158 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011159
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011160 sub = particle->children->children;
11161 while (sub != NULL) {
11162 xmlSchemaBuildAContentModel(ctxt,
11163 (xmlSchemaParticlePtr) sub, name);
11164 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011165 }
11166 tmp = ctxt->state;
11167 xmlAutomataNewCountedTrans(ctxt->am, tmp,
11168 oldstate, counter);
11169 ctxt->state =
11170 xmlAutomataNewCounterTrans(ctxt->am, tmp,
11171 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011172
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011173 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011174 sub = particle->children->children;
11175 while (sub != NULL) {
11176 xmlSchemaBuildAContentModel(ctxt,
11177 (xmlSchemaParticlePtr) sub, name);
11178 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011179 }
11180 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
11181 oldstate);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011182 if (particle->minOccurs == 0) {
11183 xmlAutomataNewEpsilon(ctxt->am,
11184 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011185 }
11186 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011187 } else if ((particle->maxOccurs > 1)
11188 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011189 xmlAutomataStatePtr tmp;
11190 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011191
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011192 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011193 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011194 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000011195
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011196 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011197 particle->minOccurs - 1,
11198 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011199
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011200 sub = particle->children->children;
11201 while (sub != NULL) {
11202 xmlSchemaBuildAContentModel(ctxt,
11203 (xmlSchemaParticlePtr) sub, name);
11204 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011205 }
11206 tmp = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011207 xmlAutomataNewCountedTrans(ctxt->am,
11208 tmp, oldstate, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011209 ctxt->state =
11210 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
11211 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011212 if (particle->minOccurs == 0) {
11213 xmlAutomataNewEpsilon(ctxt->am,
11214 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011215 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011216 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011217 sub = particle->children->children;
11218 while (sub != NULL) {
11219 xmlSchemaBuildAContentModel(ctxt,
11220 (xmlSchemaParticlePtr) sub, name);
11221 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011222 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011223 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011224 xmlAutomataNewEpsilon(ctxt->am, oldstate,
11225 ctxt->state);
11226 }
11227 }
11228 }
11229 break;
11230 }
11231 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011232 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011233 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000011234
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011235 start = ctxt->state;
11236 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000011237
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011238 /*
11239 * iterate over the subtypes and remerge the end with an
11240 * epsilon transition
11241 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011242 if (particle->maxOccurs == 1) {
11243 sub = particle->children->children;
11244 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011245 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011246 xmlSchemaBuildAContentModel(ctxt,
11247 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011248 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011249 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011250 }
11251 } else {
11252 int counter;
11253 xmlAutomataStatePtr hop;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011254 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11255 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011256 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011257 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000011258
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011259 /*
11260 * use a counter to keep track of the number of transtions
11261 * which went through the choice.
11262 */
11263 counter =
11264 xmlAutomataNewCounter(ctxt->am, minOccurs,
11265 maxOccurs);
11266 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000011267
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011268 sub = particle->children->children;
11269 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011270 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011271 xmlSchemaBuildAContentModel(ctxt,
11272 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011273 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011274 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011275 }
11276 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
11277 counter);
11278 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
11279 counter);
11280 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011281 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011282 xmlAutomataNewEpsilon(ctxt->am, start, end);
11283 }
11284 ctxt->state = end;
11285 break;
11286 }
11287 case XML_SCHEMA_TYPE_ALL:{
11288 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011289 xmlSchemaParticlePtr sub;
11290 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011291 int lax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011292
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011293 sub = (xmlSchemaParticlePtr) particle->children->children;
11294 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011295 break;
11296 start = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011297 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011298 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011299
11300 elemDecl = (xmlSchemaElementPtr) sub->children;
11301 if (elemDecl == NULL) {
11302 xmlSchemaPErr(ctxt, NULL,
11303 XML_SCHEMAP_INTERNAL,
11304 "Internal error: xmlSchemaBuildAContentModel, "
11305 "<element> particle a NULL term.\n", NULL, NULL);
11306 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011307 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011308 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011309 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011310 * {particles} of the group must be 0 or 1; this is
11311 * already ensured during the parse of the content of
11312 * <all>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011313 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011314 if ((sub->minOccurs == 1) &&
11315 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011316 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011317 ctxt->state,
11318 elemDecl->name,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011319 elemDecl->targetNamespace,
11320 1, 1, elemDecl);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011321 } else if ((sub->minOccurs == 0) &&
11322 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011323
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011324 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011325 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011326 elemDecl->name,
11327 elemDecl->targetNamespace,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011328 0,
11329 1,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011330 elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011331 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011332 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011333 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011334 lax = particle->minOccurs == 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011335 ctxt->state =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011336 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011337 break;
11338 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011339 default:
11340 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011341 "Internal error: xmlSchemaBuildAContentModel, found "
11342 "unexpected term of type %d in content model of complex "
11343 "type '%s'.\n",
11344 particle->children->type, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011345 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011346 }
11347}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011348
Daniel Veillard4255d502002-04-16 15:50:10 +000011349/**
11350 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011351 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011352 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011353 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000011354 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011355 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000011356 */
11357static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011358xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011359 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011360 const xmlChar * name)
11361{
Daniel Veillard4255d502002-04-16 15:50:10 +000011362 xmlAutomataStatePtr start;
11363
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011364 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
11365 (type->contModel != NULL) ||
11366 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
11367 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011368 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011369
11370#ifdef DEBUG_CONTENT
11371 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011372 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011373#endif
11374
Daniel Veillard4255d502002-04-16 15:50:10 +000011375 ctxt->am = xmlNewAutomata();
11376 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011377 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011378 "Cannot create automata for complex type %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011379 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011380 }
11381 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011382 xmlSchemaBuildAContentModel(ctxt, (xmlSchemaParticlePtr) type->subtypes, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011383 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011384 type->contModel = xmlAutomataCompile(ctxt->am);
11385 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011386 xmlSchemaPCustomErr(ctxt,
11387 XML_SCHEMAP_INTERNAL,
11388 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011389 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011390 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011391 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011392 XML_SCHEMAP_NOT_DETERMINISTIC,
11393 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011394 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011395 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000011396 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000011397#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011398 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011399 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011400 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000011401#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000011402 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011403 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011404 xmlFreeAutomata(ctxt->am);
11405 ctxt->am = NULL;
11406}
11407
11408/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011409 * xmlSchemaElementFixup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011410 * @elem: the schema element context
11411 * @ctxt: the schema parser context
11412 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000011413 * Resolves the references of an element declaration
11414 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011415 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000011416 */
11417static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011418xmlSchemaElementFixup(xmlSchemaElementPtr elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011419 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011420 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011421 const xmlChar * context ATTRIBUTE_UNUSED,
11422 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000011423{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011424 if ((ctxt == NULL) || (elemDecl == NULL) ||
11425 ((elemDecl != NULL) &&
11426 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011427 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011428 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011429
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011430 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011431 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011432
11433 /* (type definition) ... otherwise the type definition ·resolved·
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011434 * to by the ·actual value· of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011435 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011436 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011437 elemDecl->namedTypeNs);
11438 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011439 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011440 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011441 (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011442 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011443 XML_SCHEMA_TYPE_BASIC, "type definition");
11444 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011445 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011446 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011447 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011448 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011449
Daniel Veillardc0826a72004-08-10 14:17:33 +000011450 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011451 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011452 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000011453 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011454 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
11455 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011456 if (substHead == NULL) {
11457 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011458 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011459 (xmlSchemaTypePtr) elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011460 "substitutionGroup", elemDecl->substGroup,
11461 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011462 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011463 xmlSchemaElementFixup(substHead, ctxt, NULL, NULL, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011464 /*
11465 * Set the "substitution group affiliation".
11466 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011467 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011468 elemDecl->refDecl = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011469 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011470 * (type definition)...otherwise the {type definition} of the
11471 * element declaration ·resolved· to by the ·actual value· of
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011472 * the substitutionGroup [attribute], if present
11473 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011474 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011475 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011476 }
11477 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011478 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType == NULL) &&
11479 (elemDecl->substGroup == NULL))
11480 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000011481}
11482
11483/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011484 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000011485 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011486 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000011487 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011488 * Checks and builds the "member type definitions" property of the union
11489 * simple type. This handles part (1), part (2) is done in
11490 * xmlSchemaFinishMemberTypeDefinitionsProperty()
11491 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000011492 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000011493 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011494static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011495xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
11496 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000011497{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011498
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011499 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011500 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000011501
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011502 /*
11503 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
11504 * define the explicit members as the type definitions ·resolved·
11505 * to by the items in the ·actual value· of the memberTypes [attribute],
11506 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011507 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000011508 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011509 /*
11510 * Resolve references.
11511 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011512 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011513 lastLink = NULL;
11514 while (link != NULL) {
11515 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011516
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011517 name = ((xmlSchemaQNameRefPtr) link->type)->name;
11518 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
11519
11520 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
11521 if ((memberType == NULL) || (! IS_SIMPLE_TYPE(memberType))) {
11522 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011523 type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011524 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
11525 /*
11526 * Remove the member type link.
11527 */
11528 if (lastLink == NULL)
11529 type->memberTypes = link->next;
11530 else
11531 lastLink->next = link->next;
11532 newLink = link;
11533 link = link->next;
11534 xmlFree(newLink);
11535 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011536 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011537 lastLink = link;
11538 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011539 }
11540 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011541 /*
11542 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011543 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011544 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011545 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011546 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
11547 if (link == NULL) {
11548 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
11549 return (-1);
11550 }
11551 link->type = memberType;
11552 link->next = NULL;
11553 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011554 type->memberTypes = link;
11555 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000011556 lastLink->next = link;
11557 lastLink = link;
11558 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011559 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011560 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000011561}
11562
Daniel Veillard4255d502002-04-16 15:50:10 +000011563/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011564 * xmlSchemaIsDerivedFromBuiltInType:
11565 * @ctxt: the schema parser context
11566 * @type: the type definition
11567 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011568 *
Daniel Veillard3646d642004-06-02 19:19:14 +000011569 *
11570 * Returns 1 if the type has the given value type, or
11571 * is derived from such a type.
11572 */
William M. Brack803812b2004-06-03 02:11:24 +000011573static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011574xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000011575{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011576 if (type == NULL)
11577 return (0);
11578 if (IS_COMPLEX_TYPE(type))
11579 return (0);
11580 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11581 if (type->builtInType == valType)
11582 return(1);
11583 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11584 (type->builtInType == XML_SCHEMAS_ANYTYPE))
11585 return (0);
11586 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11587 } else
11588 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000011589
11590 return (0);
11591}
11592
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011593#if 0
11594/**
11595 * xmlSchemaIsDerivedFromBuiltInType:
11596 * @ctxt: the schema parser context
11597 * @type: the type definition
11598 * @valType: the value type
11599 *
11600 *
11601 * Returns 1 if the type has the given value type, or
11602 * is derived from such a type.
11603 */
11604static int
11605xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
11606{
11607 if (type == NULL)
11608 return (0);
11609 if (IS_COMPLEX_TYPE(type))
11610 return (0);
11611 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11612 if (type->builtInType == valType)
11613 return(1);
11614 return (0);
11615 } else
11616 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11617
11618 return (0);
11619}
11620#endif
11621
11622static xmlSchemaTypePtr
11623xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
11624{
11625 if (type == NULL)
11626 return (NULL);
11627 if (IS_COMPLEX_TYPE(type))
11628 return (NULL);
11629 if (type->type == XML_SCHEMA_TYPE_BASIC)
11630 return(type);
11631 else
11632 return(xmlSchemaQueryBuiltInType(type->subtypes));
11633
11634 return (NULL);
11635}
11636
Daniel Veillard3646d642004-06-02 19:19:14 +000011637/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011638 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000011639 * @type: the simpleType definition
11640 *
11641 * Returns the primitive type of the given type or
11642 * NULL in case of error.
11643 */
11644static xmlSchemaTypePtr
11645xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
11646{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011647
Daniel Veillard01fa6152004-06-29 17:04:39 +000011648 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011649 /*
11650 * Note that anySimpleType is actually not a primitive type
11651 * but we need that here.
11652 */
11653 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11654 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000011655 return (type);
11656 type = type->baseType;
11657 }
11658
11659 return (NULL);
11660}
11661
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011662#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011663/**
11664 * xmlSchemaGetBuiltInTypeAncestor:
11665 * @type: the simpleType definition
11666 *
11667 * Returns the primitive type of the given type or
11668 * NULL in case of error.
11669 */
11670static xmlSchemaTypePtr
11671xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
11672{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011673 if (VARIETY_LIST(type) || VARIETY_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000011674 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011675 while (type != NULL) {
11676 if (type->type == XML_SCHEMA_TYPE_BASIC)
11677 return (type);
11678 type = type->baseType;
11679 }
11680
11681 return (NULL);
11682}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011683#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011684
Daniel Veillard01fa6152004-06-29 17:04:39 +000011685/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011686 * xmlSchemaBuildAttributeUsesOwned:
11687 * @ctxt: the schema parser context
11688 * @type: the complex type definition
11689 * @cur: the attribute declaration list
11690 * @lastUse: the top of the attribute use list
11691 *
11692 * Builds the attribute uses list on the given complex type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011693 * This one is supposed to be called by
Daniel Veillard3646d642004-06-02 19:19:14 +000011694 * xmlSchemaBuildAttributeValidation only.
11695 */
11696static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011697xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011698 xmlSchemaAttributePtr cur,
11699 xmlSchemaAttributeLinkPtr *uses,
11700 xmlSchemaAttributeLinkPtr *lastUse)
11701{
11702 xmlSchemaAttributeLinkPtr tmp;
11703 while (cur != NULL) {
11704 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011705 /*
11706 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
11707 * to by the ·actual value·s of the ref [attribute] of the
Daniel Veillard3646d642004-06-02 19:19:14 +000011708 * <attributeGroup> [children], if any."
11709 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011710 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
11711 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
Daniel Veillard3646d642004-06-02 19:19:14 +000011712 lastUse) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011713 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011714 }
11715 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011716 /* W3C: "1 The set of attribute uses corresponding to the
Daniel Veillard3646d642004-06-02 19:19:14 +000011717 * <attribute> [children], if any."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011718 */
11719 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +000011720 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11721 if (tmp == NULL) {
11722 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
11723 return (-1);
11724 }
11725 tmp->attr = cur;
11726 tmp->next = NULL;
11727 if (*uses == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011728 *uses = tmp;
11729 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011730 (*lastUse)->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011731 *lastUse = tmp;
11732 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011733 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011734 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011735 return (0);
11736}
11737
Daniel Veillard50355f02004-06-08 17:52:16 +000011738/**
11739 * xmlSchemaCloneWildcardNsConstraints:
11740 * @ctxt: the schema parser context
11741 * @dest: the destination wildcard
11742 * @source: the source wildcard
11743 *
11744 * Clones the namespace constraints of source
11745 * and assignes them to dest.
11746 * Returns -1 on internal error, 0 otherwise.
11747 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011748static int
11749xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
11750 xmlSchemaWildcardPtr *dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011751 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000011752{
11753 xmlSchemaWildcardNsPtr cur, tmp, last;
11754
11755 if ((source == NULL) || (*dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011756 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011757 (*dest)->any = source->any;
11758 cur = source->nsSet;
11759 last = NULL;
11760 while (cur != NULL) {
11761 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11762 if (tmp == NULL)
11763 return(-1);
11764 tmp->value = cur->value;
11765 if (last == NULL)
11766 (*dest)->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011767 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011768 last->next = tmp;
11769 last = tmp;
11770 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011771 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011772 if ((*dest)->negNsSet != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011773 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000011774 if (source->negNsSet != NULL) {
11775 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11776 if ((*dest)->negNsSet == NULL)
11777 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011778 (*dest)->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000011779 } else
11780 (*dest)->negNsSet = NULL;
11781 return(0);
11782}
11783
Daniel Veillard50355f02004-06-08 17:52:16 +000011784/**
11785 * xmlSchemaUnionWildcards:
11786 * @ctxt: the schema parser context
11787 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011788 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000011789 *
11790 * Unions the namespace constraints of the given wildcards.
11791 * @completeWild will hold the resulting union.
11792 * Returns a positive error code on failure, -1 in case of an
11793 * internal error, 0 otherwise.
11794 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011795static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011796xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011797 xmlSchemaWildcardPtr completeWild,
11798 xmlSchemaWildcardPtr curWild)
11799{
11800 xmlSchemaWildcardNsPtr cur, curB, tmp;
11801
11802 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011803 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000011804 * value.
11805 */
11806 if ((completeWild->any == curWild->any) &&
11807 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
11808 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011809
Daniel Veillard3646d642004-06-02 19:19:14 +000011810 if ((completeWild->negNsSet == NULL) ||
11811 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011812
Daniel Veillard3646d642004-06-02 19:19:14 +000011813 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000011814 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011815
11816 /*
11817 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000011818 */
11819 cur = completeWild->nsSet;
11820 while (cur != NULL) {
11821 found = 0;
11822 curB = curWild->nsSet;
11823 while (curB != NULL) {
11824 if (cur->value == curB->value) {
11825 found = 1;
11826 break;
11827 }
11828 curB = curB->next;
11829 }
11830 if (!found)
11831 break;
11832 cur = cur->next;
11833 }
11834 if (found)
11835 return(0);
11836 } else
11837 return(0);
11838 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011839 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011840 /*
11841 * 2 If either O1 or O2 is any, then any must be the value
11842 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011843 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011844 if (completeWild->any == 0) {
11845 completeWild->any = 1;
11846 if (completeWild->nsSet != NULL) {
11847 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11848 completeWild->nsSet = NULL;
11849 }
11850 if (completeWild->negNsSet != NULL) {
11851 xmlFree(completeWild->negNsSet);
11852 completeWild->negNsSet = NULL;
11853 }
11854 }
Daniel Veillard50355f02004-06-08 17:52:16 +000011855 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011856 }
11857 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011858 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000011859 * then the union of those sets must be the value.
11860 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011861 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011862 int found;
11863 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011864
Daniel Veillard3646d642004-06-02 19:19:14 +000011865 cur = curWild->nsSet;
11866 start = completeWild->nsSet;
11867 while (cur != NULL) {
11868 found = 0;
11869 curB = start;
11870 while (curB != NULL) {
11871 if (cur->value == curB->value) {
11872 found = 1;
11873 break;
11874 }
11875 curB = curB->next;
11876 }
11877 if (!found) {
11878 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011879 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011880 return (-1);
11881 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011882 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000011883 completeWild->nsSet = tmp;
11884 }
11885 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011886 }
11887
Daniel Veillard3646d642004-06-02 19:19:14 +000011888 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011889 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011890 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011891 * 4 If the two are negations of different values (namespace names
Daniel Veillard3646d642004-06-02 19:19:14 +000011892 * or ·absent·), then a pair of not and ·absent· must be the value.
11893 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011894 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011895 (curWild->negNsSet != NULL) &&
11896 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
11897 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000011898
11899 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011900 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011901 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011902 * 5.
11903 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011904 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011905 (completeWild->negNsSet->value != NULL) &&
11906 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011907 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011908 (curWild->negNsSet->value != NULL) &&
11909 (completeWild->nsSet != NULL))) {
11910
11911 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011912
Daniel Veillard3646d642004-06-02 19:19:14 +000011913 if (completeWild->nsSet != NULL) {
11914 cur = completeWild->nsSet;
11915 curB = curWild->negNsSet;
11916 } else {
11917 cur = curWild->nsSet;
11918 curB = completeWild->negNsSet;
11919 }
11920 nsFound = 0;
11921 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011922 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011923 absentFound = 1;
11924 else if (cur->value == curB->value)
11925 nsFound = 1;
11926 if (nsFound && absentFound)
11927 break;
11928 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011929 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011930
11931 if (nsFound && absentFound) {
11932 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011933 * 5.1 If the set S includes both the negated namespace
Daniel Veillard3646d642004-06-02 19:19:14 +000011934 * name and ·absent·, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011935 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011936 completeWild->any = 1;
11937 if (completeWild->nsSet != NULL) {
11938 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11939 completeWild->nsSet = NULL;
11940 }
11941 if (completeWild->negNsSet != NULL) {
11942 xmlFree(completeWild->negNsSet);
11943 completeWild->negNsSet = NULL;
11944 }
11945 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011946 /*
11947 * 5.2 If the set S includes the negated namespace name
11948 * but not ·absent·, then a pair of not and ·absent· must
Daniel Veillard3646d642004-06-02 19:19:14 +000011949 * be the value.
11950 */
11951 if (completeWild->nsSet != NULL) {
11952 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11953 completeWild->nsSet = NULL;
11954 }
11955 if (completeWild->negNsSet == NULL) {
11956 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11957 if (completeWild->negNsSet == NULL)
11958 return (-1);
11959 }
11960 completeWild->negNsSet->value = NULL;
11961 } else if ((!nsFound) && absentFound) {
11962 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011963 * 5.3 If the set S includes ·absent· but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000011964 * namespace name, then the union is not expressible.
11965 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011966 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000011967 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011968 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011969 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011970 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011971 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011972 /*
11973 * 5.4 If the set S does not include either the negated namespace
11974 * name or ·absent·, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000011975 * and a namespace name must be the value.
11976 */
11977 if (completeWild->negNsSet == NULL) {
11978 if (completeWild->nsSet != NULL) {
11979 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11980 completeWild->nsSet = NULL;
11981 }
11982 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11983 if (completeWild->negNsSet == NULL)
11984 return (-1);
11985 completeWild->negNsSet->value = curWild->negNsSet->value;
11986 }
11987 }
11988 return (0);
11989 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011990 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011991 * 6.
11992 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011993 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011994 (completeWild->negNsSet->value == NULL) &&
11995 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011996 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011997 (curWild->negNsSet->value == NULL) &&
11998 (completeWild->nsSet != NULL))) {
11999
12000 if (completeWild->nsSet != NULL) {
12001 cur = completeWild->nsSet;
12002 } else {
12003 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012004 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012005 while (cur != NULL) {
12006 if (cur->value == NULL) {
12007 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012008 * 6.1 If the set S includes ·absent·, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012009 * value.
12010 */
12011 completeWild->any = 1;
12012 if (completeWild->nsSet != NULL) {
12013 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12014 completeWild->nsSet = NULL;
12015 }
12016 if (completeWild->negNsSet != NULL) {
12017 xmlFree(completeWild->negNsSet);
12018 completeWild->negNsSet = NULL;
12019 }
12020 return (0);
12021 }
12022 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012023 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012024 if (completeWild->negNsSet == NULL) {
12025 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012026 * 6.2 If the set S does not include ·absent·, then a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012027 * and ·absent· must be the value.
12028 */
12029 if (completeWild->nsSet != NULL) {
12030 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12031 completeWild->nsSet = NULL;
12032 }
12033 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12034 if (completeWild->negNsSet == NULL)
12035 return (-1);
12036 completeWild->negNsSet->value = NULL;
12037 }
12038 return (0);
12039 }
12040 return (0);
12041
12042}
12043
Daniel Veillard50355f02004-06-08 17:52:16 +000012044/**
12045 * xmlSchemaIntersectWildcards:
12046 * @ctxt: the schema parser context
12047 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012048 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012049 *
12050 * Intersects the namespace constraints of the given wildcards.
12051 * @completeWild will hold the resulting intersection.
12052 * Returns a positive error code on failure, -1 in case of an
12053 * internal error, 0 otherwise.
12054 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012055static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012056xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012057 xmlSchemaWildcardPtr completeWild,
12058 xmlSchemaWildcardPtr curWild)
12059{
William M. Brack803812b2004-06-03 02:11:24 +000012060 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012061
12062 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012063 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012064 * value.
12065 */
12066 if ((completeWild->any == curWild->any) &&
12067 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
12068 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012069
Daniel Veillard3646d642004-06-02 19:19:14 +000012070 if ((completeWild->negNsSet == NULL) ||
12071 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012072
Daniel Veillard3646d642004-06-02 19:19:14 +000012073 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000012074 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012075
12076 /*
12077 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000012078 */
12079 cur = completeWild->nsSet;
12080 while (cur != NULL) {
12081 found = 0;
12082 curB = curWild->nsSet;
12083 while (curB != NULL) {
12084 if (cur->value == curB->value) {
12085 found = 1;
12086 break;
12087 }
12088 curB = curB->next;
12089 }
12090 if (!found)
12091 break;
12092 cur = cur->next;
12093 }
12094 if (found)
12095 return(0);
12096 } else
12097 return(0);
12098 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012099 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012100 /*
12101 * 2 If either O1 or O2 is any, then the other must be the value.
12102 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012103 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012104 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012105 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012106 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012107 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012108 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012109 * 3 If either O1 or O2 is a pair of not and a value (a namespace
12110 * name or ·absent·) and the other is a set of (namespace names or
12111 * ·absent·), then that set, minus the negated value if it was in
Daniel Veillard3646d642004-06-02 19:19:14 +000012112 * the set, minus ·absent· if it was in the set, must be the value.
12113 */
12114 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
12115 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
12116 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012117
Daniel Veillard3646d642004-06-02 19:19:14 +000012118 if (completeWild->nsSet == NULL) {
12119 neg = completeWild->negNsSet->value;
12120 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
12121 return(-1);
12122 } else
12123 neg = curWild->negNsSet->value;
12124 /*
12125 * Remove absent and negated.
12126 */
12127 prev = NULL;
12128 cur = completeWild->nsSet;
12129 while (cur != NULL) {
12130 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012131 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012132 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012133 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012134 prev->next = cur->next;
12135 xmlFree(cur);
12136 break;
12137 }
12138 prev = cur;
12139 cur = cur->next;
12140 }
12141 if (neg != NULL) {
12142 prev = NULL;
12143 cur = completeWild->nsSet;
12144 while (cur != NULL) {
12145 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012146 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012147 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012148 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012149 prev->next = cur->next;
12150 xmlFree(cur);
12151 break;
12152 }
12153 prev = cur;
12154 cur = cur->next;
12155 }
12156 }
12157
12158 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012159 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012160 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012161 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000012162 * then the intersection of those sets must be the value.
12163 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012164 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012165 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012166
Daniel Veillard3646d642004-06-02 19:19:14 +000012167 cur = completeWild->nsSet;
12168 prev = NULL;
12169 while (cur != NULL) {
12170 found = 0;
12171 curB = curWild->nsSet;
12172 while (curB != NULL) {
12173 if (cur->value == curB->value) {
12174 found = 1;
12175 break;
12176 }
12177 curB = curB->next;
12178 }
12179 if (!found) {
12180 if (prev == NULL)
12181 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012182 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012183 prev->next = cur->next;
12184 tmp = cur->next;
12185 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012186 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012187 continue;
12188 }
12189 prev = cur;
12190 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012191 }
12192
Daniel Veillard3646d642004-06-02 19:19:14 +000012193 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012194 }
12195 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000012196 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012197 */
12198 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012199 (curWild->negNsSet != NULL) &&
12200 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012201 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012202 (curWild->negNsSet->value != NULL)) {
12203
12204 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012205 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012206 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012207 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012208 }
12209 /*
12210 * 6 If the one is a negation of a namespace name and the other
12211 * is a negation of ·absent·, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000012212 * of a namespace name must be the value.
12213 */
12214 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
12215 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012216 (completeWild->negNsSet->value == NULL)) {
12217 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000012218 }
12219 return(0);
12220}
12221
Daniel Veillard50355f02004-06-08 17:52:16 +000012222/**
12223 * xmlSchemaIsWildcardNsConstraintSubset:
12224 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012225 * @sub: the first wildcard
12226 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012227 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012228 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
12229 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012230 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012231 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000012232 */
12233static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012234xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
12235 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012236{
Daniel Veillard50355f02004-06-08 17:52:16 +000012237 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012238 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000012239 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012240 if (super->any)
12241 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012242 /*
12243 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
12244 * 2.2 super must be a pair of not and the same value.
12245 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012246 if ((sub->negNsSet != NULL) &&
12247 (super->negNsSet != NULL) &&
12248 (sub->negNsSet->value == sub->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012249 return (0);
12250 /*
12251 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
Daniel Veillard50355f02004-06-08 17:52:16 +000012252 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012253 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012254 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012255 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000012256 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012257 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012258 xmlSchemaWildcardNsPtr cur, curB;
12259 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012260
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012261 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012262 while (cur != NULL) {
12263 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012264 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012265 while (curB != NULL) {
12266 if (cur->value == curB->value) {
12267 found = 1;
12268 break;
12269 }
12270 curB = curB->next;
12271 }
12272 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012273 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012274 cur = cur->next;
12275 }
12276 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012277 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012278 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012279 xmlSchemaWildcardNsPtr cur;
12280 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012281 * 3.2.2 super must be a pair of not and a namespace name or
12282 * ·absent· and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000012283 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012284 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012285 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012286 if (cur->value == super->negNsSet->value)
12287 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012288 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012289 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012290 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012291 }
12292 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012293 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012294}
12295
12296/**
12297 * xmlSchemaBuildCompleteAttributeWildcard:
12298 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012299 * @attrs: the attribute list
Daniel Veillard50355f02004-06-08 17:52:16 +000012300 * @completeWild: the resulting complete wildcard
12301 *
12302 * Returns -1 in case of an internal error, 0 otherwise.
12303 */
12304static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012305xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012306 xmlSchemaAttributePtr attrs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012307 xmlSchemaWildcardPtr *completeWild)
12308{
Daniel Veillard3646d642004-06-02 19:19:14 +000012309 while (attrs != NULL) {
12310 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12311 xmlSchemaAttributeGroupPtr group;
12312
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012313 group = (xmlSchemaAttributeGroupPtr) attrs;
12314 /*
12315 * Handle attribute group references.
12316 */
12317 if (group->ref != NULL) {
12318 if (group->refItem == NULL) {
12319 /*
12320 * TODO: Should we raise a warning here?
12321 */
12322 /*
12323 * The referenced attribute group definition could not
12324 * be resolved beforehand, so skip.
12325 */
12326 attrs = attrs->next;
12327 continue;
12328 } else
12329 group = group->refItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012330 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012331 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012332 * For every attribute group definition, an intersected wildcard
12333 * will be created (assumed that a wildcard exists on the
12334 * particular attr. gr. def. or on any contained attr. gr. def
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012335 * at all).
12336 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
12337 * that the intersection will be performed only once.
12338 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012339 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
12340 if (group->attributes != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012341 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012342 group->attributes, &group->attributeWildcard) == -1)
12343 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012344 }
12345 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012346 }
12347 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012348 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012349 /*
12350 * Copy the first encountered wildcard as context, except for the annotation.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012351 *
12352 * Although the complete wildcard might not correspond to any
12353 * node in the schema, we will save this context node.
Daniel Veillard3646d642004-06-02 19:19:14 +000012354 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012355 *completeWild = xmlSchemaAddWildcard(ctxt, ctxt->schema,
12356 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
12357 group->attributeWildcard->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012358 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012359 completeWild, group->attributeWildcard) == -1)
12360 return (-1);
12361 (*completeWild)->processContents = group->attributeWildcard->processContents;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012362 (*completeWild)->node = group->attributeWildcard->node;
12363 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1)
Daniel Veillard50355f02004-06-08 17:52:16 +000012364 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012365 }
12366 }
12367 attrs = attrs->next;
12368 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012369
12370 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012371}
12372
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012373static int
12374xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
12375 int *fixed,
12376 const xmlChar **value,
12377 xmlSchemaValPtr *val)
12378{
12379 *fixed = 0;
12380 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012381 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012382 *val = NULL;
12383
12384 if (item->defValue == NULL)
12385 item = item->refDecl;
12386
12387 if (item == NULL)
12388 return (0);
12389
12390 if (item->defValue != NULL) {
12391 *value = item->defValue;
12392 if (val != 0)
12393 *val = item->defVal;
12394 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
12395 *fixed = 1;
12396 return (1);
12397 }
12398 return (0);
12399}
Daniel Veillard3646d642004-06-02 19:19:14 +000012400/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012401 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000012402 * @wild: the wildcard
12403 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012404 *
12405 * Validation Rule: Wildcard allows Namespace Name
12406 * (cvc-wildcard-namespace)
12407 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012408 *
12409 * Returns 1 if the given namespace matches the wildcard,
12410 * 0 otherwise.
12411 */
12412static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012413xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
12414 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000012415{
12416 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012417 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012418
12419 if (wild->any)
12420 return(1);
12421 else if (wild->nsSet != NULL) {
12422 xmlSchemaWildcardNsPtr cur;
12423
12424 cur = wild->nsSet;
12425 while (cur != NULL) {
12426 if (xmlStrEqual(cur->value, ns))
12427 return(1);
12428 cur = cur->next;
12429 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012430 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012431 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012432 return(1);
12433
Daniel Veillard3646d642004-06-02 19:19:14 +000012434 return(0);
12435}
12436
12437/**
12438 * xmlSchemaBuildAttributeValidation:
12439 * @ctxt: the schema parser context
12440 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012441 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012442 *
12443 * Builds the wildcard and the attribute uses on the given complex type.
12444 * Returns -1 if an internal error occurs, 0 otherwise.
12445 */
12446static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012447xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr pctxt,
12448 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000012449{
12450 xmlSchemaTypePtr baseType = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012451 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL,
12452 prev = NULL, uses = NULL, lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000012453 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012454 xmlSchemaTypePtr anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012455 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012456 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000012457
Daniel Veillard01fa6152004-06-29 17:04:39 +000012458 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012459 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012460 * Complex Type Definition with complex content Schema Component.
12461 *
12462 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012463 * TODO: Add checks for absent referenced attribute declarations and
12464 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000012465 */
12466 if (type->attributeUses != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012467 PERROR_INT("xmlSchemaBuildAttributeValidation",
12468 "attribute uses already builded");
Daniel Veillard3646d642004-06-02 19:19:14 +000012469 return (-1);
12470 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012471 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012472 PERROR_INT("xmlSchemaBuildAttributeValidation",
12473 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012474 return (-1);
12475 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012476 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012477 /*
12478 * Inherit the attribute uses of the base type.
12479 */
12480 /*
12481 * NOTE: It is allowed to "extend" the anyType complex type.
12482 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012483 if (! IS_ANYTYPE(baseType)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012484 if (baseType != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012485 for (cur = baseType->attributeUses; cur != NULL;
12486 cur = cur->next) {
12487 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012488 xmlMalloc(sizeof(xmlSchemaAttributeLink));
12489 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012490 xmlSchemaPErrMemory(pctxt,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012491 "building attribute uses of complexType", NULL);
12492 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012493 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012494 tmp->attr = cur->attr;
12495 tmp->next = NULL;
12496 if (type->attributeUses == NULL) {
12497 type->attributeUses = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012498 } else
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012499 lastBaseUse->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012500 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012501 }
12502 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012503 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012504 attrs = type->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012505 /*
12506 * Handle attribute wildcards.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012507 */
12508 err = xmlSchemaBuildCompleteAttributeWildcard(pctxt,
12509 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012510 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012511 * NOTE: During the parse time, the wildcard is created on the complexType
12512 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012513 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012514 if (err == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012515 PERROR_INT("xmlSchemaBuildAttributeValidation",
12516 "failed to build an intersected attribute wildcard");
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012517 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012518 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012519
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012520 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
12521 ((IS_ANYTYPE(baseType)) ||
12522 ((baseType != NULL) &&
12523 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
12524 (baseType->attributeWildcard != NULL)))) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012525 if (type->attributeWildcard != NULL) {
12526 /*
12527 * Union the complete wildcard with the base wildcard.
12528 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012529 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012530 baseType->attributeWildcard) == -1)
12531 return (-1);
12532 } else {
12533 /*
12534 * Just inherit the wildcard.
12535 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012536 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012537 * NOTE: This is the only case where an attribute
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012538 * wildcard is shared.
12539 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012540 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000012541 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012542 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012543
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012544 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12545 if (type->attributeWildcard != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012546 /*
12547 * Derivation Valid (Restriction, Complex)
12548 * 4.1 The {base type definition} must also have one.
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012549 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012550 if (baseType->attributeWildcard == NULL) {
12551 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012552 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012553 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012554 "The type has an attribute wildcard, "
12555 "but the base type %s does not have one",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012556 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012557 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012558 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012559 } else if (xmlSchemaCheckCOSNSSubset(
12560 type->attributeWildcard, baseType->attributeWildcard)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012561 /* 4.2 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012562 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012563 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012564 NULL, type, NULL,
12565 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012566 "subset of the wildcard in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012567 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12568 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012569 return (1);
12570 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012571 /* 4.3 Unless the {base type definition} is the ·ur-type
12572 * definition·, the complex type definition's {attribute
12573 * wildcard}'s {process contents} must be identical to or
12574 * stronger than the {base type definition}'s {attribute
12575 * wildcard}'s {process contents}, where strict is stronger
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012576 * than lax is stronger than skip.
12577 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012578 if ((! IS_ANYTYPE(baseType)) &&
12579 (type->attributeWildcard->processContents <
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012580 baseType->attributeWildcard->processContents)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012581 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012582 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012583 NULL, type, NULL,
12584 "The 'process contents' of the attribute wildcard is "
12585 "weaker than the one in the base type %s",
12586 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012587 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012588 return (1);
12589 }
12590 }
12591 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12592 /*
12593 * Derivation Valid (Extension)
12594 * At this point the type and the base have both, either
12595 * no wildcard or a wildcard.
12596 */
12597 if ((baseType->attributeWildcard != NULL) &&
12598 (baseType->attributeWildcard != type->attributeWildcard)) {
12599 /* 1.3 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012600 if (xmlSchemaCheckCOSNSSubset(
12601 baseType->attributeWildcard, type->attributeWildcard)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012602 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012603 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012604 NULL, type, NULL,
12605 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012606 "superset of the one in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012607 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12608 FREE_AND_NULL(str)
12609 return (1);
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012610 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012611 }
12612 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012613
Daniel Veillard3646d642004-06-02 19:19:14 +000012614 /*
12615 * Gather attribute uses defined by this type.
12616 */
12617 if (attrs != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012618 if (xmlSchemaBuildAttributeUsesOwned(pctxt, attrs,
Daniel Veillard3646d642004-06-02 19:19:14 +000012619 &uses, &lastUse) == -1) {
12620 return (-1);
12621 }
12622 }
12623 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012624 * "Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012625 * not have identical {name}s and {target namespace}s."
12626 *
12627 * For "extension" this is done further down.
12628 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012629 if ((uses != NULL) && ((type->flags &
12630 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012631 cur = uses;
12632 while (cur != NULL) {
12633 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012634 while (tmp != NULL) {
12635 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012636 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012637 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012638 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
12639
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012640 xmlSchemaPAttrUseErr(pctxt,
12641 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12642 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012643 "Duplicate attribute use %s specified",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012644 xmlSchemaFormatQName(&str,
12645 xmlSchemaGetAttrTargetNsURI(tmp->attr),
12646 xmlSchemaGetAttrName(tmp->attr)));
12647 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000012648 break;
12649 }
12650 tmp = tmp->next;
12651 }
12652 cur = cur->next;
12653 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012654 }
12655 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012656 /*
12657 * Derive by restriction.
12658 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012659 if (IS_ANYTYPE(baseType)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012660 type->attributeUses = uses;
12661 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012662 int found, valid;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012663 const xmlChar *bEffValue;
12664 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000012665
12666 cur = uses;
12667 while (cur != NULL) {
12668 found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012669 valid = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012670 base = type->attributeUses;
12671 while (base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012672 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012673 xmlSchemaGetAttrName(base->attr)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012674 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012675 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012676
12677 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012678
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012679 if ((cur->attr->occurs ==
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012680 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12681 (base->attr->occurs ==
12682 XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
12683 /*
12684 * NOOP.
12685 */
12686 } else if ((cur->attr->occurs ==
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012687 XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
12688 (base->attr->occurs ==
12689 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012690 /*
12691 * derivation-ok-restriction 2.1.1
Daniel Veillard3646d642004-06-02 19:19:14 +000012692 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012693 xmlSchemaPAttrUseErr(pctxt,
12694 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
12695 type, cur->attr,
12696 "The 'optional' use is inconsistent with a "
12697 "matching 'required' use of the base type",
12698 NULL);
12699 } else if ((cur->attr->occurs ==
12700 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12701 (base->attr->occurs ==
12702 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
12703 /*
12704 * derivation-ok-restriction 3
12705 */
12706 xmlSchemaPCustomErr(pctxt,
12707 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
12708 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012709 "A matching attribute use for the 'required' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012710 "attribute use '%s' of the base type is "
12711 "missing",
12712 xmlSchemaFormatQName(&str,
12713 xmlSchemaGetAttrTargetNsURI(base->attr),
12714 xmlSchemaGetAttrName(base->attr)));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012715 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012716 } else if (xmlSchemaCheckCOSSTDerivedOK(
12717 cur->attr->subtypes, base->attr->subtypes, 0) != 0) {
12718
12719 /*
12720 * SPEC (2.1.2) "R's {attribute declaration}'s
12721 * {type definition} must be validly derived from
12722 * B's {type definition} given the empty set as
12723 * defined in Type Derivation OK (Simple) (§3.14.6)."
12724 */
12725 xmlSchemaPAttrUseErr(pctxt,
12726 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
12727 type, cur->attr,
12728 "The attribute declaration's type "
12729 "definition is not validly derived from "
12730 "the corresponding definition in the "
12731 "base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012732 } else {
12733 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012734 * 2.1.3 [Definition:] Let the effective value
12735 * constraint of an attribute use be its {value
12736 * constraint}, if present, otherwise its {attribute
12737 * declaration}'s {value constraint} .
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012738 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012739 xmlSchemaGetEffectiveValueConstraint(base->attr,
12740 &effFixed, &bEffValue, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012741 /*
12742 * 2.1.3 ... one of the following must be true
12743 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012744 * 2.1.3.1 B's ·effective value constraint· is
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012745 * ·absent· or default.
12746 */
12747 if ((bEffValue != NULL) &&
12748 (effFixed == 1)) {
12749 const xmlChar *rEffValue = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012750
12751 xmlSchemaGetEffectiveValueConstraint(base->attr,
12752 &effFixed, &rEffValue, 0);
12753 /*
12754 * 2.1.3.2 R's ·effective value constraint· is
12755 * fixed with the same string as B's.
12756 * TODO: Compare the computed values.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012757 */
12758 if ((effFixed == 0) ||
12759 (! xmlStrEqual(rEffValue, bEffValue))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012760 xmlSchemaPAttrUseErr(pctxt,
12761 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
12762 type, cur->attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012763 "The effective value constraint of the "
12764 "attribute use is inconsistent with "
12765 "its correspondent of the base type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012766 NULL);
12767 } else {
12768 /*
12769 * Override the attribute use.
12770 */
12771 base->attr = cur->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012772 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012773 } else
12774 base->attr = cur->attr;
Daniel Veillard3646d642004-06-02 19:19:14 +000012775 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012776
Daniel Veillard3646d642004-06-02 19:19:14 +000012777 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012778 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012779 base = base->next;
12780 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012781
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012782 if ((!found) && (cur->attr->occurs !=
12783 XML_SCHEMAS_ATTR_USE_PROHIBITED)) {
12784 /*
12785 * derivation-ok-restriction 2.2
12786 */
12787 if ((baseType->attributeWildcard == NULL) ||
12788 (xmlSchemaCheckCVCWildcardNamespace(
12789 baseType->attributeWildcard,
12790 cur->attr->targetNamespace) != 1)) {
12791 xmlSchemaPAttrUseErr(pctxt,
12792 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
12793 type, cur->attr,
12794 "Neither a matching attribute use, "
12795 "nor a matching wildcard in the base type does exist",
12796 NULL);
12797 } else {
12798 /*
12799 * Add the attribute use.
12800 *
12801 * Note that this may lead to funny derivation error reports, if
12802 * multiple equal attribute uses exist; but this is not
12803 * allowed anyway, and it will be reported beforehand.
12804 */
12805 tmp = cur;
12806 if (prev != NULL)
12807 prev->next = cur->next;
12808 else
12809 uses = cur->next;
12810 cur = cur->next;
12811 tmp->next = NULL;
12812 if (type->attributeUses == NULL) {
12813 type->attributeUses = tmp;
12814 } else
12815 lastBaseUse->next = tmp;
12816 lastBaseUse = tmp;
12817
12818 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000012819 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012820 }
12821 prev = cur;
Daniel Veillard3646d642004-06-02 19:19:14 +000012822 cur = cur->next;
12823 }
12824 if (uses != NULL)
12825 xmlSchemaFreeAttributeUseList(uses);
12826 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012827 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012828 /*
12829 * The spec allows only appending, and not other kinds of extensions.
12830 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012831 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
Daniel Veillard3646d642004-06-02 19:19:14 +000012832 */
12833 if (uses != NULL) {
12834 if (type->attributeUses == NULL) {
12835 type->attributeUses = uses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012836 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000012837 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012838 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012839 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012840 PERROR_INT("xmlSchemaBuildAttributeValidation",
12841 "no derivation method");
12842 return (-1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012843 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012844 /*
12845 * 3.4.6 -> Complex Type Definition Properties Correct
12846 */
12847 if (type->attributeUses != NULL) {
12848 cur = type->attributeUses;
12849 prev = NULL;
12850 while (cur != NULL) {
12851 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012852 * 4. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012853 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000012854 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012855 * Note that this was already done for "restriction" and types derived from
12856 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000012857 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012858 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12859 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012860 while (tmp != NULL) {
12861 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012862 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012863 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012864 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012865
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012866 xmlSchemaPAttrUseErr(pctxt,
12867 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12868 type, tmp->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012869 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012870 break;
12871 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012872 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012873 }
12874 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012875 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012876 * 5. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012877 * not have {type definition}s which are or are derived from ID.
12878 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012879 if ((cur->attr->subtypes != NULL) &&
12880 (xmlSchemaIsDerivedFromBuiltInType(cur->attr->subtypes,
12881 XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012882 if (id != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012883 xmlSchemaPAttrUseErr(pctxt,
12884 XML_SCHEMAP_CT_PROPS_CORRECT_5,
12885 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012886 "There must not exist more than one attribute use, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012887 "declared of type 'ID' or derived from it",
Daniel Veillardc0826a72004-08-10 14:17:33 +000012888 NULL);
12889 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012890 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012891 id = cur;
12892 }
12893 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012894 * Remove "prohibited" attribute uses. The reason this is done at this late
Daniel Veillard3646d642004-06-02 19:19:14 +000012895 * stage is to be able to catch dublicate attribute uses. So we had to keep
12896 * prohibited uses in the list as well.
12897 */
12898 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
12899 tmp = cur;
12900 if (prev == NULL)
12901 type->attributeUses = cur->next;
12902 else
12903 prev->next = cur->next;
12904 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012905 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000012906 } else {
12907 prev = cur;
12908 cur = cur->next;
12909 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012910 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012911 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012912 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012913 * TODO: This check should be removed if we are 100% sure of
12914 * the base type attribute uses already being built.
12915 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012916 if ((baseType != NULL) && (! IS_ANYTYPE(baseType)) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012917 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012918 (IS_NOT_TYPEFIXED(baseType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012919 PERROR_INT("xmlSchemaBuildAttributeValidation",
12920 "attribute uses not builded on base type");
12921 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012922 return (0);
12923}
12924
12925/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000012926 * xmlSchemaTypeFinalContains:
12927 * @schema: the schema
12928 * @type: the type definition
12929 * @final: the final
12930 *
12931 * Evaluates if a type definition contains the given "final".
12932 * This does take "finalDefault" into account as well.
12933 *
12934 * Returns 1 if the type does containt the given "final",
12935 * 0 otherwise.
12936 */
12937static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012938xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012939{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012940 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012941 return (0);
12942 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012943 return (1);
12944 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012945 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012946}
12947
12948/**
12949 * xmlSchemaGetUnionSimpleTypeMemberTypes:
12950 * @type: the Union Simple Type
12951 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012952 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012953 * returns NULL otherwise.
12954 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012955static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000012956xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
12957{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012958 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012959 if (type->memberTypes != NULL)
12960 return (type->memberTypes);
12961 else
12962 type = type->baseType;
12963 }
12964 return (NULL);
12965}
12966
12967/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012968 * xmlSchemaGetParticleTotalRangeMin:
12969 * @particle: the particle
12970 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012971 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012972 * (all and sequence) + (choice)
12973 *
12974 * Returns the minimun Effective Total Range.
12975 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012976static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012977xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012978{
12979 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012980 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012981 return (0);
12982 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012983 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012984 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012985 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012986
12987 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012988 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012989 while (part != NULL) {
12990 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
12991 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012992 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012993 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012994 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012995 if (cur == 0)
12996 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012997 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012998 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012999 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013000 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013001 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013002 } else {
13003 /* <all> and <sequence> */
13004 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013005 xmlSchemaParticlePtr part =
13006 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013007
13008 if (part == NULL)
13009 return (0);
13010 do {
13011 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13012 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013013 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013014 else
13015 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013016 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013017 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013018 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013019 }
13020}
13021
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013022/**
13023 * xmlSchemaGetParticleTotalRangeMax:
13024 * @particle: the particle
13025 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013026 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013027 * (all and sequence) + (choice)
13028 *
13029 * Returns the maximum Effective Total Range.
13030 */
13031static int
13032xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
13033{
13034 if ((particle->children == NULL) ||
13035 (particle->children->children == NULL))
13036 return (0);
13037 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
13038 int max = -1, cur;
13039 xmlSchemaParticlePtr part =
13040 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013041
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013042 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13043 if (part->children == NULL)
13044 continue;
13045 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13046 (part->children->type == XML_SCHEMA_TYPE_ANY))
13047 cur = part->maxOccurs;
13048 else
13049 cur = xmlSchemaGetParticleTotalRangeMax(part);
13050 if (cur == UNBOUNDED)
13051 return (UNBOUNDED);
13052 if ((max < cur) || (max == -1))
13053 max = cur;
13054 }
13055 /* TODO: Handle overflows? */
13056 return (particle->maxOccurs * max);
13057 } else {
13058 /* <all> and <sequence> */
13059 int sum = 0, cur;
13060 xmlSchemaParticlePtr part =
13061 (xmlSchemaParticlePtr) particle->children->children;
13062
13063 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13064 if (part->children == NULL)
13065 continue;
13066 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13067 (part->children->type == XML_SCHEMA_TYPE_ANY))
13068 cur = part->maxOccurs;
13069 else
13070 cur = xmlSchemaGetParticleTotalRangeMax(part);
13071 if (cur == UNBOUNDED)
13072 return (UNBOUNDED);
13073 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
13074 return (UNBOUNDED);
13075 sum += cur;
13076 }
13077 /* TODO: Handle overflows? */
13078 return (particle->maxOccurs * sum);
13079 }
13080}
13081
13082/**
13083 * xmlSchemaIsParticleEmptiable:
13084 * @particle: the particle
13085 *
13086 * Schema Component Constraint: Particle Emptiable
13087 * Checks whether the given particle is emptiable.
13088 *
13089 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013090 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013091static int
13092xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
13093{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013094 /*
13095 * SPEC (1) "Its {min occurs} is 0."
13096 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013097 if ((particle == NULL) || (particle->minOccurs == 0) ||
13098 (particle->children == NULL))
13099 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013100 /*
13101 * SPEC (2) "Its {term} is a group and the minimum part of the
13102 * effective total range of that group, [...] is 0."
13103 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013104 if (IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013105 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013106 return (1);
13107 }
13108 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013109}
13110
13111/**
13112 * xmlSchemaCheckCOSSTDerivedOK:
13113 * @type: the derived simple type definition
13114 * @baseType: the base type definition
13115 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013116 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013117 * Type Derivation OK (Simple) (cos-st-derived-OK)
13118 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013119 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000013120 * derived from @baseType.
13121 *
13122 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013123 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013124static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013125xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
13126 xmlSchemaTypePtr baseType,
13127 int subset)
13128{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013129 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013130 * 1 They are the same type definition.
13131 * TODO: The identy check might have to be more complex than this.
13132 */
13133 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013134 return (0);
13135 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013136 * 2.1 restriction is not in the subset, or in the {final}
13137 * of its own {base type definition};
13138 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013139 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013140 (xmlSchemaTypeFinalContains(type->baseType,
13141 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
13142 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013143 }
13144 /* 2.2 */
13145 if (type->baseType == baseType) {
13146 /*
13147 * 2.2.1 D's ·base type definition· is B.
13148 */
13149 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013150 }
13151 /*
13152 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
13153 * and is validly derived from B given the subset, as defined by this
13154 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013155 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013156 if ((! IS_ANYTYPE(type->baseType)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013157 (xmlSchemaCheckCOSSTDerivedOK(type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013158 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013159 return (0);
13160 }
13161 /*
13162 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
Daniel Veillard01fa6152004-06-29 17:04:39 +000013163 * definition·.
13164 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013165 if (IS_ANY_SIMPLE_TYPE(baseType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013166 (VARIETY_LIST(type) || VARIETY_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013167 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013168 }
13169 /*
13170 * 2.2.4 B's {variety} is union and D is validly derived from a type
13171 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000013172 * defined by this constraint.
13173 *
13174 * NOTE: This seems not to involve built-in types, since there is no
13175 * built-in Union Simple Type.
13176 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013177 if (VARIETY_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013178 xmlSchemaTypeLinkPtr cur;
13179
13180 cur = baseType->memberTypes;
13181 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013182 if (xmlSchemaCheckCOSSTDerivedOK(type, cur->type, subset) == 0)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013183 return (0);
13184 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013185 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013186 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013187
Daniel Veillard01fa6152004-06-29 17:04:39 +000013188 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
13189}
13190
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013191/**
13192 * xmlSchemaCheckTypeDefCircularInternal:
13193 * @pctxt: the schema parser context
13194 * @ctxtType: the type definition
13195 * @ancestor: an ancestor of @ctxtType
13196 *
13197 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013198 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013199 *
13200 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
13201 * circular, 0 otherwise.
13202 */
13203static int
13204xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
13205 xmlSchemaTypePtr ctxtType,
13206 xmlSchemaTypePtr ancestor)
13207{
13208 int ret;
13209
13210 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
13211 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013212
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013213 if (ctxtType == ancestor) {
13214 xmlSchemaPCustomErr(pctxt,
13215 XML_SCHEMAP_ST_PROPS_CORRECT_2,
13216 NULL, ctxtType, GET_NODE(ctxtType),
13217 "The definition is circular", NULL);
13218 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
13219 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013220 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
13221 /*
13222 * Avoid inifinite recursion on circular types not yet checked.
13223 */
13224 return (0);
13225 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013226 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
13227 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
13228 ancestor->baseType);
13229 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
13230 return (ret);
13231}
13232
13233/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013234 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013235 * @item: the complex/simple type definition
13236 * @ctxt: the parser context
13237 * @name: the name
13238 *
13239 * Checks for circular type definitions.
13240 */
13241static void
13242xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013243 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013244 const xmlChar * name ATTRIBUTE_UNUSED)
13245{
13246 if ((item == NULL) ||
13247 ((item->type != XML_SCHEMA_TYPE_COMPLEX) &&
13248 (item->type != XML_SCHEMA_TYPE_SIMPLE)))
13249 return;
13250 xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType);
13251
13252}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013253
13254/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013255 * xmlSchemaResolveTypeDefs:
13256 * @item: the complex/simple type definition
13257 * @ctxt: the parser context
13258 * @name: the name
13259 *
13260 * Checks for circular type definitions.
13261 */
13262static void
13263xmlSchemaResolveTypeDefs(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013264 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013265 const xmlChar * name ATTRIBUTE_UNUSED)
13266{
13267 if (typeDef == NULL)
13268 return;
13269
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013270 /*
13271 * Resolve the base type.
13272 */
13273 if (typeDef->baseType == NULL) {
13274 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
13275 typeDef->base, typeDef->baseNs);
13276 if (typeDef->baseType == NULL) {
13277 xmlSchemaPResCompAttrErr(ctxt,
13278 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013279 typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013280 "base", typeDef->base, typeDef->baseNs,
13281 XML_SCHEMA_TYPE_SIMPLE, NULL);
13282 return;
13283 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013284 }
13285 if (IS_SIMPLE_TYPE(typeDef)) {
13286 if (VARIETY_UNION(typeDef)) {
13287 /*
13288 * Resolve the memberTypes.
13289 */
13290 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
13291 return;
13292 } else if (VARIETY_LIST(typeDef)) {
13293 /*
13294 * Resolve the itemType.
13295 */
13296 if ((typeDef->subtypes == NULL) && (typeDef->ref != NULL)) {
13297 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
13298 typeDef->ref, typeDef->refNs);
13299 if ((typeDef->subtypes == NULL) ||
13300 (! IS_SIMPLE_TYPE(typeDef->subtypes))) {
13301 typeDef->subtypes = NULL;
13302 xmlSchemaPResCompAttrErr(ctxt,
13303 XML_SCHEMAP_SRC_RESOLVE,
13304 typeDef, typeDef->node,
13305 "itemType", typeDef->ref, typeDef->refNs,
13306 XML_SCHEMA_TYPE_SIMPLE, NULL);
13307 }
13308 }
13309 return;
13310 }
13311 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013312}
13313
13314
13315
13316/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013317 * xmlSchemaCheckSTPropsCorrect:
13318 * @ctxt: the schema parser context
13319 * @type: the simple type definition
13320 *
13321 * Checks st-props-correct.
13322 *
13323 * Returns 0 if the properties are correct,
13324 * if not, a positive error code and -1 on internal
13325 * errors.
13326 */
13327static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013328xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013329 xmlSchemaTypePtr type)
13330{
13331 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
13332 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013333 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013334
Daniel Veillardc0826a72004-08-10 14:17:33 +000013335 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013336 /*
13337 * Schema Component Constraint: Simple Type Definition Properties Correct
13338 *
13339 * NOTE: This is somehow redundant, since we actually built a simple type
13340 * to have all the needed information; this acts as an self test.
13341 */
13342 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13343 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013344 /* Base type: If the datatype has been ·derived· by ·restriction·
13345 * then the Simple Type Definition component from which it is ·derived·,
13346 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013347 */
13348 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013349 /*
13350 * TODO: Think about: "modulo the impact of Missing
13351 * Sub-components (§5.3)."
13352 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013353 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013354 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013355 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013356 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013357 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013358
Daniel Veillard01fa6152004-06-29 17:04:39 +000013359 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013360 if (! IS_SIMPLE_TYPE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013361 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013362 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013363 NULL, type, NULL,
13364 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013365 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013366 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013367 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13368 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013369 if ( (VARIETY_LIST(type) || VARIETY_UNION(type)) &&
13370 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) &&
13371 (! IS_ANY_SIMPLE_TYPE(baseType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013372 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013373 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013374 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013375 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013376 "the simple ur-type definition as base type, not '%s'",
13377 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013378 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013379 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13380 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013381 /*
13382 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013383 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013384 if ((! VARIETY_ATOMIC(type)) && (! VARIETY_UNION(type)) &&
13385 (! VARIETY_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013386 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013387 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013388 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013389 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013390 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13391 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013392 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013393
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013394 /*
13395 * 3 The {final} of the {base type definition} must not contain restriction.
13396 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013397 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013398 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
13399 xmlSchemaPCustomErr(ctxt,
13400 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013401 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013402 "The 'final' of its base type '%s' must not contain "
13403 "'restriction'",
13404 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013405 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013406 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013407 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013408
13409 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013410 * 2 All simple type definitions must be derived ultimately from the ·simple
13411 * ur-type definition (so· circular definitions are disallowed). That is, it
13412 * must be possible to reach a built-in primitive datatype or the ·simple
13413 * ur-type definition· by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013414 *
13415 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000013416 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013417 return (0);
13418}
13419
13420/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013421 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013422 * @ctxt: the schema parser context
13423 * @type: the simple type definition
13424 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013425 * Schema Component Constraint:
13426 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
13427
13428 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013429 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013430 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013431 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013432 * a positive error code otherwise.
13433 */
13434static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013435xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013436 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013437{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013438 xmlChar *str = NULL;
13439
Daniel Veillard01fa6152004-06-29 17:04:39 +000013440 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013441 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13442 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013443 return (-1);
13444 }
13445
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013446 if (VARIETY_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013447 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013448 /*
13449 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000013450 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013451 */
13452 if (! VARIETY_ATOMIC(type->baseType)) {
13453 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013454 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013455 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013456 "The base type '%s' is not an atomic simple type",
13457 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013458 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013459 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
13460 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013461 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000013462 * restriction.
13463 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013464 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013465 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013466 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013467 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013468 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013469 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013470 "The final of its base type '%s' must not contain 'restriction'",
13471 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013472 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013473 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
13474 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013475
13476 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013477 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013478 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013479 * Primitive datatypes.
13480 */
13481 if (type->facets != NULL) {
13482 xmlSchemaFacetPtr facet;
13483 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013484
Daniel Veillard01fa6152004-06-29 17:04:39 +000013485 primitive = xmlSchemaGetPrimitiveType(type);
13486 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013487 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13488 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013489 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013490 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013491 facet = type->facets;
13492 do {
13493 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013494 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013495 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013496 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013497 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013498 }
13499 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013500 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013501 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013502 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013503 }
13504 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013505 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
13506 * of the {base type definition} (call this BF),then the DF's {value}
13507 * must be a valid restriction of BF's {value} as defined in
13508 * [XML Schemas: Datatypes]."
13509 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013510 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013511 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013512 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013513 } else if (VARIETY_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013514 xmlSchemaTypePtr itemType = NULL;
13515
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013516 itemType = type->subtypes;
13517 if ((itemType == NULL) || (! IS_SIMPLE_TYPE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013518 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13519 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013520 return (-1);
13521 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013522 if (IS_NOT_TYPEFIXED(itemType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013523 xmlSchemaTypeFixup(itemType, pctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013524 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013525 * 2.1 The {item type definition} must have a {variety} of atomic or
13526 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013527 * must be atomic).
13528 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013529 if ((! VARIETY_ATOMIC(itemType)) &&
13530 (! VARIETY_UNION(itemType))) {
13531 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013532 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013533 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013534 "The item type '%s' does not have a variety of atomic or union",
13535 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013536 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013537 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013538 } else if (VARIETY_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013539 xmlSchemaTypeLinkPtr member;
13540
13541 member = itemType->memberTypes;
13542 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013543 if (! VARIETY_ATOMIC(member->type)) {
13544 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013545 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013546 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013547 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013548 "member type '%s' of this item type is not atomic",
13549 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013550 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013551 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
13552 }
13553 member = member->next;
13554 }
13555 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013556
13557 if (IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013558 xmlSchemaFacetPtr facet;
13559 /*
13560 * This is the case if we have: <simpleType><list ..
13561 */
13562 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013563 * 2.3.1
13564 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000013565 * contain list.
13566 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013567 if (xmlSchemaTypeFinalContains(itemType,
13568 XML_SCHEMAS_TYPE_FINAL_LIST)) {
13569 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013570 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013571 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013572 "The final of its item type '%s' must not contain 'list'",
13573 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013574 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013575 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
13576 }
13577 /*
13578 * 2.3.1.2 The {facets} must only contain the whiteSpace
13579 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013580 * OPTIMIZE TODO: the S4S already disallows any facet
13581 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013582 */
13583 if (type->facets != NULL) {
13584 facet = type->facets;
13585 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013586 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013587 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013588 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013589 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013590 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
13591 }
13592 facet = facet->next;
13593 } while (facet != NULL);
13594 }
13595 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013596 * MAYBE TODO: (Hmm, not really) Datatypes states:
13597 * A ·list· datatype can be ·derived· from an ·atomic· datatype
13598 * whose ·lexical space· allows space (such as string or anyURI)or
13599 * a ·union· datatype any of whose {member type definitions}'s
Daniel Veillard01fa6152004-06-29 17:04:39 +000013600 * ·lexical space· allows space.
13601 */
13602 } else {
13603 /*
13604 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013605 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013606 */
13607 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013608 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013609 * 2.3.2.1 The {base type definition} must have a {variety} of list.
13610 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013611 if (! VARIETY_LIST(type->baseType)) {
13612 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013613 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013614 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013615 "The base type '%s' must be a list type",
13616 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013617 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013618 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
13619 }
13620 /*
13621 * 2.3.2.2 The {final} of the {base type definition} must not
13622 * contain restriction.
13623 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013624 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013625 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013626 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013627 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013628 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013629 "The 'final' of the base type '%s' must not contain 'restriction'",
13630 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013631 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013632 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
13633 }
13634 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013635 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000013636 * from the {base type definition}'s {item type definition} given
13637 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
13638 */
13639 {
13640 xmlSchemaTypePtr baseItemType;
13641
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013642 baseItemType = type->baseType->subtypes;
13643 if ((baseItemType == NULL) || (! IS_SIMPLE_TYPE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013644 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13645 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013646 return (-1);
13647 }
13648 if ((itemType != baseItemType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013649 (xmlSchemaCheckCOSSTDerivedOK(itemType,
13650 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013651 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013652 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013653 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013654 NULL, type, NULL,
13655 "The item type '%s' is not validly derived from "
13656 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013657 xmlSchemaGetComponentQName(&str, itemType),
13658 xmlSchemaGetComponentQName(&strBIT, baseItemType),
13659 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013660
13661 FREE_AND_NULL(str)
13662 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013663 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013664 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
13665 }
13666 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013667
Daniel Veillard01fa6152004-06-29 17:04:39 +000013668 if (type->facets != NULL) {
13669 xmlSchemaFacetPtr facet;
13670 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013671 /*
13672 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000013673 * and enumeration facet components are allowed among the {facets}.
13674 */
13675 facet = type->facets;
13676 do {
13677 switch (facet->type) {
13678 case XML_SCHEMA_FACET_LENGTH:
13679 case XML_SCHEMA_FACET_MINLENGTH:
13680 case XML_SCHEMA_FACET_MAXLENGTH:
13681 case XML_SCHEMA_FACET_WHITESPACE:
13682 /*
13683 * TODO: 2.5.1.2 List datatypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013684 * The value of ·whiteSpace· is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013685 */
13686 case XML_SCHEMA_FACET_PATTERN:
13687 case XML_SCHEMA_FACET_ENUMERATION:
13688 break;
13689 default: {
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_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013692 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013693 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013694 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000013695 * invalid facets.
13696 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013697 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013698 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013699 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013700 facet = facet->next;
13701 } while (facet != NULL);
13702 if (ok == 0)
13703 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
13704 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013705 * SPEC (2.3.2.5) (same as 1.3.2)
13706 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013707 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013708 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013709 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013710 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013711 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013712 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013713 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013714 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000013715 * atomic or list.
13716 */
13717 xmlSchemaTypeLinkPtr member;
13718
13719 member = type->memberTypes;
13720 while (member != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013721 if (IS_NOT_TYPEFIXED(member->type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013722 xmlSchemaTypeFixup(member->type, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013723
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013724 if ((! VARIETY_ATOMIC(member->type)) &&
13725 (! VARIETY_LIST(member->type))) {
13726 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013727 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013728 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013729 "The member type '%s' is neither an atomic, nor a list type",
13730 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013731 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013732 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
13733 }
13734 member = member->next;
13735 }
13736 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013737 * 3.3.1 If the {base type definition} is the ·simple ur-type
13738 * definition·
Daniel Veillard01fa6152004-06-29 17:04:39 +000013739 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013740 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013741 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013742 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000013743 * {final} which does not contain union.
13744 */
13745 member = type->memberTypes;
13746 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013747 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013748 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013749 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013750 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013751 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013752 "The 'final' of member type '%s' contains 'union'",
13753 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013754 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013755 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
13756 }
13757 member = member->next;
13758 }
13759 /*
13760 * 3.3.1.2 The {facets} must be empty.
13761 */
13762 if (type->facetSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013763 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013764 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013765 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013766 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013767 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
13768 }
13769 } else {
13770 /*
13771 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013772 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013773 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013774 if (! VARIETY_UNION(type->baseType)) {
13775 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013776 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013777 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013778 "The base type '%s' is not a union type",
13779 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013780 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013781 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
13782 }
13783 /*
13784 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
13785 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013786 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013787 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013788 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013789 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013790 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013791 "The 'final' of its base type '%s' must not contain 'restriction'",
13792 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013793 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013794 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
13795 }
13796 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013797 * 3.3.2.3 The {member type definitions}, in order, must be validly
13798 * derived from the corresponding type definitions in the {base
13799 * type definition}'s {member type definitions} given the empty set,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013800 * as defined in Type Derivation OK (Simple) (§3.14.6).
13801 */
13802 {
13803 xmlSchemaTypeLinkPtr baseMember;
13804
13805 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013806 * OPTIMIZE: if the type is restricting, it has no local defined
13807 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013808 * thus a check for equality can be skipped.
13809 */
13810 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013811 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013812 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000013813 * types of it's base type. This check seems not necessary with
13814 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013815 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013816 */
13817 if (type->memberTypes != NULL) {
13818 member = type->memberTypes;
13819 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013820 if ((member == NULL) && (baseMember != NULL)) {
13821 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13822 "different number of member types in base");
13823 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013824 while (member != NULL) {
13825 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013826 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13827 "different number of member types in base");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013828 }
13829 if ((member->type != baseMember->type) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013830 (xmlSchemaCheckCOSSTDerivedOK(
13831 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013832 xmlChar *strBMT = NULL, *strBT = NULL;
13833
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013834 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013835 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
13836 NULL, type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013837 "The member type %s is not validly "
13838 "derived from its corresponding member "
13839 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013840 xmlSchemaGetComponentQName(&str, member->type),
13841 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
13842 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013843 FREE_AND_NULL(str)
13844 FREE_AND_NULL(strBMT)
13845 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013846 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013847 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013848 member = member->next;
13849 baseMember = baseMember->next;
13850 }
13851 }
13852 }
13853 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013854 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000013855 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013856 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013857 if (type->facets != NULL) {
13858 xmlSchemaFacetPtr facet;
13859 int ok = 1;
13860
13861 facet = type->facets;
13862 do {
13863 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
13864 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013865 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013866 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013867 NULL, type, facet);
13868 ok = 0;
13869 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013870 facet = facet->next;
13871 } while (facet != NULL);
13872 if (ok == 0)
13873 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013874
Daniel Veillard01fa6152004-06-29 17:04:39 +000013875 }
13876 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013877 * SPEC (3.3.2.5) (same as 1.3.2)
13878 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013879 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013880 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013881 */
13882 }
13883 }
13884
13885 return (0);
13886}
13887
13888/**
13889 * xmlSchemaCheckSRCSimpleType:
13890 * @ctxt: the schema parser context
13891 * @type: the simple type definition
13892 *
13893 * Checks crc-simple-type constraints.
13894 *
13895 * Returns 0 if the constraints are satisfied,
13896 * if not a positive error code and -1 on internal
13897 * errors.
13898 */
13899static int
13900xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
13901 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013902{
13903 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013904 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013905 * must satisfy the conditions set out in Constraints on Simple Type
13906 * Definition Schema Components (§3.14.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013907 */
13908 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
13909 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
13910 /*
13911 * TODO: Removed this, since it got annoying to get an
13912 * extra error report, if anything failed until now.
13913 * Enable this if needed.
13914 */
13915 /*
13916 xmlSchemaPErr(ctxt, type->node,
13917 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013918 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000013919 "on simple type definitions.\n",
13920 type->name, NULL);
13921 */
13922 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
13923 }
13924
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013925 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013926 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013927 * src-simple-type.2 If the <restriction> alternative is chosen,
13928 * either it must have a base [attribute] or a <simpleType> among its
Daniel Veillard01fa6152004-06-29 17:04:39 +000013929 * [children], but not both.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013930 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013931 /*
13932 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013933 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013934 */
13935 } else if (VARIETY_LIST(type)) {
13936 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
13937 * an itemType [attribute] or a <simpleType> among its [children],
Daniel Veillard01fa6152004-06-29 17:04:39 +000013938 * but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013939 *
13940 * REMOVED: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013941 */
13942 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013943 xmlSchemaTypeLinkPtr member;
13944 xmlSchemaTypePtr ancestor, anySimpleType;
13945
13946 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13947
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013948 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
13949 * the <union> alternative is chosen, there must not be any entries
13950 * in the memberTypes [attribute] at any depth which resolve to the
Daniel Veillard01fa6152004-06-29 17:04:39 +000013951 * component corresponding to the <simpleType>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013952 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013953 member = type->memberTypes;
13954 while (member != NULL) {
13955 ancestor = member->type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013956 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013957 if (ancestor == type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013958 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013959 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013960 NULL, type, NULL,
13961 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013962 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013963 }
13964 if (IS_NOT_TYPEFIXED(ancestor))
13965 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013966 if (VARIETY_LIST(ancestor)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013967 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000013968 * TODO, FIXME: Although a list simple type must not have a union ST
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013969 * type as item type, which in turn has a list ST as member
13970 * type, we will assume this here as well, since this check
Daniel Veillard01fa6152004-06-29 17:04:39 +000013971 * was not yet performed.
13972 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013973 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013974
Daniel Veillard01fa6152004-06-29 17:04:39 +000013975 ancestor = ancestor->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013976 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013977 member = member->next;
13978 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013979 }
13980
13981 return (0);
13982}
13983
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013984static int
13985xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
13986{
13987 if (ctxt->vctxt == NULL) {
13988 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
13989 if (ctxt->vctxt == NULL) {
13990 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013991 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013992 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013993 "failed to create a temp. validation context.\n",
13994 NULL, NULL);
13995 return (-1);
13996 }
13997 /* TODO: Pass user data. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013998 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013999 }
14000 return (0);
14001}
14002
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014003static int
14004xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
14005 xmlNodePtr node,
14006 xmlSchemaTypePtr type,
14007 const xmlChar *value,
14008 xmlSchemaValPtr *retVal,
14009 int fireErrors,
14010 int normalize,
14011 int isNormalized);
14012
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014013/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014014 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014015 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014016 * @type: the simple type definition
14017 * @value: the default value
14018 * @node: an optional node (the holder of the value)
14019 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014020 * Schema Component Constraint: Element Default Valid (Immediate)
14021 * (cos-valid-default)
14022 * This will be used by the parser only. For the validator there's
14023 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014024 *
14025 * Returns 0 if the constraints are satisfied,
14026 * if not, a positive error code and -1 on internal
14027 * errors.
14028 */
14029static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014030xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
14031 xmlNodePtr node,
14032 xmlSchemaTypePtr type,
14033 const xmlChar *value,
14034 xmlSchemaValPtr *val)
14035{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014036 int ret = 0;
14037
14038 /*
14039 * cos-valid-default:
14040 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014041 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014042 * definition the appropriate case among the following must be true:
14043 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014044 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014045 /*
14046 * Complex type.
14047 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014048 * SPEC (2.1) "its {content type} must be a simple type definition
14049 * or mixed."
14050 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014051 * type}'s particle must be ·emptiable· as defined by
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014052 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014053 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014054 if ((! HAS_SIMPLE_CONTENT(type)) &&
14055 ((! HAS_MIXED_CONTENT(type)) || (! IS_PARTICLE_EMPTIABLE(type)))) {
14056 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014057 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014058 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014059 NULL, type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014060 "For a string to be a valid default, the type definition "
14061 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014062 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014063 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
14064 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014065 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014066 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014067 * 1 If the type definition is a simple type definition, then the string
14068 * must be ·valid· with respect to that definition as defined by String
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014069 * Valid (§3.14.4).
14070 *
14071 * AND
14072 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014073 * 2.2.1 If the {content type} is a simple type definition, then the
14074 * string must be ·valid· with respect to that simple type definition
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014075 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014076 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014077 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014078 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14079 type, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014080 else if (HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014081 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14082 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014083 else
14084 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014085
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014086 if (ret < 0) {
14087 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
14088 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014089 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014090
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014091 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000014092}
14093
14094/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014095 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000014096 * @ctxt: the schema parser context
14097 * @type: the complex type definition
14098 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014099 *.(4.6) Constraints on Complex Type Definition Schema Components
14100 * Schema Component Constraint:
14101 * Complex Type Definition Properties Correct (ct-props-correct)
14102 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000014103 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014104 * Returns 0 if the constraints are satisfied, a positive
14105 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000014106 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014107static int
14108xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
14109 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000014110{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014111 /*
14112 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
14113 *
14114 * SPEC (1) "The values of the properties of a complex type definition must
14115 * be as described in the property tableau in The Complex Type Definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014116 * Schema Component (§3.4.1), modulo the impact of Missing
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014117 * Sub-components (§5.3)."
14118 */
14119 if ((type->baseType != NULL) &&
14120 (IS_SIMPLE_TYPE(type->baseType)) &&
14121 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
14122 /*
14123 * SPEC (2) "If the {base type definition} is a simple type definition,
14124 * the {derivation method} must be extension."
14125 */
14126 xmlSchemaPCustomErr(pctxt,
14127 XML_SCHEMAP_SRC_CT_1,
14128 NULL, type, NULL,
14129 "If the base type is a simple type, the derivation method must be "
14130 "'extension'", NULL);
14131 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014132 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014133 /*
14134 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
14135 * definition·. That is, it must be possible to reach the ·ur-type
14136 * definition by repeatedly following the {base type definition}."
14137 *
14138 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
14139 *
14140 * SPEC (4) "Two distinct attribute declarations in the {attribute uses}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014141 * must not have identical {name}s and {target namespace}s."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014142 * SPEC (5) "Two distinct attribute declarations in the {attribute uses}
14143 * must not have {type definition}s which are or are derived from ID."
14144 *
14145 * NOTE (4) and (5) are done in xmlSchemaBuildAttributeValidation().
14146 */
14147 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014148}
14149
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014150static int
14151xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
14152 xmlSchemaTypePtr typeB)
14153{
14154 /*
14155 * TODO: This should implement component-identity
14156 * in the future.
14157 */
14158 if ((typeA == NULL) || (typeB == NULL))
14159 return (0);
14160 return (typeA == typeB);
14161}
14162
14163/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014164 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014165 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014166 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014167 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014168 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014169 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014170 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014171 * Type Derivation OK (Complex) (cos-ct-derived-ok)
14172 *
14173 * STATUS: completed
14174 *
14175 * Returns 0 if the constraints are satisfied, or 1
14176 * if not.
14177 */
14178static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014179xmlSchemaCheckCOSCTDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014180 xmlSchemaTypePtr baseType,
14181 int set)
14182{
14183 int equal = xmlSchemaAreEqualTypes(type, baseType);
14184 /* TODO: Error codes. */
14185 /*
14186 * SPEC "For a complex type definition (call it D, for derived)
14187 * to be validly derived from a type definition (call this
14188 * B, for base) given a subset of {extension, restriction}
14189 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014190 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014191 if (! equal) {
14192 /*
14193 * SPEC (1) "If B and D are not the same type definition, then the
14194 * {derivation method} of D must not be in the subset."
14195 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014196 if (((set & SUBSET_EXTENSION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014197 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014198 ((set & SUBSET_RESTRICTION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014199 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014200 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014201 } else {
14202 /*
14203 * SPEC (2.1) "B and D must be the same type definition."
14204 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014205 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014206 }
14207 /*
14208 * SPEC (2.2) "B must be D's {base type definition}."
14209 */
14210 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014211 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014212 /*
14213 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
14214 * definition·."
14215 */
14216 if (IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014217 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014218
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014219 if (IS_COMPLEX_TYPE(type->baseType)) {
14220 /*
14221 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
14222 * must be validly derived from B given the subset as defined by this
14223 * constraint."
14224 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014225 return (xmlSchemaCheckCOSCTDerivedOK(type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014226 baseType, set));
14227 } else {
14228 /*
14229 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
14230 * must be validly derived from B given the subset as defined in Type
14231 * Derivation OK (Simple) (§3.14.6).
14232 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014233 return (xmlSchemaCheckCOSSTDerivedOK(type->baseType, baseType, set));
14234 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014235}
14236
14237/**
14238 * xmlSchemaCheckCOSDerivedOK:
14239 * @type: the derived simple type definition
14240 * @baseType: the base type definition
14241 *
14242 * Calls:
14243 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014244 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014245 * Checks wheter @type can be validly derived from @baseType.
14246 *
14247 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014248 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014249static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014250xmlSchemaCheckCOSDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014251 xmlSchemaTypePtr baseType,
14252 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014253{
14254 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014255 return (xmlSchemaCheckCOSSTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014256 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014257 return (xmlSchemaCheckCOSCTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014258}
14259
William M. Brack2f2a6632004-08-20 23:09:47 +000014260/**
14261 * xmlSchemaCheckCOSCTExtends:
14262 * @ctxt: the schema parser context
14263 * @type: the complex type definition
14264 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014265 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014266 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014267 * Derivation Valid (Extension) (cos-ct-extends)
14268 *
14269 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014270 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014271 * (1.5)
14272 * (1.4.3.2.2.2) "Particle Valid (Extension)", which is not really needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014273 *
14274 * Returns 0 if the constraints are satisfied, a positive
14275 * error code if not and -1 if an internal error occured.
14276 */
14277static int
14278xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
14279 xmlSchemaTypePtr type)
14280{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014281 xmlSchemaTypePtr base = type->baseType;
14282 /*
14283 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14284 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000014285 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014286 /*
14287 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014288 * then all of the following must be true:"
14289 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014290 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
14291 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014292 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014293 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000014294 */
14295 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14296 xmlSchemaPCustomErr(ctxt,
14297 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14298 NULL, type, NULL,
14299 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014300 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000014301 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14302 }
14303 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014304 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014305 * uses}
14306 * of the complex type definition itself, that is, for every attribute
14307 * use in the {attribute uses} of the {base type definition}, there
14308 * must be an attribute use in the {attribute uses} of the complex
14309 * type definition itself whose {attribute declaration} has the same
14310 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014311 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000014312 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014313 * NOTE (1.2): This will be already satisfied by the way the attribute
14314 * uses are extended in xmlSchemaBuildAttributeValidation(); thus this
14315 * check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014316 */
14317
14318 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014319 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
14320 * definition must also have one, and the base type definition's
14321 * {attribute wildcard}'s {namespace constraint} must be a subset
14322 * of the complex type definition's {attribute wildcard}'s {namespace
14323 * constraint}, as defined by Wildcard Subset (§3.10.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014324 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014325 * NOTE (1.3) This is already checked in
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014326 * xmlSchemaBuildAttributeValidation; thus this check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014327 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014328 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014329 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014330 if ((type->contentTypeDef != NULL) &&
14331 (type->contentTypeDef == base->contentTypeDef)) {
14332 /*
14333 * SPEC (1.4.1) "The {content type} of the {base type definition}
14334 * and the {content type} of the complex type definition itself
14335 * must be the same simple type definition"
14336 * PASS
14337 */
14338 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
14339 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
14340 /*
14341 * SPEC (1.4.2) "The {content type} of both the {base type
14342 * definition} and the complex type definition itself must
14343 * be empty."
14344 * PASS
14345 */
14346 } else {
14347 /*
14348 * SPEC (1.4.3) "All of the following must be true:"
14349 */
14350 if (type->subtypes == NULL) {
14351 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014352 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014353 * definition itself must specify a particle.
14354 */
14355 xmlSchemaPCustomErr(ctxt,
14356 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14357 NULL, type, NULL,
14358 "The content type must specify a particle", NULL);
14359 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14360 }
14361 /*
14362 * SPEC (1.4.3.2) "One of the following must be true:"
14363 */
14364 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14365 /*
14366 * SPEC (1.4.3.2.1) "The {content type} of the {base type
14367 * definition} must be empty.
14368 * PASS
14369 */
14370 } else {
14371 /*
14372 * SPEC (1.4.3.2.2) "All of the following must be true:"
14373 */
14374 if ((type->contentType != base->contentType) ||
14375 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
14376 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
14377 /*
14378 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
14379 * or both must be element-only."
14380 */
14381 xmlSchemaPCustomErr(ctxt,
14382 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14383 NULL, type, NULL,
14384 "The content type of both, the type and its base "
14385 "type, must either 'mixed' or 'element-only'", NULL);
14386 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014387 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014388 /*
14389 * FUTURE TODO SPEC (1.4.3.2.2.2) "The particle of the
14390 * complex type definition must be a ·valid extension·
14391 * of the {base type definition}'s particle, as defined
14392 * in Particle Valid (Extension) (§3.9.6)."
14393 *
14394 * NOTE that we won't check "Particle Valid (Extension)",
14395 * since it is ensured by the derivation process in
14396 * xmlSchemaTypeFixup(). We need to implement this when heading
14397 * for a construction API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014398 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014399 }
14400 /*
14401 * TODO (1.5)
14402 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014403 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014404 } else {
14405 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014406 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014407 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014408 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014409 if (type->contentTypeDef != base) {
14410 /*
14411 * SPEC (2.1) "The {content type} must be the same simple type
14412 * definition."
14413 */
14414 xmlSchemaPCustomErr(ctxt,
14415 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14416 NULL, type, NULL,
14417 "The content type must be the simple base type", NULL);
14418 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14419 }
14420 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14421 /*
14422 * SPEC (2.2) "The {final} of the {base type definition} must not
14423 * contain extension"
14424 * NOTE that this is the same as (1.1).
14425 */
14426 xmlSchemaPCustomErr(ctxt,
14427 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14428 NULL, type, NULL,
14429 "The 'final' of the base type definition "
14430 "contains 'extension'", NULL);
14431 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014432 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014433 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014434 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014435}
14436
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014437/**
14438 * xmlSchemaCheckDerivationOKRestriction:
14439 * @ctxt: the schema parser context
14440 * @type: the complex type definition
14441 *
14442 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014443 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014444 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
14445 *
14446 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014447 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014448 * (5.4.2), (5.2.2.1)
14449 *
14450 * Returns 0 if the constraints are satisfied, a positive
14451 * error code if not and -1 if an internal error occured.
14452 */
14453static int
14454xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
14455 xmlSchemaTypePtr type)
14456{
14457 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014458
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014459 /*
14460 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14461 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014462 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014463 base = type->baseType;
14464 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
14465 /*
14466 * SPEC (1) "The {base type definition} must be a complex type
14467 * definition whose {final} does not contain restriction."
14468 */
14469 xmlSchemaPCustomErr(ctxt,
14470 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14471 NULL, type, NULL,
14472 "The 'final' of the base type definition "
14473 "contains 'restriction'", NULL);
14474 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14475 }
14476 /*
14477 * NOTE (3) and (4) are done in xmlSchemaBuildAttributeValidation().
14478 *
14479 * SPEC (5) "One of the following must be true:"
14480 */
14481 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
14482 /*
14483 * SPEC (5.1) "The {base type definition} must be the
14484 * ·ur-type definition·."
14485 * PASS
14486 */
14487 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14488 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14489 /*
14490 * SPEC (5.2.1) "The {content type} of the complex type definition
14491 * must be a simple type definition"
14492 *
14493 * SPEC (5.2.2) "One of the following must be true:"
14494 */
14495 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14496 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14497 /*
14498 * SPEC (5.2.2.1) "The {content type} of the {base type
14499 * definition} must be a simple type definition from which
14500 * the {content type} is validly derived given the empty
14501 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
14502 * URGENT TODO
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014503 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014504 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14505 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014506 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014507 /*
14508 * SPEC (5.2.2.2) "The {base type definition} must be mixed
14509 * and have a particle which is ·emptiable· as defined in
14510 * Particle Emptiable (§3.9.6)."
14511 * PASS
14512 */
14513 } else {
14514 xmlSchemaPCustomErr(ctxt,
14515 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14516 NULL, type, NULL,
14517 "The content type of the base type must be either "
14518 "a simple type or 'mixed' and an emptiable particle", NULL);
14519 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14520 }
14521 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14522 /*
14523 * SPEC (5.3.1) "The {content type} of the complex type itself must
14524 * be empty"
14525 */
14526 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14527 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014528 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014529 * definition} must also be empty."
14530 * PASS
14531 */
14532 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
14533 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
14534 xmlSchemaIsParticleEmptiable(
14535 (xmlSchemaParticlePtr) base->subtypes)) {
14536 /*
14537 * SPEC (5.3.2.2) "The {content type} of the {base type
14538 * definition} must be elementOnly or mixed and have a particle
14539 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
14540 * PASS
14541 */
14542 } else {
14543 xmlSchemaPCustomErr(ctxt,
14544 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14545 NULL, type, NULL,
14546 "The content type of the base type must be either "
14547 "empty or 'mixed' (or 'elements-only') and an emptiable "
14548 "particle", NULL);
14549 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14550 }
14551 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014552 HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014553 /*
14554 * SPEC (5.4.1.1) "The {content type} of the complex type definition
14555 * itself must be element-only"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014556 */
14557 if (HAS_MIXED_CONTENT(type) && (! HAS_MIXED_CONTENT(base))) {
14558 /*
14559 * SPEC (5.4.1.2) "The {content type} of the complex type
14560 * definition itself and of the {base type definition} must be
14561 * mixed"
14562 */
14563 xmlSchemaPCustomErr(ctxt,
14564 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14565 NULL, type, NULL,
14566 "If the content type is 'mixed', then the content type of the "
14567 "base type must also be 'mixed'", NULL);
14568 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14569 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014570 /*
14571 * SPEC (5.4.2) "The particle of the complex type definition itself
14572 * must be a ·valid restriction· of the particle of the {content
14573 * type} of the {base type definition} as defined in Particle Valid
14574 * (Restriction) (§3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014575 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014576 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014577 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014578 } else {
14579 xmlSchemaPCustomErr(ctxt,
14580 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14581 NULL, type, NULL,
14582 "The type is not a valid restriction of its base type", NULL);
14583 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14584 }
14585 return (0);
14586}
14587
14588/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014589 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014590 * @ctxt: the schema parser context
14591 * @type: the complex type definition
14592 *
14593 * (3.4.6) Constraints on Complex Type Definition Schema Components
14594 *
14595 * Returns 0 if the constraints are satisfied, a positive
14596 * error code if not and -1 if an internal error occured.
14597 */
14598static int
14599xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
14600 xmlSchemaTypePtr type)
14601{
14602 int ret;
14603 /*
14604 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014605 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014606 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
14607 if (ret != 0)
14608 return (ret);
14609 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
14610 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
14611 else
14612 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
14613 return (ret);
14614}
14615
14616/**
14617 * xmlSchemaCheckSRCCT:
14618 * @ctxt: the schema parser context
14619 * @type: the complex type definition
14620 *
14621 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014622 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014623 * Complex Type Definition Representation OK (src-ct)
14624 *
14625 * Returns 0 if the constraints are satisfied, a positive
14626 * error code if not and -1 if an internal error occured.
14627 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014628static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014629xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014630 xmlSchemaTypePtr type)
14631{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014632 xmlSchemaTypePtr base;
14633 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014634
14635 /*
14636 * TODO: Adjust the error codes here, as I used
14637 * XML_SCHEMAP_SRC_CT_1 only yet.
14638 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014639 base = type->baseType;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014640 if (! HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014641 /*
14642 * 1 If the <complexContent> alternative is chosen, the type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014643 * ·resolved· to by the ·actual value· of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014644 * must be a complex type definition;
14645 */
14646 if (! IS_COMPLEX_TYPE(base)) {
14647 xmlChar *str = NULL;
14648 xmlSchemaPCustomErr(ctxt,
14649 XML_SCHEMAP_SRC_CT_1,
14650 NULL, type, type->node,
14651 "If using <complexContent>, the base type is expected to be "
14652 "a complex type. The base type '%s' is a simple type",
14653 xmlSchemaFormatQName(&str, base->targetNamespace,
14654 base->name));
14655 FREE_AND_NULL(str)
14656 return (XML_SCHEMAP_SRC_CT_1);
14657 }
14658 } else {
14659 /*
14660 * SPEC
14661 * 2 If the <simpleContent> alternative is chosen, all of the
14662 * following must be true:
14663 * 2.1 The type definition ·resolved· to by the ·actual value· of the
14664 * base [attribute] must be one of the following:
14665 */
14666 if (IS_SIMPLE_TYPE(base)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014667 if ((type->flags &
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014668 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0) {
14669 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014670 /*
14671 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014672 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014673 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014674 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014675 xmlSchemaPCustomErr(ctxt,
14676 XML_SCHEMAP_SRC_CT_1,
14677 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014678 "If using <simpleContent> and <restriction>, the base "
14679 "type must be a complex type. The base type '%s' is "
14680 "a simple type",
14681 xmlSchemaFormatQName(&str, base->targetNamespace,
14682 base->name));
14683 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014684 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014685 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014686 } else {
14687 /* Base type is a complex type. */
14688 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14689 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14690 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014691 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014692 * simple type definition;
14693 * PASS
14694 */
14695 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014696 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014697 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014698 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014699 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014700 type->name);
14701 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014702 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014703 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14704 (type->flags &
14705 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014706
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014707 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014708 * 2.1.2 only if the <restriction> alternative is also
14709 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014710 * is mixed and a particle emptiable.
14711 */
14712 if (! xmlSchemaIsParticleEmptiable(
14713 (xmlSchemaParticlePtr) base->subtypes)) {
14714 ret = XML_SCHEMAP_SRC_CT_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014715 } else
14716 /*
14717 * Attention: at this point the <simpleType> child is in
14718 * ->contentTypeDef (put there during parsing).
14719 */
14720 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014721 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014722 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014723 * 2.2 If clause 2.1.2 above is satisfied, then there
14724 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014725 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014726 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014727 /* TODO: Change error code to ..._SRC_CT_2_2. */
14728 xmlSchemaPCustomErr(ctxt,
14729 XML_SCHEMAP_SRC_CT_1,
14730 NULL, type, NULL,
14731 "A <simpleType> is expected among the children "
14732 "of <restriction>, if <simpleContent> is used and "
14733 "the base type '%s' is a complex type",
14734 xmlSchemaFormatQName(&str, base->targetNamespace,
14735 base->name));
14736 FREE_AND_NULL(str)
14737 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014738 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014739 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014740 ret = XML_SCHEMAP_SRC_CT_1;
14741 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014742 }
14743 if (ret > 0) {
14744 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014745 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014746 xmlSchemaPCustomErr(ctxt,
14747 XML_SCHEMAP_SRC_CT_1,
14748 NULL, type, NULL,
14749 "If <simpleContent> and <restriction> is used, the "
14750 "base type must be a simple type or a complex type with "
14751 "mixed content and particle emptiable. The base type "
14752 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014753 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014754 base->name));
14755 } else {
14756 xmlSchemaPCustomErr(ctxt,
14757 XML_SCHEMAP_SRC_CT_1,
14758 NULL, type, NULL,
14759 "If <simpleContent> and <extension> is used, the "
14760 "base type must be a simple type. The base type '%s' "
14761 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014762 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014763 base->name));
14764 }
14765 FREE_AND_NULL(str)
14766 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014767 }
14768 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014769 * SPEC (3) "The corresponding complex type definition component must
14770 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014771 * Definition Schema Components (§3.4.6);"
14772 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014773 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014774 /*
14775 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014776 * above for {attribute wildcard} is satisfied, the intensional
14777 * intersection must be expressible, as defined in Attribute Wildcard
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014778 * Intersection (§3.10.6).
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014779 * NOTE (4) is done in xmlSchemaBuildAttributeValidation().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014780 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014781 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014782}
William M. Brack2f2a6632004-08-20 23:09:47 +000014783
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014784#ifdef ENABLE_PARTICLE_RESTRICTION
14785/**
14786 * xmlSchemaCheckParticleRangeOK:
14787 * @ctxt: the schema parser context
14788 * @type: the complex type definition
14789 *
14790 * (3.9.6) Constraints on Particle Schema Components
14791 * Schema Component Constraint:
14792 * Occurrence Range OK (range-ok)
14793 *
14794 * STATUS: complete
14795 *
14796 * Returns 0 if the constraints are satisfied, a positive
14797 * error code if not and -1 if an internal error occured.
14798 */
14799static int
14800xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
14801 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014802{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014803 if (rmin < bmin)
14804 return (1);
14805 if ((bmax != UNBOUNDED) &&
14806 (rmax > bmax))
14807 return (1);
14808 return (0);
14809}
14810
14811/**
14812 * xmlSchemaCheckRCaseNameAndTypeOK:
14813 * @ctxt: the schema parser context
14814 * @r: the restricting element declaration particle
14815 * @b: the base element declaration particle
14816 *
14817 * (3.9.6) Constraints on Particle Schema Components
14818 * Schema Component Constraint:
14819 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
14820 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014821 *
14822 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014823 * MISSING (3.2.3)
14824 * CLARIFY: (3.2.2)
14825 *
14826 * Returns 0 if the constraints are satisfied, a positive
14827 * error code if not and -1 if an internal error occured.
14828 */
14829static int
14830xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
14831 xmlSchemaParticlePtr r,
14832 xmlSchemaParticlePtr b)
14833{
14834 xmlSchemaElementPtr elemR, elemB;
14835
14836 /* TODO: Error codes (rcase-NameAndTypeOK). */
14837 elemR = (xmlSchemaElementPtr) r->children;
14838 elemB = (xmlSchemaElementPtr) b->children;
14839 /*
14840 * SPEC (1) "The declarations' {name}s and {target namespace}s are
14841 * the same."
14842 */
14843 if ((elemR != elemB) &&
14844 ((! xmlStrEqual(elemR->name, elemB->name)) ||
14845 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
14846 return (1);
14847 /*
14848 * SPEC (2) "R's occurrence range is a valid restriction of B's
14849 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
14850 */
14851 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
14852 b->minOccurs, b->maxOccurs) != 0)
14853 return (1);
14854 /*
14855 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
14856 * {scope} are global."
14857 */
14858 if (elemR == elemB)
14859 return (0);
14860 /*
14861 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
14862 */
14863 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
14864 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
14865 return (1);
14866 /*
14867 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
14868 * or is not fixed, or R's declaration's {value constraint} is fixed
14869 * with the same value."
14870 */
14871 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
14872 ((elemR->value == NULL) ||
14873 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
14874 /* TODO: Equality of the initial value or normalized or canonical? */
14875 (! xmlStrEqual(elemR->value, elemB->value))))
14876 return (1);
14877 /*
14878 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
14879 * definitions} is a subset of B's declaration's {identity-constraint
14880 * definitions}, if any."
14881 */
14882 if (elemB->idcs != NULL) {
14883 /* TODO */
14884 }
14885 /*
14886 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
14887 * superset of B's declaration's {disallowed substitutions}."
14888 */
14889 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
14890 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
14891 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
14892 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
14893 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
14894 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
14895 return (1);
14896 /*
14897 * SPEC (3.2.5) "R's {type definition} is validly derived given
14898 * {extension, list, union} from B's {type definition}"
14899 *
14900 * BADSPEC TODO: What's the point of adding "list" and "union" to the
14901 * set, if the corresponding constraints handle "restriction" and
14902 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014903 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014904 */
14905 {
14906 int set = 0;
14907
14908 set |= SUBSET_EXTENSION;
14909 set |= SUBSET_LIST;
14910 set |= SUBSET_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014911 if (xmlSchemaCheckCOSDerivedOK(elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014912 elemB->subtypes, set) != 0)
14913 return (1);
14914 }
14915 return (0);
14916}
14917
14918/**
14919 * xmlSchemaCheckRCaseNSCompat:
14920 * @ctxt: the schema parser context
14921 * @r: the restricting element declaration particle
14922 * @b: the base wildcard particle
14923 *
14924 * (3.9.6) Constraints on Particle Schema Components
14925 * Schema Component Constraint:
14926 * Particle Derivation OK (Elt:Any -- NSCompat)
14927 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014928 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014929 * STATUS: complete
14930 *
14931 * Returns 0 if the constraints are satisfied, a positive
14932 * error code if not and -1 if an internal error occured.
14933 */
14934static int
14935xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
14936 xmlSchemaParticlePtr r,
14937 xmlSchemaParticlePtr b)
14938{
14939 /* TODO:Error codes (rcase-NSCompat). */
14940 /*
14941 * SPEC "For an element declaration particle to be a ·valid restriction·
14942 * of a wildcard particle all of the following must be true:"
14943 *
14944 * SPEC (1) "The element declaration's {target namespace} is ·valid·
14945 * with respect to the wildcard's {namespace constraint} as defined by
14946 * Wildcard allows Namespace Name (§3.10.4)."
14947 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014948 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014949 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
14950 return (1);
14951 /*
14952 * SPEC (2) "R's occurrence range is a valid restriction of B's
14953 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
14954 */
14955 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
14956 b->minOccurs, b->maxOccurs) != 0)
14957 return (1);
14958
14959 return (0);
14960}
14961
14962/**
14963 * xmlSchemaCheckRCaseRecurseAsIfGroup:
14964 * @ctxt: the schema parser context
14965 * @r: the restricting element declaration particle
14966 * @b: the base model group particle
14967 *
14968 * (3.9.6) Constraints on Particle Schema Components
14969 * Schema Component Constraint:
14970 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
14971 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014972 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014973 * STATUS: TODO
14974 *
14975 * Returns 0 if the constraints are satisfied, a positive
14976 * error code if not and -1 if an internal error occured.
14977 */
14978static int
14979xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
14980 xmlSchemaParticlePtr r,
14981 xmlSchemaParticlePtr b)
14982{
14983 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
14984 TODO
14985 return (0);
14986}
14987
14988/**
14989 * xmlSchemaCheckRCaseNSSubset:
14990 * @ctxt: the schema parser context
14991 * @r: the restricting wildcard particle
14992 * @b: the base wildcard particle
14993 *
14994 * (3.9.6) Constraints on Particle Schema Components
14995 * Schema Component Constraint:
14996 * Particle Derivation OK (Any:Any -- NSSubset)
14997 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014998 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014999 * STATUS: complete
15000 *
15001 * Returns 0 if the constraints are satisfied, a positive
15002 * error code if not and -1 if an internal error occured.
15003 */
15004static int
15005xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
15006 xmlSchemaParticlePtr r,
15007 xmlSchemaParticlePtr b,
15008 int isAnyTypeBase)
15009{
15010 /* TODO: Error codes (rcase-NSSubset). */
15011 /*
15012 * SPEC (1) "R's occurrence range is a valid restriction of B's
15013 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15014 */
15015 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15016 b->minOccurs, b->maxOccurs))
15017 return (1);
15018 /*
15019 * SPEC (2) "R's {namespace constraint} must be an intensional subset
15020 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
15021 */
15022 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
15023 (xmlSchemaWildcardPtr) b->children))
15024 return (1);
15025 /*
15026 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
15027 * definition·, R's {process contents} must be identical to or stronger
15028 * than B's {process contents}, where strict is stronger than lax is
15029 * stronger than skip."
15030 */
15031 if (! isAnyTypeBase) {
15032 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
15033 ((xmlSchemaWildcardPtr) b->children)->processContents)
15034 return (1);
15035 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015036
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015037 return (0);
15038}
15039
15040/**
15041 * xmlSchemaCheckCOSParticleRestrict:
15042 * @ctxt: the schema parser context
15043 * @type: the complex type definition
15044 *
15045 * (3.9.6) Constraints on Particle Schema Components
15046 * Schema Component Constraint:
15047 * Particle Valid (Restriction) (cos-particle-restrict)
15048 *
15049 * STATUS: TODO
15050 *
15051 * Returns 0 if the constraints are satisfied, a positive
15052 * error code if not and -1 if an internal error occured.
15053 */
15054static int
15055xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
15056 xmlSchemaParticlePtr r,
15057 xmlSchemaParticlePtr b)
15058{
15059 int ret = 0;
15060
15061 /*part = GET_PARTICLE(type);
15062 basePart = GET_PARTICLE(base);
15063 */
15064
15065 TODO
15066
15067 /*
15068 * SPEC (1) "They are the same particle."
15069 */
15070 if (r == b)
15071 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015072
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015073
15074 return (0);
15075}
15076
15077/**
15078 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
15079 * @ctxt: the schema parser context
15080 * @r: the model group particle
15081 * @b: the base wildcard particle
15082 *
15083 * (3.9.6) Constraints on Particle Schema Components
15084 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015085 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015086 * NSRecurseCheckCardinality)
15087 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015088 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015089 * STATUS: TODO: subst-groups
15090 *
15091 * Returns 0 if the constraints are satisfied, a positive
15092 * error code if not and -1 if an internal error occured.
15093 */
15094static int
15095xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
15096 xmlSchemaParticlePtr r,
15097 xmlSchemaParticlePtr b)
15098{
15099 xmlSchemaParticlePtr part;
15100 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
15101 if ((r->children == NULL) || (r->children->children == NULL))
15102 return (-1);
15103 /*
15104 * SPEC "For a group particle to be a ·valid restriction· of a
15105 * wildcard particle..."
15106 *
15107 * SPEC (1) "Every member of the {particles} of the group is a ·valid
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015108 * restriction· of the wildcard as defined by
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015109 * Particle Valid (Restriction) (§3.9.6)."
15110 */
15111 part = (xmlSchemaParticlePtr) r->children->children;
15112 do {
15113 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
15114 return (1);
15115 part = (xmlSchemaParticlePtr) part->next;
15116 } while (part != NULL);
15117 /*
15118 * SPEC (2) "The effective total range of the group [...] is a
15119 * valid restriction of B's occurrence range as defined by
15120 * Occurrence Range OK (§3.9.6)."
15121 */
15122 if (xmlSchemaCheckParticleRangeOK(
15123 xmlSchemaGetParticleTotalRangeMin(r),
15124 xmlSchemaGetParticleTotalRangeMax(r),
15125 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015126 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015127 return (0);
15128}
15129
15130/**
15131 * xmlSchemaCheckRCaseRecurse:
15132 * @ctxt: the schema parser context
15133 * @r: the <all> or <sequence> model group particle
15134 * @b: the base <all> or <sequence> model group particle
15135 *
15136 * (3.9.6) Constraints on Particle Schema Components
15137 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015138 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015139 Recurse)
15140 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015141 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015142 * STATUS: ?
15143 * TODO: subst-groups
15144 *
15145 * Returns 0 if the constraints are satisfied, a positive
15146 * error code if not and -1 if an internal error occured.
15147 */
15148static int
15149xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
15150 xmlSchemaParticlePtr r,
15151 xmlSchemaParticlePtr b)
15152{
15153 /* xmlSchemaParticlePtr part; */
15154 /* TODO: Error codes (rcase-Recurse). */
15155 if ((r->children == NULL) || (b->children == NULL) ||
15156 (r->children->type != b->children->type))
15157 return (-1);
15158 /*
15159 * SPEC "For an all or sequence group particle to be a ·valid
15160 * restriction· of another group particle with the same {compositor}..."
15161 *
15162 * SPEC (1) "R's occurrence range is a valid restriction of B's
15163 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15164 */
15165 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15166 b->minOccurs, b->maxOccurs))
15167 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015168
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015169
15170 return (0);
15171}
15172
15173#endif
15174
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015175#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
15176 xmlSchemaPCustomErrExt(pctxt, \
15177 XML_SCHEMAP_INVALID_FACET_VALUE, \
15178 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
15179 "It is an error for both '%s' and '%s' to be specified on the "\
15180 "same type definition", \
15181 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
15182 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
15183
15184#define FACET_RESTR_ERR(fac1, msg) \
15185 xmlSchemaPCustomErr(pctxt, \
15186 XML_SCHEMAP_INVALID_FACET_VALUE, \
15187 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015188 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015189
15190#define FACET_RESTR_FIXED_ERR(fac) \
15191 xmlSchemaPCustomErr(pctxt, \
15192 XML_SCHEMAP_INVALID_FACET_VALUE, \
15193 NULL, (xmlSchemaTypePtr) fac, fac->node, \
15194 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015195 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015196
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015197static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015198xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
15199 xmlSchemaFacetPtr facet1,
15200 xmlSchemaFacetPtr facet2,
15201 int lessGreater,
15202 int orEqual,
15203 int ofBase)
15204{
15205 xmlChar *msg = NULL;
15206
15207 msg = xmlStrdup(BAD_CAST "'");
15208 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
15209 msg = xmlStrcat(msg, BAD_CAST "' has to be");
15210 if (lessGreater == 0)
15211 msg = xmlStrcat(msg, BAD_CAST " equal to");
15212 if (lessGreater == 1)
15213 msg = xmlStrcat(msg, BAD_CAST " greater than");
15214 else
15215 msg = xmlStrcat(msg, BAD_CAST " less than");
15216
15217 if (orEqual)
15218 msg = xmlStrcat(msg, BAD_CAST " or equal to");
15219 msg = xmlStrcat(msg, BAD_CAST " '");
15220 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
15221 if (ofBase)
15222 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
15223 else
15224 msg = xmlStrcat(msg, BAD_CAST "'");
15225
15226 xmlSchemaPCustomErr(pctxt,
15227 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015228 NULL, (xmlSchemaTypePtr) facet1, facet1->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015229 (const char *) msg, NULL);
15230
15231 if (msg != NULL)
15232 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015233}
15234
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015235static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015236xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
15237 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015238{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015239 xmlSchemaTypePtr base = type->baseType;
15240 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015241 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015242 flength = NULL, ftotdig = NULL, ffracdig = NULL,
15243 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
15244 fmininc = NULL, fmaxinc = NULL,
15245 fminexc = NULL, fmaxexc = NULL,
15246 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
15247 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
15248 bfmininc = NULL, bfmaxinc = NULL,
15249 bfminexc = NULL, bfmaxexc = NULL;
15250 int res, err = 0, fixedErr;
15251 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015252 * 3 The {facets} of R are the union of S and the {facets}
15253 * of B, eliminating duplicates. To eliminate duplicates,
15254 * when a facet of the same kind occurs in both S and the
15255 * {facets} of B, the one in the {facets} of B is not
15256 * included, with the exception of enumeration and pattern
15257 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015258 * are allowed.
15259 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015260
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015261 if ((type->facetSet == NULL) && (base->facetSet == NULL))
15262 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015263
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015264 last = type->facetSet;
15265 if (last != NULL)
15266 while (last->next != NULL)
15267 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015268
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015269 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
15270 facet = cur->facet;
15271 switch (facet->type) {
15272 case XML_SCHEMA_FACET_LENGTH:
15273 flength = facet; break;
15274 case XML_SCHEMA_FACET_MINLENGTH:
15275 fminlen = facet; break;
15276 case XML_SCHEMA_FACET_MININCLUSIVE:
15277 fmininc = facet; break;
15278 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15279 fminexc = facet; break;
15280 case XML_SCHEMA_FACET_MAXLENGTH:
15281 fmaxlen = facet; break;
15282 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15283 fmaxinc = facet; break;
15284 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15285 fmaxexc = facet; break;
15286 case XML_SCHEMA_FACET_TOTALDIGITS:
15287 ftotdig = facet; break;
15288 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15289 ffracdig = facet; break;
15290 default:
15291 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015292 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015293 }
15294 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15295 facet = cur->facet;
15296 switch (facet->type) {
15297 case XML_SCHEMA_FACET_LENGTH:
15298 bflength = facet; break;
15299 case XML_SCHEMA_FACET_MINLENGTH:
15300 bfminlen = facet; break;
15301 case XML_SCHEMA_FACET_MININCLUSIVE:
15302 bfmininc = facet; break;
15303 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15304 bfminexc = facet; break;
15305 case XML_SCHEMA_FACET_MAXLENGTH:
15306 bfmaxlen = facet; break;
15307 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15308 bfmaxinc = facet; break;
15309 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15310 bfmaxexc = facet; break;
15311 case XML_SCHEMA_FACET_TOTALDIGITS:
15312 bftotdig = facet; break;
15313 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15314 bffracdig = facet; break;
15315 default:
15316 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015317 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015318 }
15319 err = 0;
15320 /*
15321 * length and minLength or maxLength (2.2) + (3.2)
15322 */
15323 if (flength && (fminlen || fmaxlen)) {
15324 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
15325 "either of 'minLength' or 'maxLength' to be specified on "
15326 "the same type definition")
15327 }
15328 /*
15329 * Mutual exclusions in the same derivation step.
15330 */
15331 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015332 /*
15333 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015334 */
15335 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
15336 }
15337 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015338 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015339 * SCC "minInclusive and minExclusive"
15340 */
15341 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015342 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015343
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015344 if (flength && bflength) {
15345 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015346 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015347 * The values have to be equal.
15348 */
15349 res = xmlSchemaCompareValues(flength->val, bflength->val);
15350 if (res == -2)
15351 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015352 if (res != 0)
15353 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
15354 if ((res != 0) && (bflength->fixed)) {
15355 FACET_RESTR_FIXED_ERR(flength)
15356 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015357
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015358 }
15359 if (fminlen && bfminlen) {
15360 /*
15361 * SCC "minLength valid restriction"
15362 * minLength >= BASE minLength
15363 */
15364 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
15365 if (res == -2)
15366 goto internal_error;
15367 if (res == -1)
15368 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
15369 if ((res != 0) && (bfminlen->fixed)) {
15370 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015371 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015372 }
15373 if (fmaxlen && bfmaxlen) {
15374 /*
15375 * SCC "maxLength valid restriction"
15376 * maxLength <= BASE minLength
15377 */
15378 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
15379 if (res == -2)
15380 goto internal_error;
15381 if (res == 1)
15382 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
15383 if ((res != 0) && (bfmaxlen->fixed)) {
15384 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015385 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015386 }
15387 /*
15388 * SCC "length and minLength or maxLength"
15389 */
15390 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015391 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015392 if (flength) {
15393 if (! fminlen)
15394 flength = bflength;
15395 if (fminlen) {
15396 /* (1.1) length >= minLength */
15397 res = xmlSchemaCompareValues(flength->val, fminlen->val);
15398 if (res == -2)
15399 goto internal_error;
15400 if (res == -1)
15401 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
15402 }
15403 if (! fmaxlen)
15404 fmaxlen = bfmaxlen;
15405 if (fmaxlen) {
15406 /* (2.1) length <= maxLength */
15407 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
15408 if (res == -2)
15409 goto internal_error;
15410 if (res == 1)
15411 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
15412 }
15413 }
15414 if (fmaxinc) {
15415 /*
15416 * "maxInclusive"
15417 */
15418 if (fmininc) {
15419 /* SCC "maxInclusive >= minInclusive" */
15420 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
15421 if (res == -2)
15422 goto internal_error;
15423 if (res == -1) {
15424 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
15425 }
15426 }
15427 /*
15428 * SCC "maxInclusive valid restriction"
15429 */
15430 if (bfmaxinc) {
15431 /* maxInclusive <= BASE maxInclusive */
15432 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
15433 if (res == -2)
15434 goto internal_error;
15435 if (res == 1)
15436 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
15437 if ((res != 0) && (bfmaxinc->fixed)) {
15438 FACET_RESTR_FIXED_ERR(fmaxinc)
15439 }
15440 }
15441 if (bfmaxexc) {
15442 /* maxInclusive < BASE maxExclusive */
15443 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
15444 if (res == -2)
15445 goto internal_error;
15446 if (res != -1) {
15447 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
15448 }
15449 }
15450 if (bfmininc) {
15451 /* maxInclusive >= BASE minInclusive */
15452 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
15453 if (res == -2)
15454 goto internal_error;
15455 if (res == -1) {
15456 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
15457 }
15458 }
15459 if (bfminexc) {
15460 /* maxInclusive > BASE minExclusive */
15461 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
15462 if (res == -2)
15463 goto internal_error;
15464 if (res != 1) {
15465 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
15466 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015467 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015468 }
15469 if (fmaxexc) {
15470 /*
15471 * "maxExclusive >= minExclusive"
15472 */
15473 if (fminexc) {
15474 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
15475 if (res == -2)
15476 goto internal_error;
15477 if (res == -1) {
15478 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
15479 }
15480 }
15481 /*
15482 * "maxExclusive valid restriction"
15483 */
15484 if (bfmaxexc) {
15485 /* maxExclusive <= BASE maxExclusive */
15486 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
15487 if (res == -2)
15488 goto internal_error;
15489 if (res == 1) {
15490 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
15491 }
15492 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015493 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015494 }
15495 }
15496 if (bfmaxinc) {
15497 /* maxExclusive <= BASE maxInclusive */
15498 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
15499 if (res == -2)
15500 goto internal_error;
15501 if (res == 1) {
15502 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
15503 }
15504 }
15505 if (bfmininc) {
15506 /* maxExclusive > BASE minInclusive */
15507 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
15508 if (res == -2)
15509 goto internal_error;
15510 if (res != 1) {
15511 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
15512 }
15513 }
15514 if (bfminexc) {
15515 /* maxExclusive > BASE minExclusive */
15516 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
15517 if (res == -2)
15518 goto internal_error;
15519 if (res != 1) {
15520 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
15521 }
15522 }
15523 }
15524 if (fminexc) {
15525 /*
15526 * "minExclusive < maxInclusive"
15527 */
15528 if (fmaxinc) {
15529 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
15530 if (res == -2)
15531 goto internal_error;
15532 if (res != -1) {
15533 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
15534 }
15535 }
15536 /*
15537 * "minExclusive valid restriction"
15538 */
15539 if (bfminexc) {
15540 /* minExclusive >= BASE minExclusive */
15541 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
15542 if (res == -2)
15543 goto internal_error;
15544 if (res == -1) {
15545 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
15546 }
15547 if ((res != 0) && (bfminexc->fixed)) {
15548 FACET_RESTR_FIXED_ERR(fminexc)
15549 }
15550 }
15551 if (bfmaxinc) {
15552 /* minExclusive <= BASE maxInclusive */
15553 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
15554 if (res == -2)
15555 goto internal_error;
15556 if (res == 1) {
15557 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
15558 }
15559 }
15560 if (bfmininc) {
15561 /* minExclusive >= BASE minInclusive */
15562 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
15563 if (res == -2)
15564 goto internal_error;
15565 if (res == -1) {
15566 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
15567 }
15568 }
15569 if (bfmaxexc) {
15570 /* minExclusive < BASE maxExclusive */
15571 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
15572 if (res == -2)
15573 goto internal_error;
15574 if (res != -1) {
15575 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
15576 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015577 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015578 }
15579 if (fmininc) {
15580 /*
15581 * "minInclusive < maxExclusive"
15582 */
15583 if (fmaxexc) {
15584 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
15585 if (res == -2)
15586 goto internal_error;
15587 if (res != -1) {
15588 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
15589 }
15590 }
15591 /*
15592 * "minExclusive valid restriction"
15593 */
15594 if (bfmininc) {
15595 /* minInclusive >= BASE minInclusive */
15596 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
15597 if (res == -2)
15598 goto internal_error;
15599 if (res == -1) {
15600 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
15601 }
15602 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015603 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015604 }
15605 }
15606 if (bfmaxinc) {
15607 /* minInclusive <= BASE maxInclusive */
15608 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
15609 if (res == -2)
15610 goto internal_error;
15611 if (res == -1) {
15612 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
15613 }
15614 }
15615 if (bfminexc) {
15616 /* minInclusive > BASE minExclusive */
15617 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
15618 if (res == -2)
15619 goto internal_error;
15620 if (res != 1)
15621 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
15622 }
15623 if (bfmaxexc) {
15624 /* minInclusive < BASE maxExclusive */
15625 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
15626 if (res == -2)
15627 goto internal_error;
15628 if (res != -1)
15629 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
15630 }
15631 }
15632 if (ftotdig && bftotdig) {
15633 /*
15634 * SCC " totalDigits valid restriction"
15635 * totalDigits <= BASE totalDigits
15636 */
15637 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
15638 if (res == -2)
15639 goto internal_error;
15640 if (res == 1)
15641 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
15642 -1, 1, 1);
15643 if ((res != 0) && (bftotdig->fixed)) {
15644 FACET_RESTR_FIXED_ERR(ftotdig)
15645 }
15646 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015647 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015648 /*
15649 * SCC "fractionDigits valid restriction"
15650 * fractionDigits <= BASE fractionDigits
15651 */
15652 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
15653 if (res == -2)
15654 goto internal_error;
15655 if (res == 1)
15656 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
15657 -1, 1, 1);
15658 if ((res != 0) && (bffracdig->fixed)) {
15659 FACET_RESTR_FIXED_ERR(ffracdig)
15660 }
15661 }
15662 /*
15663 * SCC "fractionDigits less than or equal to totalDigits"
15664 */
15665 if (! ftotdig)
15666 ftotdig = bftotdig;
15667 if (! ffracdig)
15668 ffracdig = bffracdig;
15669 if (ftotdig && ffracdig) {
15670 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
15671 if (res == -2)
15672 goto internal_error;
15673 if (res == 1)
15674 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
15675 -1, 1, 0);
15676 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015677 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015678 * *Enumerations* won' be added here, since only the first set
15679 * of enumerations in the ancestor-or-self axis is used
15680 * for validation, plus we need to use the base type of those
15681 * enumerations for whitespace.
15682 *
15683 * *Patterns*: won't be add here, since they are ORed at
15684 * type level and ANDed at ancestor level. This will
15685 * happed during validation by walking the base axis
15686 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015687 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015688 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15689 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015690 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015691 * Special handling of enumerations and patterns.
15692 * TODO: hmm, they should not appear in the set, so remove this.
15693 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015694 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015695 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015696 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015697 /*
15698 * Search for a duplicate facet in the current type.
15699 */
15700 link = type->facetSet;
15701 err = 0;
15702 fixedErr = 0;
15703 while (link != NULL) {
15704 facet = link->facet;
15705 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015706 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015707 case XML_SCHEMA_FACET_WHITESPACE:
15708 /*
15709 * The whitespace must be stronger.
15710 */
15711 if (facet->whitespace < bfacet->whitespace) {
15712 FACET_RESTR_ERR(flength,
15713 "The 'whitespace' value has to be equal to "
15714 "or stronger than the 'whitespace' value of "
15715 "the base type")
15716 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015717 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015718 (facet->whitespace != bfacet->whitespace)) {
15719 FACET_RESTR_FIXED_ERR(facet)
15720 }
15721 break;
15722 default:
15723 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015724 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015725 /* Duplicate found. */
15726 break;
15727 }
15728 link = link->next;
15729 }
15730 /*
15731 * If no duplicate was found: add the base types's facet
15732 * to the set.
15733 */
15734 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015735 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015736 xmlMalloc(sizeof(xmlSchemaFacetLink));
15737 if (link == NULL) {
15738 xmlSchemaPErrMemory(pctxt,
15739 "deriving facets, creating a facet link", NULL);
15740 return (-1);
15741 }
15742 link->facet = cur->facet;
15743 link->next = NULL;
15744 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015745 type->facetSet = link;
15746 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015747 last->next = link;
15748 last = link;
15749 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015750
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015751 }
15752
15753 return (0);
15754internal_error:
15755 xmlSchemaPCustomErr(pctxt,
15756 XML_SCHEMAP_INVALID_FACET_VALUE,
15757 NULL, type, NULL,
15758 "Internal error: xmlSchemaDeriveAndValidateFacets", NULL);
15759 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015760}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015761
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015762static int
15763xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
15764 xmlSchemaTypePtr type)
15765{
15766 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
15767 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015768 * The actual value is then formed by replacing any union type
15769 * definition in the ·explicit members· with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015770 * {member type definitions}, in order.
15771 */
15772 link = type->memberTypes;
15773 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015774
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015775 if (IS_NOT_TYPEFIXED(link->type))
15776 xmlSchemaTypeFixup(link->type, pctxt, NULL);
15777
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015778 if (VARIETY_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015779 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015780 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015781 link->type = subLink->type;
15782 if (subLink->next != NULL) {
15783 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015784 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015785 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015786 while (subLink != NULL) {
15787 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015788 xmlMalloc(sizeof(xmlSchemaTypeLink));
15789 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015790 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015791 NULL);
15792 return (-1);
15793 }
15794 newLink->type = subLink->type;
15795 prevLink->next = newLink;
15796 prevLink = newLink;
15797 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015798
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015799 subLink = subLink->next;
15800 }
15801 }
15802 }
15803 }
15804 link = link->next;
15805 }
15806 return (0);
15807}
15808
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015809static void
15810xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
15811{
15812 int has = 0, needVal = 0, normVal = 0;
15813
15814 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
15815 if (has) {
15816 needVal = (type->baseType->flags &
15817 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
15818 normVal = (type->baseType->flags &
15819 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
15820 }
15821 if (type->facets != NULL) {
15822 xmlSchemaFacetPtr fac;
15823
15824 for (fac = type->facets; fac != NULL; fac = fac->next) {
15825 switch (fac->type) {
15826 case XML_SCHEMA_FACET_WHITESPACE:
15827 break;
15828 case XML_SCHEMA_FACET_PATTERN:
15829 normVal = 1;
15830 has = 1;
15831 break;
15832 case XML_SCHEMA_FACET_ENUMERATION:
15833 needVal = 1;
15834 normVal = 1;
15835 has = 1;
15836 break;
15837 default:
15838 has = 1;
15839 break;
15840 }
15841 }
15842 }
15843 if (normVal)
15844 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
15845 if (needVal)
15846 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15847 if (has)
15848 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
15849
15850 if (has && (! needVal) && VARIETY_ATOMIC(type)) {
15851 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
15852 /*
15853 * OPTIMIZE VAL TODO: Some facets need a computed value.
15854 */
15855 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
15856 (prim->builtInType != XML_SCHEMAS_STRING)) {
15857 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15858 }
15859 }
15860}
15861
15862static int
15863xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
15864{
15865
15866
15867 /*
15868 * Evaluate the whitespace-facet value.
15869 */
15870 if (VARIETY_LIST(type)) {
15871 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15872 return (0);
15873 } else if (VARIETY_UNION(type))
15874 return (0);
15875
15876 if (type->facetSet != NULL) {
15877 xmlSchemaFacetLinkPtr lin;
15878
15879 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
15880 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
15881 switch (lin->facet->whitespace) {
15882 case XML_SCHEMAS_FACET_PRESERVE:
15883 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
15884 break;
15885 case XML_SCHEMAS_FACET_REPLACE:
15886 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
15887 break;
15888 case XML_SCHEMAS_FACET_COLLAPSE:
15889 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15890 break;
15891 default:
15892 return (-1);
15893 }
15894 return (0);
15895 }
15896 }
15897 }
15898 /*
15899 * For all ·atomic· datatypes other than string (and types ·derived·
15900 * by ·restriction· from it) the value of whiteSpace is fixed to
15901 * collapse
15902 */
15903 {
15904 xmlSchemaTypePtr anc;
15905
15906 for (anc = type->baseType; anc != NULL &&
15907 anc->builtInType != XML_SCHEMAS_ANYTYPE;
15908 anc = anc->baseType) {
15909
15910 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
15911 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
15912 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
15913
15914 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
15915 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
15916 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
15917
15918 } else
15919 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15920 break;
15921 }
15922 }
15923 return (0);
15924 }
15925 return (0);
15926}
15927
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015928/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015929 * xmlSchemaTypeFixup:
15930 * @typeDecl: the schema type definition
15931 * @ctxt: the schema parser context
15932 *
15933 * Fixes the content model of the type.
15934 */
15935static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015936xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015937 xmlSchemaParserCtxtPtr pctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000015938{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015939 if (type == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000015940 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015941 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) &&
15942 (type->type != XML_SCHEMA_TYPE_SIMPLE))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000015943 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015944 if (! IS_NOT_TYPEFIXED(type))
15945 return;
15946 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000015947 if (name == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015948 name = type->name;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015949
15950 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015951 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015952 XML_SCHEMAP_INTERNAL,
15953 NULL, type, NULL,
15954 "Internal error: xmlSchemaTypeFixup, "
15955 "baseType is missing on '%s'", type->name);
15956 return;
15957 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015958
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015959 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015960 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015961
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015962 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015963 * Type-fix the base type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015964 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015965 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015966 xmlSchemaTypeFixup(baseType, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015967 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
15968 /*
15969 * Skip fixup if the base type is invalid.
15970 * TODO: Generate a warning!
15971 */
15972 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015973 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015974 /*
15975 * This basically checks if the base type can be derived.
15976 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015977 if (xmlSchemaCheckSRCCT(pctxt, type) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015978 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
15979 return;
15980 }
15981 /*
15982 * Fixup the content type.
15983 */
15984 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
15985 /*
15986 * Corresponds to <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015987 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015988 if ((IS_COMPLEX_TYPE(baseType)) &&
15989 (baseType->contentTypeDef != NULL) &&
15990 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015991 xmlSchemaTypePtr contentBase, content;
15992 char buf[30];
15993 const xmlChar *tmpname;
15994 /*
15995 * SPEC (1) If <restriction> + base type is <complexType>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015996 * "whose own {content type} is a simple type..."
Daniel Veillard01fa6152004-06-29 17:04:39 +000015997 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015998 if (type->contentTypeDef != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015999 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016000 * SPEC (1.1) "the simple type definition corresponding to the
16001 * <simpleType> among the [children] of <restriction> if there
16002 * is one;"
16003 * Note that this "<simpleType> among the [children]" was put
16004 * into ->contentTypeDef during parsing.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016005 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016006 contentBase = type->contentTypeDef;
16007 type->contentTypeDef = NULL;
16008 } else {
16009 /*
16010 * (1.2) "...otherwise (<restriction> has no <simpleType>
16011 * among its [children]), the simple type definition which
16012 * is the {content type} of the ... base type."
16013 */
16014 contentBase = baseType->contentTypeDef;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016015 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016016 /*
16017 * SPEC
16018 * "... a simple type definition which restricts the simple
16019 * type definition identified in clause 1.1 or clause 1.2
16020 * with a set of facet components"
16021 *
16022 * Create the anonymous simple type, which will be the content
16023 * type of the complex type.
16024 */
16025 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
16026 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
16027 content = xmlSchemaAddType(pctxt,
16028 pctxt->schema, tmpname, tmpname, type->node);
16029 if (content == NULL)
16030 return;
16031 /*
16032 * We will use the same node as for the <complexType>
16033 * to have it somehow anchored in the schema doc.
16034 */
16035 content->node = type->node;
16036 content->type = XML_SCHEMA_TYPE_SIMPLE;
16037 content->contentType = XML_SCHEMA_CONTENT_SIMPLE;
16038 content->baseType = contentBase;
16039 /*
16040 * Move the facets, previously anchored on the complexType.
16041 */
16042 content->facets = type->facets;
16043 type->facets = NULL;
16044 content->facetSet = type->facetSet;
16045 type->facetSet = NULL;
16046
16047 type->contentTypeDef = content;
16048 if (IS_NOT_TYPEFIXED(contentBase))
16049 xmlSchemaTypeFixup(contentBase, pctxt, NULL);
16050 xmlSchemaTypeFixup(content, pctxt, NULL);
16051
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016052 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16053 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16054 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
16055 /*
16056 * SPEC (2) If <restriction> + base is a mixed <complexType> with
16057 * an emptiable particle, then a simple type definition which
16058 * restricts the <restriction>'s <simpleType> child.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016059 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016060 if ((type->contentTypeDef == NULL) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016061 (type->contentTypeDef->baseType == NULL)) {
16062 /*
16063 * TODO: Check if this ever happens.
16064 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016065 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016066 XML_SCHEMAP_INTERNAL,
16067 NULL, type, NULL,
16068 "Internal error: xmlSchemaTypeFixup, "
16069 "complex type '%s': the <simpleContent><restriction> "
16070 "is missing a <simpleType> child, but was not catched "
16071 "by xmlSchemaCheckSRCCT()", type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016072 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016073 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16074 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16075 /*
16076 * SPEC (3) If <extension> + base is <complexType> with
16077 * <simpleType> content, "...then the {content type} of that
16078 * complex type definition"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016079 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016080 if (baseType->contentTypeDef == NULL) {
16081 /*
16082 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
16083 * should have catched this already.
16084 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016085 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016086 XML_SCHEMAP_INTERNAL,
16087 NULL, type, NULL,
16088 "Internal error: xmlSchemaTypeFixup, "
16089 "complex type '%s': the <extension>ed base type is "
16090 "a complex type with no simple content type",
16091 type->name);
16092 }
16093 type->contentTypeDef = baseType->contentTypeDef;
16094 } else if ((IS_SIMPLE_TYPE(baseType)) &&
16095 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16096 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016097 * SPEC (4) <extension> + base is <simpleType>
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016098 * "... then that simple type definition"
16099 */
16100 type->contentTypeDef = baseType;
16101 } else {
16102 /*
16103 * TODO: Check if this ever happens.
16104 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016105 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016106 XML_SCHEMAP_INTERNAL,
16107 NULL, type, NULL,
16108 "Internal error: xmlSchemaTypeFixup, "
16109 "complex type '%s' with <simpleContent>: unhandled "
16110 "derivation case", type->name);
16111 }
16112 } else {
16113 int dummySequence = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016114 xmlSchemaParticlePtr particle =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016115 (xmlSchemaParticlePtr) type->subtypes;
16116 /*
16117 * Corresponds to <complexType><complexContent>...
16118 *
16119 * NOTE that the effective mixed was already set during parsing of
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016120 * <complexType> and <complexContent>; its flag value is
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016121 * XML_SCHEMAS_TYPE_MIXED.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016122 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016123 * Compute the "effective content":
16124 * (2.1.1) + (2.1.2) + (2.1.3)
16125 */
16126 if ((particle == NULL) ||
16127 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
16128 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
16129 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
16130 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
16131 (particle->minOccurs == 0))) &&
16132 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016133 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016134 /*
16135 * SPEC (2.1.4) "If the ·effective mixed· is true, then
16136 * a particle whose properties are as follows:..."
16137 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016138 * Empty sequence model group with
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016139 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
16140 * NOTE that we sill assign it the <complexType> node to
16141 * somehow anchor it in the doc.
16142 */
16143 if ((particle == NULL) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016144 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016145 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016146 * Create the particle.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016147 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016148 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016149 type->node, 1, 1);
16150 if (particle == NULL)
16151 return;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016152 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016153 * Create the model group.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016154 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016155 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016156 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016157 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16158 if (particle->children == NULL)
16159 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016160
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016161 type->subtypes = (xmlSchemaTypePtr) particle;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016162 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016163 dummySequence = 1;
16164 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16165 } else {
16166 /*
16167 * SPEC (2.1.5) "otherwise empty"
16168 */
16169 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016170 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016171 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016172 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016173 * SPEC (2.2) "otherwise the particle corresponding to the
16174 * <all>, <choice>, <group> or <sequence> among the
16175 * [children]."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016176 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016177 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16178 }
16179 /*
16180 * Compute the "content type".
16181 */
16182 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016183 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016184 * SPEC (3.1) "If <restriction>..."
16185 * (3.1.1) + (3.1.2) */
16186 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
16187 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16188 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16189 }
16190 } else {
16191 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016192 * SPEC (3.2) "If <extension>..."
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016193 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016194 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16195 /*
16196 * SPEC (3.2.1)
16197 */
16198 type->contentType = baseType->contentType;
16199 type->subtypes = baseType->subtypes;
16200 /*
16201 * NOTE that the effective mixed is ignored here.
16202 */
16203 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16204 /*
16205 * SPEC (3.2.2)
16206 */
16207 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16208 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16209 } else {
16210 /*
16211 * SPEC (3.2.3)
16212 */
16213 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16214 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16215 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016216 * "A model group whose {compositor} is sequence and whose
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016217 * {particles} are..."
16218 */
16219 if (! dummySequence) {
16220 xmlSchemaTreeItemPtr effectiveContent =
16221 (xmlSchemaTreeItemPtr) type->subtypes;
16222 /*
16223 * Create the particle.
16224 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016225 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016226 type->node, 1, 1);
16227 if (particle == NULL)
16228 return;
16229 /*
16230 * Create the "sequence" model group.
16231 */
16232 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016233 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016234 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16235 if (particle->children == NULL)
16236 return;
16237 type->subtypes = (xmlSchemaTypePtr) particle;
16238 /*
16239 * SPEC "the particle of the {content type} of
16240 * the ... base ..."
16241 * Create a duplicate of the base type's particle
16242 * and assign its "term" to it.
16243 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016244 particle->children->children =
16245 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
16246 pctxt->schema, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016247 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016248 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016249 if (particle->children->children == NULL)
16250 return;
16251 particle = (xmlSchemaParticlePtr)
16252 particle->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016253 particle->children =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016254 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
16255 /*
16256 * SPEC "followed by the ·effective content·."
16257 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016258 particle->next = effectiveContent;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016259 } else {
16260 /*
16261 * This is the case when there is already an empty
16262 * <sequence> with minOccurs==maxOccurs==1.
16263 * Just add the base types's content type.
16264 * NOTE that, although we miss to add an intermediate
16265 * <sequence>, this should produce no difference to
16266 * neither the regex compilation of the content model,
16267 * nor to the complex type contraints.
16268 */
16269 particle->children->children =
16270 (xmlSchemaTreeItemPtr) baseType->subtypes;
16271 }
16272 }
16273 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016274 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016275 /*
16276 * Apply the complex type component constraints; this will not
16277 * check attributes, since this is done in
16278 * xmlSchemaBuildAttributeValidation().
16279 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016280 if (xmlSchemaCheckCTComponent(pctxt, type) != 0)
16281 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016282 /*
16283 * Inherit & check constraints for attributes.
16284 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016285 xmlSchemaBuildAttributeValidation(pctxt, type);
16286 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016287 /*
16288 * Simple Type Definition Schema Component
16289 */
16290 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016291 if (VARIETY_LIST(type)) {
16292 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016293 * Corresponds to <simpleType><list>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016294 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016295 if (type->subtypes == NULL) {
16296 /*
16297 * This one is really needed, so get out.
16298 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016299 PERROR_INT("xmlSchemaTypeFixup",
16300 "list type has no item-type assigned");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016301 return;
16302 }
16303 if (IS_NOT_TYPEFIXED(type->subtypes))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016304 xmlSchemaTypeFixup(type->subtypes, pctxt, NULL);
16305 } else if (VARIETY_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016306 /*
16307 * Corresponds to <simpleType><union>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016308 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016309 if (type->memberTypes == NULL) {
16310 /*
16311 * This one is really needed, so get out.
16312 */
16313 return;
16314 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016315 if (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016316 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016317 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016318 xmlSchemaTypePtr baseType = type->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016319 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016320 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016321 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016322 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016323 xmlSchemaTypeFixup(baseType, pctxt, NULL);
16324 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016325 * Variety
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016326 * If the <restriction> alternative is chosen, then the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016327 * {variety} of the {base type definition}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016328 */
16329 if (VARIETY_ATOMIC(baseType))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016330 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016331 else if (VARIETY_LIST(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016332 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
16333 /*
16334 * Inherit the itemType.
16335 */
16336 type->subtypes = baseType->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016337 } else if (VARIETY_UNION(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016338 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
16339 /*
16340 * NOTE that we won't assign the memberTypes of the base,
16341 * since this will make trouble when freeing them; we will
16342 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016343 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016344 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016345 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016346 /*
16347 * Check constraints.
16348 *
16349 * TODO: Split this somehow, we need to know first if we can derive
16350 * from the base type at all!
16351 */
16352 if (type->baseType != NULL) {
16353 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016354 * Schema Component Constraint: Simple Type Restriction
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016355 * (Facets)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016356 * NOTE: Satisfaction of 1 and 2 arise from the fixup
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016357 * applied beforehand.
16358 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016359 xmlSchemaCheckSRCSimpleType(pctxt, type);
16360 xmlSchemaCheckFacetValues(type, pctxt);
16361 if ((type->facetSet != NULL) ||
16362 (type->baseType->facetSet != NULL))
16363 xmlSchemaDeriveAndValidateFacets(pctxt, type);
16364 /*
16365 * Whitespace value.
16366 */
16367 xmlSchemaTypeFixupWhitespace(type);
16368 xmlSchemaTypeFixupOptimFacets(type);
16369 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016370 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016371
Daniel Veillard8651f532002-04-17 09:06:27 +000016372#ifdef DEBUG_TYPE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016373 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016374 xmlGenericError(xmlGenericErrorContext,
16375 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016376 type->node->doc->URL,
16377 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016378 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016379 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016380 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016381 if ((IS_SIMPLE_TYPE(type)) || (IS_COMPLEX_TYPE(type))) {
16382 switch (type->contentType) {
16383 case XML_SCHEMA_CONTENT_SIMPLE:
16384 xmlGenericError(xmlGenericErrorContext, "simple\n");
16385 break;
16386 case XML_SCHEMA_CONTENT_ELEMENTS:
16387 xmlGenericError(xmlGenericErrorContext, "elements\n");
16388 break;
16389 case XML_SCHEMA_CONTENT_UNKNOWN:
16390 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
16391 break;
16392 case XML_SCHEMA_CONTENT_EMPTY:
16393 xmlGenericError(xmlGenericErrorContext, "empty\n");
16394 break;
16395 case XML_SCHEMA_CONTENT_MIXED:
16396 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016397 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016398 xmlGenericError(xmlGenericErrorContext,
16399 "mixed as emptiable particle\n");
16400 else
16401 xmlGenericError(xmlGenericErrorContext, "mixed\n");
16402 break;
16403 /* Removed, since not used. */
16404 /*
16405 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
16406 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
16407 break;
16408 */
16409 case XML_SCHEMA_CONTENT_BASIC:
16410 xmlGenericError(xmlGenericErrorContext, "basic\n");
16411 break;
16412 default:
16413 xmlGenericError(xmlGenericErrorContext,
16414 "not registered !!!\n");
16415 break;
16416 }
Daniel Veillard8651f532002-04-17 09:06:27 +000016417 }
16418#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016419}
16420
16421/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016422 * xmlSchemaCheckFacet:
16423 * @facet: the facet
16424 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000016425 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016426 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016427 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016428 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016429 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016430 * Returns 0 if valid, a positive error code if not valid and
16431 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016432 */
16433int
16434xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016435 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016436 xmlSchemaParserCtxtPtr pctxt,
16437 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016438{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016439 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016440
Daniel Veillardce682bc2004-11-05 17:22:25 +000016441 if ((facet == NULL) || (typeDecl == NULL))
16442 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016443 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016444 * TODO: will the parser context be given if used from
16445 * the relaxNG module?
16446 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016447 if (pctxt == NULL)
16448 ctxtGiven = 0;
16449 else
16450 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016451
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016452 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016453 case XML_SCHEMA_FACET_MININCLUSIVE:
16454 case XML_SCHEMA_FACET_MINEXCLUSIVE:
16455 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016456 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
16457 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016458 /*
16459 * Okay we need to validate the value
16460 * at that point.
16461 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016462 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016463
16464 /* 4.3.5.5 Constraints on enumeration Schema Components
16465 * Schema Component Constraint: enumeration valid restriction
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016466 * It is an ·error· if any member of {value} is not in the
16467 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016468 *
16469 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016470 * The value ·must· be in the
16471 * ·value space· of the ·base type·.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016472 */
16473 /*
16474 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016475 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016476 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016477 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016478 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016479 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016480 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016481 */
16482 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
16483 base = typeDecl->baseType;
16484 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016485 PERROR_INT("xmlSchemaCheckFacet",
16486 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016487 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016488 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016489 } else
16490 base = typeDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016491
16492 if (! ctxtGiven) {
16493 /*
16494 * A context is needed if called from RelaxNG.
16495 */
16496 pctxt = xmlSchemaNewParserCtxt("*");
16497 if (pctxt == NULL)
16498 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016499 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016500 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016501 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016502 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016503 * facet->node is just the node holding the facet
16504 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016505 * of the facet.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016506 */
16507 ret = xmlSchemaVCheckCVCSimpleType(
16508 (xmlSchemaAbstractCtxtPtr) pctxt, facet->node, base,
16509 facet->value, &(facet->val), 1, 1, 0);
16510 if (ret != 0) {
16511 if (ret < 0) {
16512 /* No error message for RelaxNG. */
16513 if (ctxtGiven) {
16514 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16515 XML_SCHEMAP_INTERNAL, facet->node, NULL,
16516 "Internal error: xmlSchemaCheckFacet, "
16517 "failed to validate the value '%s' of the "
16518 "facet '%s' against the base type",
16519 facet->value, xmlSchemaFacetTypeToString(facet->type));
16520 }
16521 goto internal_error;
16522 }
16523 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16524 /* No error message for RelaxNG. */
16525 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016526 xmlChar *str = NULL;
16527
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016528 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16529 ret, facet->node, (xmlSchemaTypePtr) facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016530 "The value '%s' of the facet does not validate "
16531 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016532 facet->value,
16533 xmlSchemaFormatQName(&str,
16534 base->targetNamespace, base->name));
16535 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016536 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016537 goto exit;
16538 } else if (facet->val == NULL) {
16539 if (ctxtGiven) {
16540 PERROR_INT("xmlSchemaCheckFacet",
16541 "value was not computed");
16542 }
16543 TODO
16544 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016545 break;
16546 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016547 case XML_SCHEMA_FACET_PATTERN:
16548 facet->regexp = xmlRegexpCompile(facet->value);
16549 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016550 ret = XML_SCHEMAP_REGEXP_INVALID;
16551 /* No error message for RelaxNG. */
16552 if (ctxtGiven) {
16553 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16554 ret, facet->node, typeDecl,
16555 "The value '%s' of the facet 'pattern' is not a "
16556 "valid regular expression",
16557 facet->value, NULL);
16558 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016559 }
16560 break;
16561 case XML_SCHEMA_FACET_TOTALDIGITS:
16562 case XML_SCHEMA_FACET_FRACTIONDIGITS:
16563 case XML_SCHEMA_FACET_LENGTH:
16564 case XML_SCHEMA_FACET_MAXLENGTH:
16565 case XML_SCHEMA_FACET_MINLENGTH:{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016566 ret = xmlSchemaValidatePredefinedType(
16567 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
16568 facet->value, &(facet->val));
16569 if (ret != 0) {
16570 if (ret < 0) {
16571 /* No error message for RelaxNG. */
16572 if (ctxtGiven) {
16573 PERROR_INT("xmlSchemaCheckFacet",
16574 "validating facet value");
16575 }
16576 goto internal_error;
16577 }
16578 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16579 /* No error message for RelaxNG. */
16580 if (ctxtGiven) {
16581 /* error code */
16582 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16583 ret, facet->node, typeDecl,
16584 "The value '%s' of the facet '%s' is not a valid "
16585 "'nonNegativeInteger'",
16586 facet->value,
16587 xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016588 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016589 }
16590 break;
16591 }
16592 case XML_SCHEMA_FACET_WHITESPACE:{
16593 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
16594 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
16595 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
16596 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
16597 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
16598 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
16599 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016600 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16601 /* No error message for RelaxNG. */
16602 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016603 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016604 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16605 ret, facet->node, typeDecl,
16606 "The value '%s' of the facet 'whitespace' is not "
16607 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016608 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016609 }
16610 }
16611 default:
16612 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016613 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016614exit:
16615 if ((! ctxtGiven) && (pctxt != NULL))
16616 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016617 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016618internal_error:
16619 if ((! ctxtGiven) && (pctxt != NULL))
16620 xmlSchemaFreeParserCtxt(pctxt);
16621 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016622}
16623
16624/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016625 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000016626 * @typeDecl: the schema type definition
16627 * @ctxt: the schema parser context
16628 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016629 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000016630 */
16631static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016632xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
16633 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000016634{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016635 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016636 /*
16637 * NOTE: It is intended to use the facets list, instead
16638 * of facetSet.
16639 */
16640 if (typeDecl->facets != NULL) {
16641 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016642
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016643 /*
16644 * Temporarily assign the "schema" to the validation context
16645 * of the parser context. This is needed for NOTATION validation.
16646 */
16647 if (ctxt->vctxt == NULL) {
16648 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
16649 return;
16650 }
16651 ctxt->vctxt->schema = ctxt->schema;
16652
Daniel Veillard01fa6152004-06-29 17:04:39 +000016653 while (facet != NULL) {
16654 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
16655 facet = facet->next;
16656 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016657
16658 ctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016659 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016660}
16661
16662/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016663 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016664 * @ctxtMGroup: the searched model group
16665 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016666 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016667 *
16668 * This one is intended to be used by
16669 * xmlSchemaCheckGroupDefCircular only.
16670 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016671 * Returns the particle with the circular model group definition reference,
16672 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016673 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016674static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016675xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016676 xmlSchemaTreeItemPtr particle)
16677{
16678 xmlSchemaTreeItemPtr circ = NULL;
16679 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016680 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016681
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016682 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016683 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016684 if (term == NULL)
16685 continue;
16686 switch (term->type) {
16687 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016688 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016689 if (gdef == groupDef)
16690 return (particle);
16691 /*
16692 * Mark this model group definition to avoid infinite
16693 * recursion on circular references not yet examined.
16694 */
16695 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
16696 continue;
16697 if (gdef->children != NULL) {
16698 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16699 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
16700 gdef->children->children);
16701 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16702 if (circ != NULL)
16703 return (circ);
16704 }
16705 break;
16706 case XML_SCHEMA_TYPE_SEQUENCE:
16707 case XML_SCHEMA_TYPE_CHOICE:
16708 case XML_SCHEMA_TYPE_ALL:
16709 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
16710 if (circ != NULL)
16711 return (circ);
16712 break;
16713 default:
16714 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016715 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016716 }
16717 return (NULL);
16718}
16719
16720/**
16721 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016722 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016723 * @ctxt: the parser context
16724 * @name: the name
16725 *
16726 * Checks for circular references to model group definitions.
16727 */
16728static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016729xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016730 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016731 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016732{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016733 /*
16734 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016735 * 2 Circular groups are disallowed. That is, within the {particles}
16736 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016737 * is the group itself.
16738 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016739 if ((item == NULL) ||
16740 (item->type != XML_SCHEMA_TYPE_GROUP) ||
16741 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016742 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016743 {
16744 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016745
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016746 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016747 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016748 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016749 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016750 * TODO: The error report is not adequate: this constraint
16751 * is defined for model groups but not definitions, but since
16752 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016753 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016754 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016755 */
16756 xmlSchemaPCustomErr(ctxt,
16757 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016758 NULL, NULL, GET_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016759 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016760 "defined", xmlSchemaFormatQName(&str,
16761 item->targetNamespace, item->name));
16762 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016763 /*
16764 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016765 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016766 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016767 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016768 }
16769 }
16770}
16771
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016772/**
16773 * xmlSchemaGroupDefTermFixup:
16774 * @item: the particle with a model group definition as term
16775 * @ctxt: the parser context
16776 * @name: the name
16777 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016778 * Checks cos-all-limited.
16779 *
16780 * Assigns the model group of model group definitions to the "term"
16781 * of the referencing particle.
16782 * In xmlSchemaMiscRefFixup the model group definitions was assigned
16783 * to the "term", since needed for the circularity check.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016784 */
16785static void
16786xmlSchemaGroupDefTermFixup(xmlSchemaParticlePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016787 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016788 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016789{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016790 if ((item == NULL) ||
16791 (item->type != XML_SCHEMA_TYPE_PARTICLE) ||
16792 (item->children == NULL) ||
16793 (item->children->type != XML_SCHEMA_TYPE_GROUP) ||
16794 (item->children->children == NULL))
16795 return;
16796 item->children = item->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016797 /*
16798 * TODO: Not nice, but we will anchor cos-all-limited here.
16799 */
16800 if ((item->children->type == XML_SCHEMA_TYPE_ALL) &&
16801 (item->maxOccurs != 1)) {
16802 /*
16803 * SPEC (1.2) "the {term} property of a particle with
16804 * {max occurs}=1which is part of a pair which constitutes the
16805 * {content type} of a complex type definition."
16806 */
16807 xmlSchemaPCustomErr(ctxt,
16808 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16809 NULL, (xmlSchemaTypePtr) item, item->node,
16810 "The particle's 'maxOccurs' must be 1, since an xs:all model "
16811 "group is its term", NULL);
16812 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016813}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016814
16815/**
16816 * xmlSchemaGetCircAttrGrRef:
16817 * @ctxtGr: the searched attribute group
16818 * @attr: the current attribute list to be processed
16819 *
16820 * This one is intended to be used by
16821 * xmlSchemaCheckSRCAttributeGroupCircular only.
16822 *
16823 * Returns the circular attribute grou reference, otherwise NULL.
16824 */
16825static xmlSchemaAttributeGroupPtr
16826xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
16827 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016828{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016829 xmlSchemaAttributeGroupPtr circ = NULL, gr;
16830 int marked;
16831 /*
16832 * We will search for an attribute group reference which
16833 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016834 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016835 while (attr != NULL) {
16836 marked = 0;
16837 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
16838 gr = (xmlSchemaAttributeGroupPtr) attr;
16839 if (gr->refItem != NULL) {
16840 if (gr->refItem == ctxtGr)
16841 return (gr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016842 else if (gr->refItem->flags &
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016843 XML_SCHEMAS_ATTRGROUP_MARKED) {
16844 attr = attr->next;
16845 continue;
16846 } else {
16847 /*
16848 * Mark as visited to avoid infinite recursion on
16849 * circular references not yet examined.
16850 */
16851 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
16852 marked = 1;
16853 }
16854 }
16855 if (gr->attributes != NULL)
16856 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
16857 /*
16858 * Unmark the visited group's attributes.
16859 */
16860 if (marked)
16861 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
16862 if (circ != NULL)
16863 return (circ);
16864 }
16865 attr = attr->next;
16866 }
16867 return (NULL);
16868}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016869
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016870/**
16871 * xmlSchemaCheckSRCAttributeGroupCircular:
16872 * attrGr: the attribute group definition
16873 * @ctxt: the parser context
16874 * @name: the name
16875 *
16876 * Checks for circular references of attribute groups.
16877 */
16878static void
16879xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016880 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016881 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016882{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016883 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016884 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016885 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016886 * 3 Circular group reference is disallowed outside <redefine>.
16887 * That is, unless this element information item's parent is
16888 * <redefine>, then among the [children], if any, there must
16889 * not be an <attributeGroup> with ref [attribute] which resolves
16890 * to the component corresponding to this <attributeGroup>. Indirect
16891 * circularity is also ruled out. That is, when QName resolution
16892 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
16893 * any <attributeGroup>s with a ref [attribute] among the [children],
16894 * it must not be the case that a ·QName· is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016895 * which resolves to the component corresponding to this <attributeGroup>.
16896 */
16897 /*
16898 * Only global components can be referenced.
16899 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016900 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016901 (attrGr->attributes == NULL))
16902 return;
16903 else {
16904 xmlSchemaAttributeGroupPtr circ;
16905
16906 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
16907 if (circ != NULL) {
16908 /*
16909 * TODO: Report the referenced attr group as QName.
16910 */
16911 xmlSchemaPCustomErr(ctxt,
16912 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16913 NULL, NULL, circ->node,
16914 "Circular reference to the attribute group '%s' "
16915 "defined", attrGr->name);
16916 /*
16917 * NOTE: We will cut the reference to avoid further
16918 * confusion of the processor.
16919 * BADSPEC: The spec should define how to process in this case.
16920 */
16921 circ->attributes = NULL;
16922 circ->refItem = NULL;
16923 }
16924 }
16925}
16926
16927/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000016928 * xmlSchemaAttrGrpFixup:
16929 * @attrgrpDecl: the schema attribute definition
16930 * @ctxt: the schema parser context
16931 * @name: the attribute name
16932 *
16933 * Fixes finish doing the computations on the attributes definitions
16934 */
16935static void
Daniel Veillard3646d642004-06-02 19:19:14 +000016936xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016937 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000016938{
16939 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000016940 name = attrgrp->name;
16941 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016942 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000016943 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016944 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000016945
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016946 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016947 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016948 if (ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016949 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016950 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016951 (xmlSchemaTypePtr) attrgrp, attrgrp->node,
16952 "ref", attrgrp->ref, attrgrp->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016953 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016954 return;
16955 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016956 attrgrp->refItem = ref;
16957 /*
16958 * Check for self reference!
16959 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016960 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000016961 attrgrp->attributes = ref->attributes;
16962 attrgrp->attributeWildcard = ref->attributeWildcard;
16963 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000016964}
16965
16966/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016967 * xmlSchemaAttrCheckValConstr:
16968 * @item: an schema attribute declaration/use
16969 * @ctxt: a schema parser context
16970 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016971 *
16972 *
16973 * Schema Component Constraint: Attribute Declaration Properties Correct
16974 * (a-props-correct)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016975 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000016976 *
16977 * Fixes finish doing the computations on the attributes definitions
16978 */
16979static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016980xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016981 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016982 const xmlChar * name ATTRIBUTE_UNUSED)
16983{
16984
16985 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016986 * 2 if there is a {value constraint}, the canonical lexical
16987 * representation of its value must be ·valid· with respect
16988 * to the {type definition} as defined in String Valid (§3.14.4).
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016989 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016990 if (item->defValue != NULL) {
16991 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016992
16993 if (item->subtypes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016994 PERROR_INT("xmlSchemaCheckAttrValConstr",
16995 "type is missing");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016996 return;
16997 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016998 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt,
16999 item->node, item->subtypes, item->defValue, &(item->defVal),
17000 1, 1, 0);
17001 if (ret != 0) {
17002 if (ret < 0) {
17003 PERROR_INT("xmlSchemaAttrCheckValConstr",
17004 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017005 return;
17006 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017007 ret = XML_SCHEMAP_A_PROPS_CORRECT_2;
17008 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
17009 ret, item->node, (xmlSchemaTypePtr) item,
17010 "The value of the value constraint is not valid", NULL, NULL);
17011 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017012 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017013 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017014}
17015
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017016static xmlSchemaElementPtr
17017xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
17018 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017019{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017020 xmlSchemaElementPtr ret;
17021
17022 if (SUBST_GROUP_AFF(ancestor) == NULL)
17023 return (NULL);
17024 if (SUBST_GROUP_AFF(ancestor) == elemDecl)
17025 return (ancestor);
17026
17027 if (SUBST_GROUP_AFF(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
17028 return (NULL);
17029 SUBST_GROUP_AFF(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
17030 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
17031 SUBST_GROUP_AFF(ancestor));
17032 SUBST_GROUP_AFF(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
17033
17034 return (ret);
17035}
17036
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017037/**
17038 * xmlSchemaCheckElemPropsCorrect:
17039 * @ctxt: a schema parser context
17040 * @decl: the element declaration
17041 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017042 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017043 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017044 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017045 *
17046 * STATUS:
17047 * missing: (6)
17048 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017049static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017050xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
17051 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017052{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017053 int ret = 0;
17054 xmlSchemaTypePtr typeDef = ELEM_TYPE(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017055 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017056 * SPEC (1) "The values of the properties of an element declaration
17057 * must be as described in the property tableau in The Element
17058 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
17059 * Sub-components (§5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017060 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017061 if (SUBST_GROUP_AFF(elemDecl) != NULL) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017062 xmlSchemaElementPtr head = SUBST_GROUP_AFF(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017063
17064 xmlSchemaCheckElementDeclComponent(head, pctxt, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017065 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017066 * SPEC (3) "If there is a non-·absent· {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017067 * affiliation}, then {scope} must be global."
17068 */
17069 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
17070 xmlSchemaPCustomErr(pctxt,
17071 XML_SCHEMAP_E_PROPS_CORRECT_3,
17072 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17073 "Only global element declarations can have a "
17074 "substitution group affiliation", NULL);
17075 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017076 }
17077 /*
17078 * TODO: SPEC (6) "Circular substitution groups are disallowed.
17079 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017080 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017081 * property."
17082 */
17083 if (head == elemDecl)
17084 circ = head;
17085 else if (SUBST_GROUP_AFF(head) != NULL)
17086 circ = xmlSchemaCheckSubstGroupCircular(head, head);
17087 else
17088 circ = NULL;
17089 if (circ != NULL) {
17090 xmlChar *strA = NULL, *strB = NULL;
17091
17092 xmlSchemaPCustomErrExt(pctxt,
17093 XML_SCHEMAP_E_PROPS_CORRECT_6,
17094 NULL, (xmlSchemaTypePtr) circ, circ->node,
17095 "The element declaration '%s' defines a circular "
17096 "substitution group to element declaration '%s'",
17097 xmlSchemaGetComponentQName(&strA, circ),
17098 xmlSchemaGetComponentQName(&strB, head),
17099 NULL);
17100 FREE_AND_NULL(strA)
17101 FREE_AND_NULL(strB)
17102 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
17103 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017104 /*
17105 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017106 * the {type definition}
17107 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017108 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017109 * of the {substitution group exclusions} of the {substitution group
17110 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
17111 * (if the {type definition} is complex) or as defined in
17112 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017113 * simple)."
17114 *
17115 * NOTE: {substitution group exclusions} means the values of the
17116 * attribute "final".
17117 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017118
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017119 if (typeDef != ELEM_TYPE(SUBST_GROUP_AFF(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017120 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017121
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017122 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
17123 set |= SUBSET_EXTENSION;
17124 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
17125 set |= SUBSET_RESTRICTION;
17126
17127 if (xmlSchemaCheckCOSDerivedOK(typeDef,
17128 ELEM_TYPE(head), set) != 0) {
17129 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
17130
17131 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017132 xmlSchemaPCustomErrExt(pctxt,
17133 XML_SCHEMAP_E_PROPS_CORRECT_4,
17134 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017135 "The type definition '%s' was "
17136 "either rejected by the substitution group "
17137 "affiliation '%s', or not validly derived from its type "
17138 "definition '%s'",
17139 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017140 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017141 xmlSchemaGetComponentQName(&strC, ELEM_TYPE(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017142 FREE_AND_NULL(strA)
17143 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017144 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017145 }
17146 }
17147 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017148 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017149 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017150 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017151 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017152 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017153 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017154 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017155 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017156 ((IS_SIMPLE_TYPE(typeDef) &&
17157 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017158 (IS_COMPLEX_TYPE(typeDef) &&
17159 HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017160 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
17161 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017162
17163 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
17164 xmlSchemaPCustomErr(pctxt,
17165 XML_SCHEMAP_E_PROPS_CORRECT_5,
17166 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17167 "The type definition (or type definition's content type) is or "
17168 "is derived from ID; value constraints are not allowed in "
17169 "conjunction with such a type definition", NULL);
17170 } else if (elemDecl->value != NULL) {
17171 int vcret;
17172 xmlNodePtr node = NULL;
17173
17174 /*
17175 * SPEC (2) "If there is a {value constraint}, the canonical lexical
17176 * representation of its value must be ·valid· with respect to the
17177 * {type definition} as defined in Element Default Valid (Immediate)
17178 * (§3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017179 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017180 if (typeDef == NULL) {
17181 xmlSchemaPErr(pctxt, elemDecl->node,
17182 XML_SCHEMAP_INTERNAL,
17183 "Internal error: xmlSchemaCheckElemPropsCorrect, "
17184 "type is missing... skipping validation of "
17185 "the value constraint", NULL, NULL);
17186 return (-1);
17187 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017188 if (elemDecl->node != NULL) {
17189 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
17190 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17191 BAD_CAST "fixed");
17192 else
17193 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17194 BAD_CAST "default");
17195 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017196 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
17197 typeDef, elemDecl->value, &(elemDecl->defVal));
17198 if (vcret != 0) {
17199 if (vcret < 0) {
17200 PERROR_INT("xmlSchemaElemCheckValConstr",
17201 "failed to validate the value constraint of an "
17202 "element declaration");
17203 return (-1);
17204 }
17205 return (vcret);
17206 }
17207 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017208
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017209 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017210}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017211
17212/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017213 * xmlSchemaCheckElemSubstGroup:
17214 * @ctxt: a schema parser context
17215 * @decl: the element declaration
17216 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017217 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017218 * Schema Component Constraint:
17219 * Substitution Group (cos-equiv-class)
17220 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017221 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017222 * a list will be built for each subst. group head, holding all direct
17223 * referents to this head.
17224 * NOTE that this function needs:
17225 * 1. circular subst. groups to be checked beforehand
17226 * 2. the declaration's type to be derived from the head's type
17227 *
17228 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017229 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017230 */
17231static void
17232xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
17233 xmlSchemaElementPtr elemDecl)
17234{
17235 if ((SUBST_GROUP_AFF(elemDecl) == NULL) ||
17236 /* SPEC (1) "Its {abstract} is false." */
17237 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
17238 return;
17239 {
17240 xmlSchemaElementPtr head;
17241 xmlSchemaTypePtr headType, type;
17242 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017243 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017244 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
17245 * {disallowed substitutions} as the blocking constraint, as defined in
17246 * Substitution Group OK (Transitive) (§3.3.6)."
17247 */
17248 for (head = SUBST_GROUP_AFF(elemDecl); head != NULL;
17249 head = SUBST_GROUP_AFF(head)) {
17250 set = 0;
17251 methSet = 0;
17252 /*
17253 * The blocking constraints.
17254 */
17255 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
17256 continue;
17257 headType = head->subtypes;
17258 type = elemDecl->subtypes;
17259 if (headType == type)
17260 goto add_member;
17261 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
17262 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17263 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
17264 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17265 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017266 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017267 * "The set of all {derivation method}s involved in the
17268 * derivation of D's {type definition} from C's {type definition}
17269 * does not intersect with the union of the blocking constraint,
17270 * C's {prohibited substitutions} (if C is complex, otherwise the
17271 * empty set) and the {prohibited substitutions} (respectively the
17272 * empty set) of any intermediate {type definition}s in the
17273 * derivation of D's {type definition} from C's {type definition}."
17274 */
17275 /*
17276 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
17277 * subst.head axis, the methSet does not need to be computed for
17278 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017279 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017280 /*
17281 * The set of all {derivation method}s involved in the derivation
17282 */
17283 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017284 if ((type->flags &
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017285 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
17286 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17287 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017288
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017289 if ((type->flags &
17290 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) &&
17291 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17292 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17293
17294 type = type->baseType;
17295 }
17296 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017297 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017298 * the head's type.
17299 */
17300 type = elemDecl->subtypes->baseType;
17301 while (type != NULL) {
17302 if (IS_COMPLEX_TYPE(type)) {
17303 if ((type->flags &
17304 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17305 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
17306 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17307 if ((type->flags &
17308 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17309 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17310 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17311 } else
17312 break;
17313 if (type == headType)
17314 break;
17315 type = type->baseType;
17316 }
17317 if ((set != 0) &&
17318 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17319 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
17320 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17321 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
17322 continue;
17323 }
17324add_member:
17325 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
17326 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
17327 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
17328 }
17329 }
17330}
17331
17332/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017333 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017334 * @item: an schema element declaration/particle
17335 * @ctxt: a schema parser context
17336 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017337 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017338 * Validates the value constraints of an element declaration.
17339 *
17340 * Fixes finish doing the computations on the element declarations.
17341 */
17342static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017343xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017344 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017345 const xmlChar * name ATTRIBUTE_UNUSED)
17346{
17347 if (elemDecl == NULL)
17348 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017349 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
17350 return;
17351 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017352 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
17353 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017354}
17355
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017356/**
17357 * xmlSchemaMiscRefFixup:
17358 * @item: an schema component
17359 * @ctxt: a schema parser context
17360 * @name: the internal name of the component
17361 *
17362 * Resolves references of misc. schema components.
17363 */
17364static void
17365xmlSchemaMiscRefFixup(xmlSchemaTreeItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017366 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017367 const xmlChar * name ATTRIBUTE_UNUSED)
17368{
17369 if (item->type == XML_SCHEMA_TYPE_PARTICLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017370 if ((item->children != NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017371 (item->children->type == XML_SCHEMA_EXTRA_QNAMEREF)) {
17372 xmlSchemaQNameRefPtr ref = (xmlSchemaQNameRefPtr) item->children;
17373 xmlSchemaTreeItemPtr refItem;
17374 /*
17375 * Resolve the reference.
17376 */
17377 item->children = NULL;
17378 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
17379 ref->itemType, ref->name, ref->targetNamespace);
17380 if (refItem == NULL) {
17381 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017382 NULL, GET_NODE(item), "ref", ref->name,
17383 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017384 } else {
17385 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
17386 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017387 * NOTE that we will assign the model group definition
17388 * itself to the "term" of the particle. This will ease
17389 * the check for circular model group definitions. After
17390 * that the "term" will be assigned the model group of the
17391 * model group definition.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017392 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017393 item->children = refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017394 } else
17395 item->children = refItem;
17396 }
17397 }
17398 }
17399}
17400
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017401static int
17402xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
17403 xmlSchemaValPtr y)
17404{
17405 xmlSchemaTypePtr tx, ty, ptx, pty;
17406 int ret;
17407
17408 while (x != NULL) {
17409 /* Same types. */
17410 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
17411 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
17412 ptx = xmlSchemaGetPrimitiveType(tx);
17413 pty = xmlSchemaGetPrimitiveType(ty);
17414 /*
17415 * (1) if a datatype T' is ·derived· by ·restriction· from an
17416 * atomic datatype T then the ·value space· of T' is a subset of
17417 * the ·value space· of T. */
17418 /*
17419 * (2) if datatypes T' and T'' are ·derived· by ·restriction·
17420 * from a common atomic ancestor T then the ·value space·s of T'
17421 * and T'' may overlap.
17422 */
17423 if (ptx != pty)
17424 return(0);
17425 /*
17426 * We assume computed values to be normalized, so do a fast
17427 * string comparison for string based types.
17428 */
17429 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
17430 IS_ANY_SIMPLE_TYPE(ptx)) {
17431 if (! xmlStrEqual(
17432 xmlSchemaValueGetAsString(x),
17433 xmlSchemaValueGetAsString(y)))
17434 return (0);
17435 } else {
17436 ret = xmlSchemaCompareValuesWhtsp(
17437 x, XML_SCHEMA_WHITESPACE_PRESERVE,
17438 y, XML_SCHEMA_WHITESPACE_PRESERVE);
17439 if (ret == -2)
17440 return(-1);
17441 if (ret != 0)
17442 return(0);
17443 }
17444 /*
17445 * Lists.
17446 */
17447 x = xmlSchemaValueGetNext(x);
17448 if (x != NULL) {
17449 y = xmlSchemaValueGetNext(y);
17450 if (y == NULL)
17451 return (0);
17452 } else if (xmlSchemaValueGetNext(y) != NULL)
17453 return (0);
17454 else
17455 return (1);
17456 }
17457 return (0);
17458}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017459
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017460/**
17461 * xmlSchemaAttrFixup:
17462 * @item: an schema attribute declaration/use.
17463 * @ctxt: a schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017464 * @name: the name of the attribute
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017465 *
17466 * Fixes finish doing the computations on attribute declarations/uses.
17467 */
17468static void
17469xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017470 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017471 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000017472{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017473 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017474 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017475 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000017476 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000017477 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017478 * The simple type definition corresponding to the <simpleType> element
17479 * information item in the [children], if present, otherwise the simple
17480 * type definition ·resolved· to by the ·actual value· of the type
Daniel Veillard01fa6152004-06-29 17:04:39 +000017481 * [attribute], if present, otherwise the ·simple ur-type definition·.
17482 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017483 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000017484 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017485 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
17486 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017487 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017488 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017489 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000017490
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017491 type = xmlSchemaGetType(ctxt->schema, item->typeName,
17492 item->typeNs);
17493 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017494 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017495 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017496 (xmlSchemaTypePtr) item, item->node,
17497 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017498 XML_SCHEMA_TYPE_SIMPLE, NULL);
17499 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017500 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017501
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017502 } else if (item->ref != NULL) {
17503 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000017504
Daniel Veillardc0826a72004-08-10 14:17:33 +000017505 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017506 * We have an attribute use here; assign the referenced
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017507 * attribute declaration.
17508 */
17509 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017510 * TODO: Evaluate, what errors could occur if the declaration is not
17511 * found. It might be possible that the "typefixup" might crash if
17512 * no ref declaration was found.
17513 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017514 decl = xmlSchemaGetAttributeDecl(ctxt->schema, item->ref, item->refNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017515 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017516 xmlSchemaPResCompAttrErr(ctxt,
17517 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017518 (xmlSchemaTypePtr) item, item->node,
17519 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017520 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017521 return;
17522 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017523 item->refDecl = decl;
17524 xmlSchemaAttrFixup(decl, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017525 item->subtypes = decl->subtypes;
17526 /*
17527 * Attribute Use Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017528 * au-props-correct.2: If the {attribute declaration} has a fixed
17529 * {value constraint}, then if the attribute use itself has a
17530 * {value constraint}, it must also be fixed and its value must match
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017531 * that of the {attribute declaration}'s {value constraint}.
17532 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017533 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017534 (item->defValue != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017535 if ((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017536 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017537 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17538 NULL, NULL, item->node,
17539 "The attribute declaration has a 'fixed' value constraint "
17540 ", thus it must be 'fixed' in attribute use as well",
17541 NULL);
17542 } else {
17543 if (! xmlSchemaAreValuesEqual(item->defVal, decl->defVal)) {
17544 xmlSchemaPCustomErr(ctxt,
17545 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17546 NULL, NULL, item->node,
17547 "The 'fixed' value constraint of the attribute use "
17548 "must match the attribute declaration's value "
17549 "constraint '%s'",
17550 decl->defValue);
17551 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017552 }
17553 /*
17554 * FUTURE: One should change the values of the attr. use
17555 * if ever validation should be attempted even if the
17556 * schema itself was not fully valid.
17557 */
17558 }
Daniel Veillard3646d642004-06-02 19:19:14 +000017559 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017560 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
17561 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017562}
17563
17564/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017565 * xmlSchemaResolveIDCKeyRef:
17566 * @idc: the identity-constraint definition
17567 * @ctxt: the schema parser context
17568 * @name: the attribute name
17569 *
17570 * Resolve keyRef references to key/unique IDCs.
17571 */
17572static void
17573xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017574 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000017575 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017576{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017577 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
17578 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017579 if (idc->ref->name != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017580 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017581 ctxt->schema->idcDef,
17582 idc->ref->name,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017583 idc->ref->targetNamespace);
17584 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017585 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017586 * TODO: It is actually not an error to fail to resolve.
17587 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017588 xmlSchemaPResCompAttrErr(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017589 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017590 (xmlSchemaTypePtr) idc, idc->node,
17591 "refer", idc->ref->name,
17592 idc->ref->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017593 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
17594 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017595 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017596 }
17597}
17598
17599/**
Daniel Veillard4255d502002-04-16 15:50:10 +000017600 * xmlSchemaParse:
17601 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017602 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017603 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000017604 * XML Shema struture which can be used to validate instances.
17605 * *WARNING* this interface is highly subject to change
17606 *
17607 * Returns the internal XML Schema structure built from the resource or
17608 * NULL in case of error
17609 */
17610xmlSchemaPtr
17611xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
17612{
17613 xmlSchemaPtr ret = NULL;
17614 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017615 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017616 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017617
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017618 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017619 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017620 * the API; i.e. not automatically by the validated instance document.
17621 */
17622
Daniel Veillard4255d502002-04-16 15:50:10 +000017623 xmlSchemaInitTypes();
17624
Daniel Veillard6045c902002-10-09 21:13:59 +000017625 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000017626 return (NULL);
17627
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017628 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017629 ctxt->counter = 0;
17630 ctxt->container = NULL;
17631
17632 /*
17633 * First step is to parse the input document into an DOM/Infoset
17634 */
Daniel Veillard6045c902002-10-09 21:13:59 +000017635 if (ctxt->URL != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017636 doc = xmlReadFile((const char *) ctxt->URL, NULL,
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017637 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017638 if (doc == NULL) {
17639 xmlSchemaPErr(ctxt, NULL,
17640 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017641 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017642 ctxt->URL, NULL);
17643 return (NULL);
17644 }
Daniel Veillard6045c902002-10-09 21:13:59 +000017645 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017646 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
17647 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017648 if (doc == NULL) {
17649 xmlSchemaPErr(ctxt, NULL,
17650 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017651 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017652 NULL, NULL);
17653 return (NULL);
17654 }
17655 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000017656 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000017657 } else if (ctxt->doc != NULL) {
17658 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017659 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000017660 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017661 xmlSchemaPErr(ctxt, NULL,
17662 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017663 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017664 NULL, NULL);
17665 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000017666 }
17667
17668 /*
17669 * Then extract the root and Schema parse it
17670 */
17671 root = xmlDocGetRootElement(doc);
17672 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017673 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
17674 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017675 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000017676 if (!preserve) {
17677 xmlFreeDoc(doc);
17678 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017679 return (NULL);
17680 }
17681
17682 /*
17683 * Remove all the blank text nodes
17684 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017685 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000017686
17687 /*
17688 * Then do the parsing for good
17689 */
17690 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000017691 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000017692 if (!preserve) {
17693 xmlFreeDoc(doc);
17694 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017695 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000017696 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017697 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017698 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000017699 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017700 ctxt->ctxtType = NULL;
17701 ctxt->parentItem = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017702
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017703 /*
17704 * Resolve base types of simple/complex types.
17705 */
17706 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaResolveTypeDefs, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017707
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017708 if (ctxt->nberrors != 0)
17709 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017710
17711 if (ret->volatiles != NULL) {
17712 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17713 int i;
17714 xmlSchemaTreeItemPtr item;
17715
17716 for (i = 0; i < list->nbItems; i++) {
17717 item = (xmlSchemaTreeItemPtr) list->items[i];
17718 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17719 xmlSchemaMiscRefFixup(item, ctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017720 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017721 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017722 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000017723 * Then fixup all attributes declarations
17724 */
17725 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017726 /*
17727 * Then fixup all attributes group declarations
17728 */
17729 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
17730 ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017731 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017732 * Resolve identity-constraint keyRefs.
17733 */
17734 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017735 /*
17736 * Check type defnitions for circular references.
17737 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017738 xmlHashScan(ret->typeDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017739 xmlSchemaCheckTypeDefCircular, ctxt);
17740 /*
17741 * Check model groups defnitions for circular references.
17742 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017743 xmlHashScan(ret->groupDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017744 xmlSchemaCheckGroupDefCircular, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017745 /*
17746 * Set the "term" of particles pointing to model group definitions
17747 * to the contained model group.
17748 */
17749 if (ret->volatiles != NULL) {
17750 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17751 int i;
17752 xmlSchemaParticlePtr item;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017753
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017754 for (i = 0; i < list->nbItems; i++) {
17755 item = (xmlSchemaParticlePtr) list->items[i];
17756 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17757 xmlSchemaGroupDefTermFixup(item, ctxt, NULL);
17758 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017759 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017760 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017761 * Check attribute groups for circular references.
17762 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017763 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
17764 xmlSchemaCheckAttributeGroupCircular, ctxt);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017765 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017766 * Then fix references of element declaration; apply constraints.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017767 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000017768 xmlHashScanFull(ret->elemDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017769 (xmlHashScannerFull) xmlSchemaElementFixup, ctxt);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017770 /*
17771 * We will stop here if the schema was not valid to avoid internal errors
17772 * on missing sub-components. This is not conforming to the spec, since it
17773 * allows missing components, but it might make further processing crash.
17774 * So see it as a very strict handling, which might be made more lax in the
17775 * future.
17776 */
17777 if (ctxt->nberrors != 0)
17778 goto exit;
17779 /*
17780 * Then fixup all types properties
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017781 */
17782 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017783 /*
17784 * Validate the value constraint of attribute declarations/uses.
17785 */
17786 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017787 /*
17788 * Validate the value constraint of element declarations.
17789 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017790 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElementDeclComponent, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017791
17792 if (ctxt->nberrors != 0)
17793 goto exit;
17794
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017795 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017796 * TODO: cos-element-consistent, cos-all-limited
17797 *
17798 * Then build the content model for all complex types
17799 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017800 xmlHashScan(ret->typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017801 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017802
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017803exit:
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017804 if (ctxt->nberrors != 0) {
17805 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017806 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017807 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017808 return (ret);
17809}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017810
Daniel Veillard4255d502002-04-16 15:50:10 +000017811/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000017812 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000017813 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000017814 * @err: the error callback
17815 * @warn: the warning callback
17816 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000017817 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017818 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017819 */
17820void
17821xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017822 xmlSchemaValidityErrorFunc err,
17823 xmlSchemaValidityWarningFunc warn, void *ctx)
17824{
Daniel Veillard4255d502002-04-16 15:50:10 +000017825 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017826 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000017827 ctxt->error = err;
17828 ctxt->warning = warn;
17829 ctxt->userData = ctx;
17830}
17831
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017832/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000017833 * xmlSchemaGetParserErrors:
17834 * @ctxt: a XMl-Schema parser context
17835 * @err: the error callback result
17836 * @warn: the warning callback result
17837 * @ctx: contextual data for the callbacks result
17838 *
17839 * Get the callback information used to handle errors for a parser context
17840 *
17841 * Returns -1 in case of failure, 0 otherwise
17842 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017843int
Daniel Veillard259f0df2004-08-18 09:13:18 +000017844xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
17845 xmlSchemaValidityErrorFunc * err,
17846 xmlSchemaValidityWarningFunc * warn, void **ctx)
17847{
17848 if (ctxt == NULL)
17849 return(-1);
17850 if (err != NULL)
17851 *err = ctxt->error;
17852 if (warn != NULL)
17853 *warn = ctxt->warning;
17854 if (ctx != NULL)
17855 *ctx = ctxt->userData;
17856 return(0);
17857}
17858
17859/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017860 * xmlSchemaFacetTypeToString:
17861 * @type: the facet type
17862 *
17863 * Convert the xmlSchemaTypeType to a char string.
17864 *
17865 * Returns the char string representation of the facet type if the
17866 * type is a facet and an "Internal Error" string otherwise.
17867 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017868static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017869xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
17870{
17871 switch (type) {
17872 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017873 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017874 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017875 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017876 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017877 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017878 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017879 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017880 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017881 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017882 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017883 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017884 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017885 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017886 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017887 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017888 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017889 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017890 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017891 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017892 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017893 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017894 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017895 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017896 default:
17897 break;
17898 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017899 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017900}
17901
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017902static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000017903xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
17904{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017905 /*
17906 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000017907 * from xsd:string.
17908 */
17909 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017910 /*
17911 * Note that we assume a whitespace of preserve for anySimpleType.
17912 */
17913 if ((type->builtInType == XML_SCHEMAS_STRING) ||
17914 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
17915 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000017916 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017917 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017918 else {
17919 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017920 * For all ·atomic· datatypes other than string (and types ·derived·
17921 * by ·restriction· from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000017922 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017923 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000017924 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017925 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017926 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017927 } else if (VARIETY_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017928 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017929 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017930 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017931 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
17932 } else if (VARIETY_UNION(type)) {
17933 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
17934 } else if (VARIETY_ATOMIC(type)) {
17935 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
17936 return (XML_SCHEMA_WHITESPACE_PRESERVE);
17937 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
17938 return (XML_SCHEMA_WHITESPACE_REPLACE);
17939 else
17940 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017941 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017942 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017943}
17944
Daniel Veillard4255d502002-04-16 15:50:10 +000017945/************************************************************************
17946 * *
17947 * Simple type validation *
17948 * *
17949 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000017950
Daniel Veillard4255d502002-04-16 15:50:10 +000017951
17952/************************************************************************
17953 * *
17954 * DOM Validation code *
17955 * *
17956 ************************************************************************/
17957
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017958static void
17959xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
17960{
17961 int i, nbItems;
17962 xmlSchemaTypePtr item, *items;
17963
17964
17965 /*
17966 * During the Assemble of the schema ctxt->curItems has
17967 * been filled with the relevant new items. Fix those up.
17968 */
17969 nbItems = ctxt->assemble->nbItems;
17970 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017971
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017972 for (i = 0; i < nbItems; i++) {
17973 item = items[i];
17974 switch (item->type) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017975 case XML_SCHEMA_TYPE_COMPLEX:
17976 case XML_SCHEMA_TYPE_SIMPLE:
17977 xmlSchemaResolveTypeDefs(item, ctxt, NULL);
17978 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017979 case XML_SCHEMA_TYPE_ATTRIBUTE:
17980 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
17981 break;
17982 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017983 xmlSchemaElementFixup((xmlSchemaElementPtr) item, ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017984 NULL, NULL, NULL);
17985 break;
17986 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017987 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017988 ctxt, NULL);
17989 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017990 case XML_SCHEMA_TYPE_PARTICLE:
17991 xmlSchemaMiscRefFixup((xmlSchemaTreeItemPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017992 default:
17993 break;
17994 }
17995 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017996 if (ctxt->nberrors != 0)
17997 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017998 /*
17999 * Circularity checks.
18000 */
18001 for (i = 0; i < nbItems; i++) {
18002 item = items[i];
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018003 switch (item->type) {
18004 case XML_SCHEMA_TYPE_COMPLEX:
18005 case XML_SCHEMA_TYPE_SIMPLE:
18006 xmlSchemaCheckTypeDefCircular(
18007 (xmlSchemaTypePtr) item, ctxt, NULL);
18008 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018009 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018010 xmlSchemaCheckGroupDefCircular(
18011 (xmlSchemaModelGroupDefPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018012 break;
18013 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
18014 xmlSchemaCheckAttributeGroupCircular(
18015 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
18016 break;
18017 default:
18018 break;
18019 }
18020 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018021 if (ctxt->nberrors != 0)
18022 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018023 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018024 * Set the "term" of particles pointing to model group definitions
18025 * to the contained model group.
18026 */
18027 for (i = 0; i < nbItems; i++) {
18028 item = items[i];
18029 if ((item->type == XML_SCHEMA_TYPE_PARTICLE) &&
18030 (((xmlSchemaParticlePtr) item)->children != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018031 (((xmlSchemaParticlePtr) item)->children->type ==
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018032 XML_SCHEMA_TYPE_GROUP)) {
18033 xmlSchemaGroupDefTermFixup((xmlSchemaParticlePtr) item,
18034 ctxt, NULL);
18035 }
18036 }
18037 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018038 * Fixup for simple/complex types.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018039 */
18040 for (i = 0; i < nbItems; i++) {
18041 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018042 switch (item->type) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018043 case XML_SCHEMA_TYPE_SIMPLE:
18044 case XML_SCHEMA_TYPE_COMPLEX:
18045 xmlSchemaTypeFixup(item, ctxt, NULL);
18046 break;
18047 default:
18048 break;
18049 }
18050 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018051 if (ctxt->nberrors != 0)
18052 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018053 /*
18054 * Validate value contraint values.
18055 */
18056 for (i = 0; i < nbItems; i++) {
18057 item = items[i];
18058 switch (item->type) {
18059 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018060 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item,
18061 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018062 break;
18063 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018064 xmlSchemaCheckElementDeclComponent((xmlSchemaElementPtr) item,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018065 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018066 break;
18067 default:
18068 break;
18069 }
18070 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018071 if (ctxt->nberrors != 0)
18072 return;
18073 /*
18074 * Build the content model for complex types.
18075 */
18076 for (i = 0; i < nbItems; i++) {
18077 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018078 switch (item->type) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018079 case XML_SCHEMA_TYPE_COMPLEX:
18080 xmlSchemaBuildContentModel(item, ctxt, NULL);
18081 break;
18082 default:
18083 break;
18084 }
18085 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018086}
18087
18088/**
18089 * xmlSchemaAssembleByLocation:
18090 * @pctxt: a schema parser context
18091 * @vctxt: a schema validation context
18092 * @schema: the existing schema
18093 * @node: the node that fired the assembling
18094 * @nsName: the namespace name of the new schema
18095 * @location: the location of the schema
18096 *
18097 * Expands an existing schema by an additional schema.
18098 *
18099 * Returns 0 if the new schema is correct, a positive error code
18100 * number otherwise and -1 in case of an internal or API error.
18101 */
18102static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018103xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018104 xmlSchemaPtr schema,
18105 xmlNodePtr node,
18106 const xmlChar *nsName,
18107 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018108{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018109 const xmlChar *targetNs, *oldtns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018110 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018111 int oldflags, ret = 0, oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018112 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018113 xmlSchemaParserCtxtPtr pctxt;
18114
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018115 /*
18116 * This should be used:
18117 * 1. on <import>(s)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018118 * 2. if requested by the validated instance
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018119 * 3. if requested via the API
18120 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018121 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018122 return (-1);
18123 /*
18124 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018125 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018126 if ((vctxt->pctxt == NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018127 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
18128 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018129 pctxt = vctxt->pctxt;
18130 /*
18131 * Set the counter to produce unique names for anonymous items.
18132 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018133 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018134 /*
18135 * Acquire the schema document.
18136 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018137 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) vctxt, schema,
18138 node, nsName, location, &doc, &targetNs, 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018139 if (ret != 0) {
18140 if (doc != NULL)
18141 xmlFreeDoc(doc);
18142 } else if (doc != NULL) {
18143 docElem = xmlDocGetRootElement(doc);
18144 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018145 * Create new assemble info.
18146 */
18147 if (pctxt->assemble == NULL) {
18148 pctxt->assemble = xmlSchemaNewAssemble();
18149 if (pctxt->assemble == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018150 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018151 "Memory error: xmlSchemaAssembleByLocation, "
18152 "allocating assemble info", NULL);
18153 xmlFreeDoc(doc);
18154 return (-1);
18155 }
18156 }
18157 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018158 * Save and reset the context & schema.
18159 */
18160 oldflags = schema->flags;
18161 oldtns = schema->targetNamespace;
18162 olddoc = schema->doc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018163 oldIsS4S = vctxt->pctxt->isS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018164
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018165 xmlSchemaClearSchemaDefaults(schema);
18166 schema->targetNamespace = targetNs;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018167 if ((targetNs != NULL) &&
18168 xmlStrEqual(targetNs, xmlSchemaNs)) {
18169 /*
18170 * We are parsing the schema for schema!
18171 */
18172 vctxt->pctxt->isS4S = 1;
18173 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018174 /* schema->nbCurItems = 0; */
18175 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018176 pctxt->ctxtType = NULL;
18177 pctxt->parentItem = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018178
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018179 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
18180 if (pctxt->nberrors != 0) {
18181 vctxt->nberrors += pctxt->nberrors;
18182 goto finally;
18183 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018184 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018185 if (pctxt->nberrors != 0) {
18186 vctxt->nberrors += pctxt->nberrors;
18187 goto finally;
18188 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018189 xmlSchemaPostSchemaAssembleFixup(pctxt);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018190 if (pctxt->nberrors != 0)
18191 vctxt->nberrors += pctxt->nberrors;
18192finally:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018193 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018194 * Set the counter of items.
18195 */
18196 schema->counter = pctxt->counter;
18197 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018198 * Free the list of assembled components.
18199 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018200 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018201 /*
18202 * Restore the context & schema.
18203 */
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018204 vctxt->pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018205 schema->flags = oldflags;
18206 schema->targetNamespace = oldtns;
18207 schema->doc = olddoc;
18208 ret = pctxt->err;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018209 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018210 return (ret);
18211}
18212
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018213static xmlSchemaAttrInfoPtr
18214xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
18215 int metaType)
18216{
18217 if (vctxt->nbAttrInfos == 0)
18218 return (NULL);
18219 {
18220 int i;
18221 xmlSchemaAttrInfoPtr iattr;
18222
18223 for (i = 0; i < vctxt->nbAttrInfos; i++) {
18224 iattr = vctxt->attrInfos[i];
18225 if (iattr->metaType == metaType)
18226 return (iattr);
18227 }
18228
18229 }
18230 return (NULL);
18231}
18232
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018233/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018234 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018235 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018236 *
18237 * Expands an existing schema by an additional schema using
18238 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
18239 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
18240 * must be set to 1.
18241 *
18242 * Returns 0 if the new schema is correct, a positive error code
18243 * number otherwise and -1 in case of an internal or API error.
18244 */
18245static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018246xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018247{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018248 const xmlChar *cur, *end;
18249 const xmlChar *nsname = NULL, *location;
18250 int count = 0;
18251 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018252 xmlSchemaAttrInfoPtr iattr;
18253
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018254 /*
18255 * Parse the value; we will assume an even number of values
18256 * to be given (this is how Xerces and XSV work).
18257 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018258 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
18259 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
18260 if (iattr == NULL)
18261 xmlSchemaGetMetaAttrInfo(vctxt,
18262 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
18263 if (iattr == NULL)
18264 return (0);
18265 cur = iattr->value;
18266 do {
18267 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018268 /*
18269 * Get the namespace name.
18270 */
18271 while (IS_BLANK_CH(*cur))
18272 cur++;
18273 end = cur;
18274 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18275 end++;
18276 if (end == cur)
18277 break;
18278 count++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018279 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018280 cur = end;
18281 }
18282 /*
18283 * Get the URI.
18284 */
18285 while (IS_BLANK_CH(*cur))
18286 cur++;
18287 end = cur;
18288 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18289 end++;
18290 if (end == cur)
18291 break;
18292 count++;
18293 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018294 cur = end;
18295 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
18296 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018297 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018298 VERROR_INT("xmlSchemaAssembleByXSI",
18299 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018300 return (-1);
18301 }
18302 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018303 return (ret);
18304}
18305
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018306#define VAL_CREATE_DICT if (vctxt->dict == NULL) vctxt->dict = xmlDictCreate();
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018307
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018308static const xmlChar *
18309xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
18310 const xmlChar *prefix)
18311{
18312 if (vctxt->sax != NULL) {
18313 int i, j;
18314 xmlSchemaNodeInfoPtr inode;
18315
18316 for (i = vctxt->depth; i >= 0; i--) {
18317 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
18318 inode = vctxt->elemInfos[i];
18319 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
18320 if (((prefix == NULL) &&
18321 (inode->nsBindings[j] == NULL)) ||
18322 ((prefix != NULL) && xmlStrEqual(prefix,
18323 inode->nsBindings[j]))) {
18324
18325 /*
18326 * Note that the namespace bindings are already
18327 * in a string dict.
18328 */
18329 return (inode->nsBindings[j+1]);
18330 }
18331 }
18332 }
18333 }
18334 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018335#ifdef LIBXML_WRITER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018336 } else if (vctxt->reader != NULL) {
18337 xmlChar *nsName;
18338
18339 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
18340 if (nsName != NULL) {
18341 const xmlChar *ret;
18342
18343 VAL_CREATE_DICT;
18344 ret = xmlDictLookup(vctxt->dict, nsName, -1);
18345 xmlFree(nsName);
18346 return (ret);
18347 } else
18348 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018349#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018350 } else {
18351 xmlNsPtr ns;
18352
18353 if ((vctxt->inode->node == NULL) ||
18354 (vctxt->inode->node->doc == NULL)) {
18355 VERROR_INT("xmlSchemaLookupNamespace",
18356 "no node or node's doc avaliable");
18357 return (NULL);
18358 }
18359 ns = xmlSearchNs(vctxt->inode->node->doc,
18360 vctxt->inode->node, prefix);
18361 if (ns != NULL)
18362 return (ns->href);
18363 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018364 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018365}
18366
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018367/*
18368* This one works on the schema of the validation context.
18369*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018370static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018371xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
18372 xmlSchemaPtr schema,
18373 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018374 const xmlChar *value,
18375 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018376 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018377{
18378 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018379
18380 if (vctxt && (vctxt->schema == NULL)) {
18381 VERROR_INT("xmlSchemaValidateNotation",
18382 "a schema is needed on the validation context");
18383 return (-1);
18384 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018385 ret = xmlValidateQName(value, 1);
18386 if (ret != 0)
18387 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018388 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018389 xmlChar *localName = NULL;
18390 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018391
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018392 localName = xmlSplitQName2(value, &prefix);
18393 if (prefix != NULL) {
18394 const xmlChar *nsName = NULL;
18395
18396 if (vctxt != NULL)
18397 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
18398 else if (node != NULL) {
18399 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
18400 if (ns != NULL)
18401 nsName = ns->href;
18402 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018403 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018404 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018405 return (1);
18406 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018407 if (nsName == NULL) {
18408 xmlFree(prefix);
18409 xmlFree(localName);
18410 return (1);
18411 }
18412 if (xmlHashLookup2(schema->notaDecl, localName,
18413 nsName) != NULL) {
18414 if (valNeeded && (val != NULL)) {
18415 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
18416 BAD_CAST xmlStrdup(nsName));
18417 if (*val == NULL)
18418 ret = -1;
18419 }
18420 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018421 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018422 xmlFree(prefix);
18423 xmlFree(localName);
18424 } else {
18425 if (xmlHashLookup2(schema->notaDecl, value, NULL) != NULL) {
18426 if (valNeeded && (val != NULL)) {
18427 (*val) = xmlSchemaNewNOTATIONValue(
18428 BAD_CAST xmlStrdup(value), NULL);
18429 if (*val == NULL)
18430 ret = -1;
18431 }
18432 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018433 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018434 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018435 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018436 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018437}
18438
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018439/************************************************************************
18440 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018441 * Validation of identity-constraints (IDC) *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018442 * *
18443 ************************************************************************/
18444
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018445/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018446 * xmlSchemaAugmentIDC:
18447 * @idcDef: the IDC definition
18448 *
18449 * Creates an augmented IDC definition item.
18450 *
18451 * Returns the item, or NULL on internal errors.
18452 */
18453static void
18454xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
18455 xmlSchemaValidCtxtPtr vctxt)
18456{
18457 xmlSchemaIDCAugPtr aidc;
18458
18459 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
18460 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018461 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018462 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
18463 NULL);
18464 return;
18465 }
18466 aidc->bubbleDepth = -1;
18467 aidc->def = idcDef;
18468 aidc->next = NULL;
18469 if (vctxt->aidcs == NULL)
18470 vctxt->aidcs = aidc;
18471 else {
18472 aidc->next = vctxt->aidcs;
18473 vctxt->aidcs = aidc;
18474 }
18475}
18476
18477/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018478 * xmlSchemaIDCNewBinding:
18479 * @idcDef: the IDC definition of this binding
18480 *
18481 * Creates a new IDC binding.
18482 *
18483 * Returns the new binding in case of succeeded, NULL on internal errors.
18484 */
18485static xmlSchemaPSVIIDCBindingPtr
18486xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
18487{
18488 xmlSchemaPSVIIDCBindingPtr ret;
18489
18490 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
18491 sizeof(xmlSchemaPSVIIDCBinding));
18492 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018493 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018494 "allocating a PSVI IDC binding item", NULL);
18495 return (NULL);
18496 }
18497 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
18498 ret->definition = idcDef;
18499 return (ret);
18500}
18501
18502/**
18503 * xmlSchemaIDCStoreNodeTableItem:
18504 * @vctxt: the WXS validation context
18505 * @item: the IDC node table item
18506 *
18507 * The validation context is used to store an IDC node table items.
18508 * They are stored to avoid copying them if IDC node-tables are merged
18509 * with corresponding parent IDC node-tables (bubbling).
18510 *
18511 * Returns 0 if succeeded, -1 on internal errors.
18512 */
18513static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018514xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018515 xmlSchemaPSVIIDCNodePtr item)
18516{
18517 /*
18518 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018519 */
18520 if (vctxt->idcNodes == NULL) {
18521 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018522 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
18523 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018524 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018525 "allocating the IDC node table item list", NULL);
18526 return (-1);
18527 }
18528 vctxt->sizeIdcNodes = 20;
18529 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
18530 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018531 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
18532 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018533 sizeof(xmlSchemaPSVIIDCNodePtr));
18534 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018535 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018536 "re-allocating the IDC node table item list", NULL);
18537 return (-1);
18538 }
18539 }
18540 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018541
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018542 return (0);
18543}
18544
18545/**
18546 * xmlSchemaIDCStoreKey:
18547 * @vctxt: the WXS validation context
18548 * @item: the IDC key
18549 *
18550 * The validation context is used to store an IDC key.
18551 *
18552 * Returns 0 if succeeded, -1 on internal errors.
18553 */
18554static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018555xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018556 xmlSchemaPSVIIDCKeyPtr key)
18557{
18558 /*
18559 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018560 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018561 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018562 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018563 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
18564 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018565 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018566 "allocating the IDC key storage list", NULL);
18567 return (-1);
18568 }
18569 vctxt->sizeIdcKeys = 40;
18570 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
18571 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018572 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
18573 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018574 sizeof(xmlSchemaPSVIIDCKeyPtr));
18575 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018576 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018577 "re-allocating the IDC key storage list", NULL);
18578 return (-1);
18579 }
18580 }
18581 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018582
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018583 return (0);
18584}
18585
18586/**
18587 * xmlSchemaIDCAppendNodeTableItem:
18588 * @bind: the IDC binding
18589 * @ntItem: the node-table item
18590 *
18591 * Appends the IDC node-table item to the binding.
18592 *
18593 * Returns 0 on success and -1 on internal errors.
18594 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018595static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018596xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
18597 xmlSchemaPSVIIDCNodePtr ntItem)
18598{
18599 if (bind->nodeTable == NULL) {
18600 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018601 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018602 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
18603 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018604 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018605 "allocating an array of IDC node-table items", NULL);
18606 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018607 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018608 } else if (bind->sizeNodes <= bind->nbNodes) {
18609 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018610 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18611 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018612 sizeof(xmlSchemaPSVIIDCNodePtr));
18613 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018614 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018615 "re-allocating an array of IDC node-table items", NULL);
18616 return(-1);
18617 }
18618 }
18619 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018620 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018621}
18622
18623/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018624 * xmlSchemaIDCAquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018625 * @vctxt: the WXS validation context
18626 * @matcher: the IDC matcher
18627 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018628 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018629 * of the given matcher. If none found, a new one is created
18630 * and added to the IDC table.
18631 *
18632 * Returns an IDC binding or NULL on internal errors.
18633 */
18634static xmlSchemaPSVIIDCBindingPtr
18635xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
18636 xmlSchemaIDCMatcherPtr matcher)
18637{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018638 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018639
18640 info = vctxt->elemInfos[matcher->depth];
18641
18642 if (info->idcTable == NULL) {
18643 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
18644 if (info->idcTable == NULL)
18645 return (NULL);
18646 return(info->idcTable);
18647 } else {
18648 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018649
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018650 bind = info->idcTable;
18651 do {
18652 if (bind->definition == matcher->aidc->def)
18653 return(bind);
18654 if (bind->next == NULL) {
18655 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
18656 if (bind->next == NULL)
18657 return (NULL);
18658 return(bind->next);
18659 }
18660 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018661 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018662 }
18663 return (NULL);
18664}
18665
18666/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018667 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018668 * @key: the IDC key
18669 *
18670 * Frees an IDC key together with its compiled value.
18671 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018672static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018673xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
18674{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018675 if (key->val != NULL)
18676 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018677 xmlFree(key);
18678}
18679
18680/**
18681 * xmlSchemaIDCFreeBinding:
18682 *
18683 * Frees an IDC binding. Note that the node table-items
18684 * are not freed.
18685 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018686static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018687xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
18688{
18689 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018690 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18691 int i;
18692 /*
18693 * Node-table items for keyrefs are not stored globally
18694 * to the validation context, since they are not bubbled.
18695 * We need to free them here.
18696 */
18697 for (i = 0; i < bind->nbNodes; i++) {
18698 xmlFree(bind->nodeTable[i]->keys);
18699 xmlFree(bind->nodeTable[i]);
18700 }
18701 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018702 xmlFree(bind->nodeTable);
18703 }
18704 xmlFree(bind);
18705}
18706
18707/**
18708 * xmlSchemaIDCFreeIDCTable:
18709 * @bind: the first IDC binding in the list
18710 *
18711 * Frees an IDC table, i.e. all the IDC bindings in the list.
18712 */
18713static void
18714xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
18715{
18716 xmlSchemaPSVIIDCBindingPtr prev;
18717
18718 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018719 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018720 bind = bind->next;
18721 xmlSchemaIDCFreeBinding(prev);
18722 }
18723}
18724
18725/**
18726 * xmlSchemaIDCFreeMatcherList:
18727 * @matcher: the first IDC matcher in the list
18728 *
18729 * Frees a list of IDC matchers.
18730 */
18731static void
18732xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
18733{
18734 xmlSchemaIDCMatcherPtr next;
18735
18736 while (matcher != NULL) {
18737 next = matcher->next;
18738 if (matcher->keySeqs != NULL) {
18739 int i;
18740 for (i = 0; i < matcher->sizeKeySeqs; i++)
18741 if (matcher->keySeqs[i] != NULL)
18742 xmlFree(matcher->keySeqs[i]);
18743 xmlFree(matcher->keySeqs);
18744 }
18745 xmlFree(matcher);
18746 matcher = next;
18747 }
18748}
18749
18750/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018751 * xmlSchemaIDCAddStateObject:
18752 * @vctxt: the WXS validation context
18753 * @matcher: the IDC matcher
18754 * @sel: the XPath information
18755 * @parent: the parent "selector" state object if any
18756 * @type: "selector" or "field"
18757 *
18758 * Creates/reuses and activates state objects for the given
18759 * XPath information; if the XPath expression consists of unions,
18760 * multiple state objects are created for every unioned expression.
18761 *
18762 * Returns 0 on success and -1 on internal errors.
18763 */
18764static int
18765xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
18766 xmlSchemaIDCMatcherPtr matcher,
18767 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018768 int type)
18769{
18770 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018771
18772 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018773 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018774 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018775 if (vctxt->xpathStatePool != NULL) {
18776 sto = vctxt->xpathStatePool;
18777 vctxt->xpathStatePool = sto->next;
18778 sto->next = NULL;
18779 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018780 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018781 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018782 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018783 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
18784 if (sto == NULL) {
18785 xmlSchemaVErrMemory(NULL,
18786 "allocating an IDC state object", NULL);
18787 return (-1);
18788 }
18789 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
18790 }
18791 /*
18792 * Add to global list.
18793 */
18794 if (vctxt->xpathStates != NULL)
18795 sto->next = vctxt->xpathStates;
18796 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018797
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018798 /*
18799 * Free the old xpath validation context.
18800 */
18801 if (sto->xpathCtxt != NULL)
18802 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
18803
18804 /*
18805 * Create a new XPath (pattern) validation context.
18806 */
18807 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
18808 (xmlPatternPtr) sel->xpathComp);
18809 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018810 VERROR_INT("xmlSchemaIDCAddStateObject",
18811 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018812 return (-1);
18813 }
18814 sto->type = type;
18815 sto->depth = vctxt->depth;
18816 sto->matcher = matcher;
18817 sto->sel = sel;
18818 sto->nbHistory = 0;
18819
18820#if DEBUG_IDC
18821 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
18822 sto->sel->xpath);
18823#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018824 return (0);
18825}
18826
18827/**
18828 * xmlSchemaXPathEvaluate:
18829 * @vctxt: the WXS validation context
18830 * @nodeType: the nodeType of the current node
18831 *
18832 * Evaluates all active XPath state objects.
18833 *
18834 * Returns the number of IC "field" state objects which resolved to
18835 * this node, 0 if none resolved and -1 on internal errors.
18836 */
18837static int
18838xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018839 xmlElementType nodeType)
18840{
18841 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018842 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018843
18844 if (vctxt->xpathStates == NULL)
18845 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018846
18847 if (nodeType == XML_ATTRIBUTE_NODE)
18848 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018849#if DEBUG_IDC
18850 {
18851 xmlChar *str = NULL;
18852 xmlGenericError(xmlGenericErrorContext,
18853 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018854 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
18855 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018856 FREE_AND_NULL(str)
18857 }
18858#endif
18859 /*
18860 * Process all active XPath state objects.
18861 */
18862 first = vctxt->xpathStates;
18863 sto = first;
18864 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018865#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018866 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018867 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
18868 sto->matcher->aidc->def->name, sto->sel->xpath);
18869 else
18870 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
18871 sto->matcher->aidc->def->name, sto->sel->xpath);
18872#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018873 if (nodeType == XML_ELEMENT_NODE)
18874 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018875 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018876 else
18877 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018878 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018879
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018880 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018881 VERROR_INT("xmlSchemaXPathEvaluate",
18882 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018883 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018884 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018885 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018886 goto next_sto;
18887 /*
18888 * Full match.
18889 */
18890#if DEBUG_IDC
18891 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018892 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018893#endif
18894 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018895 * Register a match in the state object history.
18896 */
18897 if (sto->history == NULL) {
18898 sto->history = (int *) xmlMalloc(5 * sizeof(int));
18899 if (sto->history == NULL) {
18900 xmlSchemaVErrMemory(NULL,
18901 "allocating the state object history", NULL);
18902 return(-1);
18903 }
18904 sto->sizeHistory = 10;
18905 } else if (sto->sizeHistory <= sto->nbHistory) {
18906 sto->sizeHistory *= 2;
18907 sto->history = (int *) xmlRealloc(sto->history,
18908 sto->sizeHistory * sizeof(int));
18909 if (sto->history == NULL) {
18910 xmlSchemaVErrMemory(NULL,
18911 "re-allocating the state object history", NULL);
18912 return(-1);
18913 }
18914 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018915 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018916
18917#ifdef DEBUG_IDC
18918 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
18919 vctxt->depth);
18920#endif
18921
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018922 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
18923 xmlSchemaIDCSelectPtr sel;
18924 /*
18925 * Activate state objects for the IDC fields of
18926 * the IDC selector.
18927 */
18928#if DEBUG_IDC
18929 xmlGenericError(xmlGenericErrorContext, "IDC: "
18930 "activating field states\n");
18931#endif
18932 sel = sto->matcher->aidc->def->fields;
18933 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018934 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
18935 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
18936 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018937 sel = sel->next;
18938 }
18939 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
18940 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018941 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018942 */
18943#if DEBUG_IDC
18944 xmlGenericError(xmlGenericErrorContext,
18945 "IDC: key found\n");
18946#endif
18947 /*
18948 * Notify that the character value of this node is
18949 * needed.
18950 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018951 if (resolved == 0) {
18952 if ((vctxt->inode->flags &
18953 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
18954 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
18955 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018956 resolved++;
18957 }
18958next_sto:
18959 if (sto->next == NULL) {
18960 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018961 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018962 */
18963 head = first;
18964 sto = vctxt->xpathStates;
18965 } else
18966 sto = sto->next;
18967 }
18968 return (resolved);
18969}
18970
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000018971static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018972xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000018973 xmlChar **buf,
18974 xmlSchemaPSVIIDCKeyPtr *seq,
18975 int count)
18976{
18977 int i, res;
18978 const xmlChar *value = NULL;
18979
18980 *buf = xmlStrdup(BAD_CAST "[");
18981 for (i = 0; i < count; i++) {
18982 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018983 res = xmlSchemaGetCanonValueWhtsp(seq[i]->val, &value,
18984 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type));
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000018985 if (res == 0)
18986 *buf = xmlStrcat(*buf, value);
18987 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018988 VERROR_INT("xmlSchemaFormatIDCKeySequence",
18989 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000018990 *buf = xmlStrcat(*buf, BAD_CAST "???");
18991 }
18992 if (i < count -1)
18993 *buf = xmlStrcat(*buf, BAD_CAST "', ");
18994 else
18995 *buf = xmlStrcat(*buf, BAD_CAST "'");
18996 if (value != NULL) {
18997 xmlFree((xmlChar *) value);
18998 value = NULL;
18999 }
19000 }
19001 *buf = xmlStrcat(*buf, BAD_CAST "]");
19002
19003 return (BAD_CAST *buf);
19004}
19005
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019006/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019007 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019008 * @vctxt: the WXS validation context
19009 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019010 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019011 *
19012 * Processes and pops the history items of the IDC state objects.
19013 * IDC key-sequences are validated/created on IDC bindings.
19014 *
19015 * Returns 0 on success and -1 on internal errors.
19016 */
19017static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019018xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019019 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019020{
19021 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019022 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019023 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019024 xmlSchemaTypePtr type = vctxt->inode->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019025
19026 if (vctxt->xpathStates == NULL)
19027 return (0);
19028 sto = vctxt->xpathStates;
19029
19030#if DEBUG_IDC
19031 {
19032 xmlChar *str = NULL;
19033 xmlGenericError(xmlGenericErrorContext,
19034 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019035 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19036 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019037 FREE_AND_NULL(str)
19038 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019039#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019040 /*
19041 * Evaluate the state objects.
19042 */
19043 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000019044 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
19045 if (res == -1) {
19046 VERROR_INT("xmlSchemaXPathProcessHistory",
19047 "calling xmlStreamPop()");
19048 return (-1);
19049 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019050#if DEBUG_IDC
19051 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
19052 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019053#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019054 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019055 goto deregister_check;
19056
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019057 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019058
19059 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019060 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019061 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019062 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019063 sto = sto->next;
19064 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019065 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019066 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19067 if (! IS_SIMPLE_TYPE(type)) {
19068 /*
19069 * Not qualified if the field resolves to a node of non
19070 * simple type.
19071 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019072 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19073 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019074 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19075 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019076 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019077
19078 sto->nbHistory--;
19079 goto deregister_check;
19080 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019081 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019082 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019083 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019084 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019085 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019086 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019087 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19088 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019089 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019090 sto->nbHistory--;
19091 goto deregister_check;
19092 } else {
19093 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
19094 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019095 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019096
19097 /*
19098 * The key will be anchored on the matcher's list of
19099 * key-sequences. The position in this list is determined
19100 * by the target node's depth relative to the matcher's
19101 * depth of creation (i.e. the depth of the scope element).
19102 */
19103 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019104 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019105
19106 /*
19107 * Create/grow the array of key-sequences.
19108 */
19109 if (matcher->keySeqs == NULL) {
19110 if (pos > 9)
19111 matcher->sizeKeySeqs = pos * 2;
19112 else
19113 matcher->sizeKeySeqs = 10;
19114 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19115 xmlMalloc(matcher->sizeKeySeqs *
19116 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19117 if (matcher->keySeqs == NULL) {
19118 xmlSchemaVErrMemory(NULL,
19119 "allocating an array of key-sequences",
19120 NULL);
19121 return(-1);
19122 }
19123 memset(matcher->keySeqs, 0,
19124 matcher->sizeKeySeqs *
19125 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19126 } else if (pos >= matcher->sizeKeySeqs) {
19127 int i = matcher->sizeKeySeqs;
19128
19129 matcher->sizeKeySeqs *= 2;
19130 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19131 xmlRealloc(matcher->keySeqs,
19132 matcher->sizeKeySeqs *
19133 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019134 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019135 xmlSchemaVErrMemory(NULL,
19136 "reallocating an array of key-sequences",
19137 NULL);
19138 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019139 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019140 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019141 * The array needs to be NULLed.
19142 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019143 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019144 for (; i < matcher->sizeKeySeqs; i++)
19145 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019146 }
19147
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019148 /*
19149 * Get/create the key-sequence.
19150 */
19151 keySeq = matcher->keySeqs[pos];
19152 if (keySeq == NULL) {
19153 goto create_sequence;
19154 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019155 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019156 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019157 * cvc-identity-constraint:
19158 * 3 For each node in the ·target node set· all
19159 * of the {fields}, with that node as the context
19160 * node, evaluate to either an empty node-set or
19161 * a node-set with exactly one member, which must
19162 * have a simple type.
19163 *
19164 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019165 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019166 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19167 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019168 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019169 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019170 "with more than one member",
19171 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019172 sto->nbHistory--;
19173 goto deregister_check;
19174 } else {
19175 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019176 }
19177 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019178
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019179create_sequence:
19180 /*
19181 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019182 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019183 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
19184 matcher->aidc->def->nbFields *
19185 sizeof(xmlSchemaPSVIIDCKeyPtr));
19186 if (keySeq == NULL) {
19187 xmlSchemaVErrMemory(NULL,
19188 "allocating an IDC key-sequence", NULL);
19189 return(-1);
19190 }
19191 memset(keySeq, 0, matcher->aidc->def->nbFields *
19192 sizeof(xmlSchemaPSVIIDCKeyPtr));
19193 matcher->keySeqs[pos] = keySeq;
19194create_key:
19195 /*
19196 * Created a key once per node only.
19197 */
19198 if (key == NULL) {
19199 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
19200 sizeof(xmlSchemaPSVIIDCKey));
19201 if (key == NULL) {
19202 xmlSchemaVErrMemory(NULL,
19203 "allocating a IDC key", NULL);
19204 xmlFree(keySeq);
19205 matcher->keySeqs[pos] = NULL;
19206 return(-1);
19207 }
19208 /*
19209 * Consume the compiled value.
19210 */
19211 key->type = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019212 key->val = vctxt->inode->val;
19213 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019214 /*
19215 * Store the key in a global list.
19216 */
19217 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
19218 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019219 return (-1);
19220 }
19221 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019222 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019223 }
19224 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019225
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019226 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
19227 xmlSchemaPSVIIDCBindingPtr bind;
19228 xmlSchemaPSVIIDCNodePtr ntItem;
19229 xmlSchemaIDCMatcherPtr matcher;
19230 xmlSchemaIDCPtr idc;
19231 int pos, i, j, nbKeys;
19232 /*
19233 * Here we have the following scenario:
19234 * An IDC 'selector' state object resolved to a target node,
19235 * during the time this target node was in the
19236 * ancestor-or-self axis, the 'field' state object(s) looked
19237 * out for matching nodes to create a key-sequence for this
19238 * target node. Now we are back to this target node and need
19239 * to put the key-sequence, together with the target node
19240 * itself, into the node-table of the corresponding IDC
19241 * binding.
19242 */
19243 matcher = sto->matcher;
19244 idc = matcher->aidc->def;
19245 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019246 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019247 /*
19248 * Check if the matcher has any key-sequences at all, plus
19249 * if it has a key-sequence for the current target node.
19250 */
19251 if ((matcher->keySeqs == NULL) ||
19252 (matcher->sizeKeySeqs <= pos)) {
19253 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19254 goto selector_key_error;
19255 else
19256 goto selector_leave;
19257 }
19258
19259 keySeq = &(matcher->keySeqs[pos]);
19260 if (*keySeq == NULL) {
19261 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19262 goto selector_key_error;
19263 else
19264 goto selector_leave;
19265 }
19266
19267 for (i = 0; i < nbKeys; i++) {
19268 if ((*keySeq)[i] == NULL) {
19269 /*
19270 * Not qualified, if not all fields did resolve.
19271 */
19272 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
19273 /*
19274 * All fields of a "key" IDC must resolve.
19275 */
19276 goto selector_key_error;
19277 }
19278 goto selector_leave;
19279 }
19280 }
19281 /*
19282 * All fields did resolve.
19283 */
19284
19285 /*
19286 * 4.1 If the {identity-constraint category} is unique(/key),
19287 * then no two members of the ·qualified node set· have
19288 * ·key-sequences· whose members are pairwise equal, as
19289 * defined by Equal in [XML Schemas: Datatypes].
19290 *
19291 * Get the IDC binding from the matcher and check for
19292 * duplicate key-sequences.
19293 */
19294 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
19295 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
19296 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019297 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019298
19299 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019300 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019301 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019302 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019303 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019304 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019305 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019306 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019307 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019308 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019309 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019310 if (res == -1) {
19311 return (-1);
19312 } else if (res == 0)
19313 break;
19314 }
19315 if (res == 1) {
19316 /*
19317 * Duplicate found.
19318 */
19319 break;
19320 }
19321 i++;
19322 } while (i < bind->nbNodes);
19323 if (i != bind->nbNodes) {
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019324 xmlChar *str = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019325 /*
19326 * TODO: Try to report the key-sequence.
19327 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019328 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19329 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019330 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019331 "Duplicate key-sequence %s",
19332 xmlSchemaFormatIDCKeySequence(vctxt, &str,
19333 (*keySeq), nbKeys), NULL);
19334 FREE_AND_NULL(str)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019335 goto selector_leave;
19336 }
19337 }
19338 /*
19339 * Add a node-table item to the IDC binding.
19340 */
19341 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
19342 sizeof(xmlSchemaPSVIIDCNode));
19343 if (ntItem == NULL) {
19344 xmlSchemaVErrMemory(NULL,
19345 "allocating an IDC node-table item", NULL);
19346 xmlFree(*keySeq);
19347 *keySeq = NULL;
19348 return(-1);
19349 }
19350 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
19351
19352 /*
19353 * Store the node-table item on global list.
19354 */
19355 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
19356 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
19357 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019358 xmlFree(*keySeq);
19359 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019360 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019361 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019362 }
19363 /*
19364 * Init the node-table item. Consume the key-sequence.
19365 */
19366 ntItem->node = vctxt->node;
19367 ntItem->keys = *keySeq;
19368 *keySeq = NULL;
19369 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
19370 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19371 /*
19372 * Free the item, since keyref items won't be
19373 * put on a global list.
19374 */
19375 xmlFree(ntItem->keys);
19376 xmlFree(ntItem);
19377 }
19378 return (-1);
19379 }
19380
19381 goto selector_leave;
19382selector_key_error:
19383 /*
19384 * 4.2.1 (KEY) The ·target node set· and the
19385 * ·qualified node set· are equal, that is, every
19386 * member of the ·target node set· is also a member
19387 * of the ·qualified node set· and vice versa.
19388 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019389 VERROR(XML_SCHEMAV_CVC_IDC, (xmlSchemaTypePtr) idc,
19390 "All 'key' fields must evaluate to a node");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019391selector_leave:
19392 /*
19393 * Free the key-sequence if not added to the IDC table.
19394 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019395 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019396 xmlFree(*keySeq);
19397 *keySeq = NULL;
19398 }
19399 } /* if selector */
19400
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019401 sto->nbHistory--;
19402
19403deregister_check:
19404 /*
19405 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019406 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019407 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019408#if DEBUG_IDC
19409 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
19410 sto->sel->xpath);
19411#endif
19412 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019413 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019414 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019415 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019416 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019417 nextsto = sto->next;
19418 /*
19419 * Unlink from the list of active XPath state objects.
19420 */
19421 vctxt->xpathStates = sto->next;
19422 sto->next = vctxt->xpathStatePool;
19423 /*
19424 * Link it to the pool of reusable state objects.
19425 */
19426 vctxt->xpathStatePool = sto;
19427 sto = nextsto;
19428 } else
19429 sto = sto->next;
19430 } /* while (sto != NULL) */
19431 return (0);
19432}
19433
19434/**
19435 * xmlSchemaIDCRegisterMatchers:
19436 * @vctxt: the WXS validation context
19437 * @elemDecl: the element declaration
19438 *
19439 * Creates helper objects to evaluate IDC selectors/fields
19440 * successively.
19441 *
19442 * Returns 0 if OK and -1 on internal errors.
19443 */
19444static int
19445xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
19446 xmlSchemaElementPtr elemDecl)
19447{
19448 xmlSchemaIDCMatcherPtr matcher, last = NULL;
19449 xmlSchemaIDCPtr idc, refIdc;
19450 xmlSchemaIDCAugPtr aidc;
19451
19452 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
19453 if (idc == NULL)
19454 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019455
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019456#if DEBUG_IDC
19457 {
19458 xmlChar *str = NULL;
19459 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019460 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019461 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19462 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019463 FREE_AND_NULL(str)
19464 }
19465#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019466 if (vctxt->inode->idcMatchers != NULL) {
19467 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19468 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019469 return (-1);
19470 }
19471 do {
19472 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19473 /*
19474 * Since IDCs bubbles are expensive we need to know the
19475 * depth at which the bubbles should stop; this will be
19476 * the depth of the top-most keyref IDC. If no keyref
19477 * references a key/unique IDC, the bubbleDepth will
19478 * be -1, indicating that no bubbles are needed.
19479 */
19480 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
19481 if (refIdc != NULL) {
19482 /*
19483 * Lookup the augmented IDC.
19484 */
19485 aidc = vctxt->aidcs;
19486 while (aidc != NULL) {
19487 if (aidc->def == refIdc)
19488 break;
19489 aidc = aidc->next;
19490 }
19491 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019492 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019493 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019494 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019495 return (-1);
19496 }
19497 if ((aidc->bubbleDepth == -1) ||
19498 (vctxt->depth < aidc->bubbleDepth))
19499 aidc->bubbleDepth = vctxt->depth;
19500 }
19501 }
19502 /*
19503 * Lookup the augmented IDC item for the IDC definition.
19504 */
19505 aidc = vctxt->aidcs;
19506 while (aidc != NULL) {
19507 if (aidc->def == idc)
19508 break;
19509 aidc = aidc->next;
19510 }
19511 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019512 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19513 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019514 return (-1);
19515 }
19516 /*
19517 * Create an IDC matcher for every IDC definition.
19518 */
19519 matcher = (xmlSchemaIDCMatcherPtr)
19520 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
19521 if (matcher == NULL) {
19522 xmlSchemaVErrMemory(vctxt,
19523 "allocating an IDC matcher", NULL);
19524 return (-1);
19525 }
19526 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
19527 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019528 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019529 else
19530 last->next = matcher;
19531 last = matcher;
19532
19533 matcher->type = IDC_MATCHER;
19534 matcher->depth = vctxt->depth;
19535 matcher->aidc = aidc;
19536#if DEBUG_IDC
19537 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
19538#endif
19539 /*
19540 * Init the automaton state object.
19541 */
19542 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019543 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019544 return (-1);
19545
19546 idc = idc->next;
19547 } while (idc != NULL);
19548 return (0);
19549}
19550
19551/**
19552 * xmlSchemaBubbleIDCNodeTables:
19553 * @depth: the current tree depth
19554 *
19555 * Merges IDC bindings of an element at @depth into the corresponding IDC
19556 * bindings of its parent element. If a duplicate note-table entry is found,
19557 * both, the parent node-table entry and child entry are discarded from the
19558 * node-table of the parent.
19559 *
19560 * Returns 0 if OK and -1 on internal errors.
19561 */
19562static int
19563xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
19564{
19565 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019566 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
19567 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019568 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
19569 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019570 int i, j, k, ret = 0, oldNum, newDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019571 int duplTop;
19572
19573 /*
19574 * The node table has the following sections:
19575 *
19576 * O --> old node-table entries (first)
19577 * O
19578 * + --> new node-table entries
19579 * +
19580 * % --> new duplicate node-table entries
19581 * %
19582 * # --> old duplicate node-table entries
19583 * # (last)
19584 *
19585 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019586 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019587 if (bind == NULL) {
19588 /* Fine, no table, no bubbles. */
19589 return (0);
19590 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019591
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019592 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
19593 /*
19594 * Walk all bindings; create new or add to existing bindings.
19595 * Remove duplicate key-sequences.
19596 */
19597start_binding:
19598 while (bind != NULL) {
19599 /*
19600 * Skip keyref IDCs.
19601 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019602 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19603 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019604 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019605 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019606 /*
19607 * Check if the key/unique IDC table needs to be bubbled.
19608 */
19609 aidc = vctxt->aidcs;
19610 do {
19611 if (aidc->def == bind->definition) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019612 if ((aidc->bubbleDepth == -1) ||
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019613 (aidc->bubbleDepth >= vctxt->depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019614 bind = bind->next;
19615 goto start_binding;
19616 }
19617 break;
19618 }
19619 aidc = aidc->next;
19620 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019621
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019622 if (parTable != NULL)
19623 parBind = *parTable;
19624 while (parBind != NULL) {
19625 /*
19626 * Search a matching parent binding for the
19627 * IDC definition.
19628 */
19629 if (parBind->definition == bind->definition) {
19630
19631 /*
19632 * Compare every node-table entry of the child node,
19633 * i.e. the key-sequence within, ...
19634 */
19635 oldNum = parBind->nbNodes; /* Skip newly added items. */
19636 duplTop = oldNum + parBind->nbDupls;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019637 newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019638
19639 for (i = 0; i < bind->nbNodes; i++) {
19640 node = bind->nodeTable[i];
19641 if (node == NULL)
19642 continue;
19643 /*
19644 * ...with every key-sequence of the parent node, already
19645 * evaluated to be a duplicate key-sequence.
19646 */
19647 if (parBind->nbDupls != 0) {
19648 j = bind->nbNodes + newDupls;
19649 while (j < duplTop) {
19650 parNode = parBind->nodeTable[j];
19651 for (k = 0; k < bind->definition->nbFields; k++) {
19652 key = node->keys[k];
19653 parKey = parNode->keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019654 ret = xmlSchemaAreValuesEqual(key->val,
19655 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019656 if (ret == -1) {
19657 /* TODO: Internal error */
19658 return(-1);
19659 } else if (ret == 0)
19660 break;
19661
19662 }
19663 if (ret == 1)
19664 /* Duplicate found. */
19665 break;
19666 j++;
19667 }
19668 if (j != duplTop) {
19669 /* Duplicate found. */
19670 continue;
19671 }
19672 }
19673 /*
19674 * ... and with every key-sequence of the parent node.
19675 */
19676 j = 0;
19677 while (j < oldNum) {
19678 parNode = parBind->nodeTable[j];
19679 /*
19680 * Compare key by key.
19681 */
19682 for (k = 0; k < parBind->definition->nbFields; k++) {
19683 key = node->keys[k];
19684 parKey = parNode->keys[k];
19685
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019686 ret = xmlSchemaAreValuesEqual(key->val,
19687 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019688 if (ret == -1) {
19689 /* TODO: Internal error */
19690 } else if (ret == 0)
19691 break;
19692
19693 }
19694 if (ret == 1)
19695 /*
19696 * The key-sequences are equal.
19697 */
19698 break;
19699 j++;
19700 }
19701 if (j != oldNum) {
19702 /*
19703 * Handle duplicates.
19704 */
19705 newDupls++;
19706 oldNum--;
19707 parBind->nbNodes--;
19708 /*
19709 * Move last old item to pos of duplicate.
19710 */
19711 parBind->nodeTable[j] =
19712 parBind->nodeTable[oldNum];
19713
19714 if (parBind->nbNodes != oldNum) {
19715 /*
19716 * If new items exist, move last new item to
19717 * last of old items.
19718 */
19719 parBind->nodeTable[oldNum] =
19720 parBind->nodeTable[parBind->nbNodes];
19721 }
19722 /*
19723 * Move duplicate to last pos of new/old items.
19724 */
19725 parBind->nodeTable[parBind->nbNodes] = parNode;
19726
19727 } else {
19728 /*
19729 * Add the node-table entry (node and key-sequence) of
19730 * the child node to the node table of the parent node.
19731 */
19732 if (parBind->nodeTable == NULL) {
19733 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019734 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019735 if (parBind->nodeTable == NULL) {
19736 xmlSchemaVErrMemory(NULL,
19737 "allocating IDC list of node-table items", NULL);
19738 return(-1);
19739 }
19740 parBind->sizeNodes = 1;
19741 } else if (duplTop >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019742 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019743 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19744 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
19745 sizeof(xmlSchemaPSVIIDCNodePtr));
19746 if (parBind->nodeTable == NULL) {
19747 xmlSchemaVErrMemory(NULL,
19748 "re-allocating IDC list of node-table items", NULL);
19749 return(-1);
19750 }
19751 }
19752
19753 /*
19754 * Move first old duplicate to last position
19755 * of old duplicates +1.
19756 */
19757 if (parBind->nbDupls != 0) {
19758 parBind->nodeTable[duplTop] =
19759 parBind->nodeTable[parBind->nbNodes + newDupls];
19760 }
19761 /*
19762 * Move first new duplicate to last position of
19763 * new duplicates +1.
19764 */
19765 if (newDupls != 0) {
19766 parBind->nodeTable[parBind->nbNodes + newDupls] =
19767 parBind->nodeTable[parBind->nbNodes];
19768 }
19769 /*
19770 * Append the new node-table entry to the 'new node-table
19771 * entries' section.
19772 */
19773 parBind->nodeTable[parBind->nbNodes] = node;
19774 parBind->nbNodes++;
19775 duplTop++;
19776 }
19777 }
19778 parBind->nbDupls += newDupls;
19779 break;
19780 }
19781 if (parBind->next == NULL)
19782 lastParBind = parBind;
19783 parBind = parBind->next;
19784 }
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019785 if ((parBind == NULL) && (bind->nbNodes != 0)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019786 /*
19787 * No binding for the IDC was found: create a new one and
19788 * copy all node-tables.
19789 */
19790 parBind = xmlSchemaIDCNewBinding(bind->definition);
19791 if (parBind == NULL)
19792 return(-1);
19793
19794 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19795 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
19796 if (parBind->nodeTable == NULL) {
19797 xmlSchemaVErrMemory(NULL,
19798 "allocating an array of IDC node-table items", NULL);
19799 xmlSchemaIDCFreeBinding(parBind);
19800 return(-1);
19801 }
19802 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019803 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019804 memcpy(parBind->nodeTable, bind->nodeTable,
19805 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019806 if (*parTable == NULL)
19807 *parTable = parBind;
19808 else
19809 lastParBind->next = parBind;
19810 }
19811 bind = bind->next;
19812 }
19813 return (0);
19814}
19815
19816/**
19817 * xmlSchemaCheckCVCIDCKeyRef:
19818 * @vctxt: the WXS validation context
19819 * @elemDecl: the element declaration
19820 *
19821 * Check the cvc-idc-keyref constraints.
19822 */
19823static int
19824xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
19825{
19826 xmlSchemaPSVIIDCBindingPtr refbind, bind;
19827
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019828 refbind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019829 /*
19830 * Find a keyref.
19831 */
19832 while (refbind != NULL) {
19833 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19834 int i, j, k, res;
19835 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
19836 xmlSchemaPSVIIDCKeyPtr refKey, key;
19837
19838 /*
19839 * Find the referred key/unique.
19840 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019841 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019842 do {
19843 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
19844 bind->definition)
19845 break;
19846 bind = bind->next;
19847 } while (bind != NULL);
19848
19849 /*
19850 * Search for a matching key-sequences.
19851 */
19852 for (i = 0; i < refbind->nbNodes; i++) {
19853 res = 0;
19854 if (bind != NULL) {
19855 refKeys = refbind->nodeTable[i]->keys;
19856 for (j = 0; j < bind->nbNodes; j++) {
19857 keys = bind->nodeTable[j]->keys;
19858 for (k = 0; k < bind->definition->nbFields; k++) {
19859 refKey = refKeys[k];
19860 key = keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019861 res = xmlSchemaAreValuesEqual(key->val,
19862 refKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019863 if (res == 0)
19864 break;
19865 else if (res == -1) {
19866 return (-1);
19867 }
19868 }
19869 if (res == 1) {
19870 /*
19871 * Match found.
19872 */
19873 break;
19874 }
19875 }
19876 }
19877 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019878 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019879 /* TODO: Report the key-sequence. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019880 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19881 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019882 (xmlSchemaTypePtr) refbind->definition,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019883 "No match found for key-sequence %s of key "
19884 "reference '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019885 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019886 refbind->nodeTable[i]->keys,
19887 refbind->definition->nbFields),
19888 xmlSchemaFormatQName(&strB,
19889 refbind->definition->targetNamespace,
19890 refbind->definition->name));
19891 FREE_AND_NULL(str);
19892 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019893 }
19894 }
19895 }
19896 refbind = refbind->next;
19897 }
19898 return (0);
19899}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019900
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019901/************************************************************************
19902 * *
19903 * XML Reader validation code *
19904 * *
19905 ************************************************************************/
19906
19907static xmlSchemaAttrInfoPtr
19908xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019909{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019910 xmlSchemaAttrInfoPtr iattr;
19911 /*
19912 * Grow/create list of attribute infos.
19913 */
19914 if (vctxt->attrInfos == NULL) {
19915 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
19916 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
19917 vctxt->sizeAttrInfos = 1;
19918 if (vctxt->attrInfos == NULL) {
19919 xmlSchemaVErrMemory(vctxt,
19920 "allocating attribute info list", NULL);
19921 return (NULL);
19922 }
19923 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
19924 vctxt->sizeAttrInfos++;
19925 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
19926 xmlRealloc(vctxt->attrInfos,
19927 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
19928 if (vctxt->attrInfos == NULL) {
19929 xmlSchemaVErrMemory(vctxt,
19930 "re-allocating attribute info list", NULL);
19931 return (NULL);
19932 }
19933 } else {
19934 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
19935 if (iattr->localName != NULL) {
19936 VERROR_INT("xmlSchemaGetFreshAttrInfo",
19937 "attr info not cleared");
19938 return (NULL);
19939 }
19940 iattr->nodeType = XML_ATTRIBUTE_NODE;
19941 return (iattr);
19942 }
19943 /*
19944 * Create an attribute info.
19945 */
19946 iattr = (xmlSchemaAttrInfoPtr)
19947 xmlMalloc(sizeof(xmlSchemaAttrInfo));
19948 if (iattr == NULL) {
19949 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
19950 return (NULL);
19951 }
19952 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
19953 iattr->nodeType = XML_ATTRIBUTE_NODE;
19954 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
19955
19956 return (iattr);
19957}
19958
19959static int
19960xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
19961 xmlNodePtr attrNode,
19962 const xmlChar *localName,
19963 const xmlChar *nsName,
19964 int ownedNames,
19965 xmlChar *value,
19966 int ownedValue)
19967{
19968 xmlSchemaAttrInfoPtr attr;
19969
19970 attr = xmlSchemaGetFreshAttrInfo(vctxt);
19971 if (attr == NULL) {
19972 VERROR_INT("xmlSchemaPushAttribute",
19973 "calling xmlSchemaGetFreshAttrInfo()");
19974 return (-1);
19975 }
19976 attr->node = attrNode;
19977 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
19978 attr->localName = localName;
19979 attr->nsName = nsName;
19980 if (ownedNames)
19981 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
19982 /*
19983 * Evaluate if it's an XSI attribute.
19984 */
19985 if (nsName != NULL) {
19986 if (xmlStrEqual(localName, BAD_CAST "nil")) {
19987 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
19988 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
19989 }
19990 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
19991 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
19992 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
19993 }
19994 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
19995 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
19996 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
19997 }
19998 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
19999 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20000 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
20001 }
20002 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
20003 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
20004 }
20005 }
20006 attr->value = value;
20007 if (ownedValue)
20008 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
20009 if (attr->metaType != 0)
20010 attr->state = XML_SCHEMAS_ATTR_META;
20011 return (0);
20012}
20013
20014static void
20015xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
20016{
20017 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
20018 FREE_AND_NULL(ielem->localName);
20019 FREE_AND_NULL(ielem->nsName);
20020 } else {
20021 ielem->localName = NULL;
20022 ielem->nsName = NULL;
20023 }
20024 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
20025 FREE_AND_NULL(ielem->value);
20026 } else {
20027 ielem->value = NULL;
20028 }
20029 if (ielem->val != NULL) {
20030 xmlSchemaFreeValue(ielem->val);
20031 ielem->val = NULL;
20032 }
20033 if (ielem->idcMatchers != NULL) {
20034 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
20035 ielem->idcMatchers = NULL;
20036 }
20037 if (ielem->idcTable != NULL) {
20038 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
20039 ielem->idcTable = NULL;
20040 }
20041 if (ielem->regexCtxt != NULL) {
20042 xmlRegFreeExecCtxt(ielem->regexCtxt);
20043 ielem->regexCtxt = NULL;
20044 }
20045 if (ielem->nsBindings != NULL) {
20046 xmlFree((xmlChar **)ielem->nsBindings);
20047 ielem->nsBindings = NULL;
20048 ielem->nbNsBindings = 0;
20049 ielem->sizeNsBindings = 0;
20050 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020051}
20052
20053/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020054 * xmlSchemaGetFreshElemInfo:
20055 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020056 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020057 * Creates/reuses and initializes the element info item for
20058 * the currect tree depth.
20059 *
20060 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020061 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020062static xmlSchemaNodeInfoPtr
20063xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020064{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020065 xmlSchemaNodeInfoPtr info = NULL;
20066
20067 if (vctxt->depth > vctxt->sizeElemInfos) {
20068 VERROR_INT("xmlSchemaGetFreshElemInfo",
20069 "inconsistent depth encountered");
20070 return (NULL);
20071 }
20072 if (vctxt->elemInfos == NULL) {
20073 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20074 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
20075 if (vctxt->elemInfos == NULL) {
20076 xmlSchemaVErrMemory(vctxt,
20077 "allocating the element info array", NULL);
20078 return (NULL);
20079 }
20080 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
20081 vctxt->sizeElemInfos = 10;
20082 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
20083 int i = vctxt->sizeElemInfos;
20084
20085 vctxt->sizeElemInfos *= 2;
20086 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20087 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
20088 sizeof(xmlSchemaNodeInfoPtr));
20089 if (vctxt->elemInfos == NULL) {
20090 xmlSchemaVErrMemory(vctxt,
20091 "re-allocating the element info array", NULL);
20092 return (NULL);
20093 }
20094 /*
20095 * We need the new memory to be NULLed.
20096 * TODO: Use memset instead?
20097 */
20098 for (; i < vctxt->sizeElemInfos; i++)
20099 vctxt->elemInfos[i] = NULL;
20100 } else
20101 info = vctxt->elemInfos[vctxt->depth];
20102
20103 if (info == NULL) {
20104 info = (xmlSchemaNodeInfoPtr)
20105 xmlMalloc(sizeof(xmlSchemaNodeInfo));
20106 if (info == NULL) {
20107 xmlSchemaVErrMemory(vctxt,
20108 "allocating an element info", NULL);
20109 return (NULL);
20110 }
20111 vctxt->elemInfos[vctxt->depth] = info;
20112 } else {
20113 if (info->localName != NULL) {
20114 VERROR_INT("xmlSchemaGetFreshElemInfo",
20115 "elem info has not been cleared");
20116 return (NULL);
20117 }
20118 }
20119 memset(info, 0, sizeof(xmlSchemaNodeInfo));
20120 info->nodeType = XML_ELEMENT_NODE;
20121 info->depth = vctxt->depth;
20122
20123 return (info);
20124}
20125
20126#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
20127#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
20128#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
20129
20130static int
20131xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
20132 xmlNodePtr node,
20133 xmlSchemaTypePtr type,
20134 xmlSchemaValType valType,
20135 const xmlChar * value,
20136 xmlSchemaValPtr val,
20137 unsigned long length,
20138 int fireErrors)
20139{
20140 int ret, error = 0;
20141
20142 xmlSchemaTypePtr tmpType;
20143 xmlSchemaFacetLinkPtr facetLink;
20144 xmlSchemaFacetPtr facet;
20145 unsigned long len = 0;
20146 xmlSchemaWhitespaceValueType ws;
20147
20148 /*
20149 * In Libxml2, derived built-in types have currently no explicit facets.
20150 */
20151 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020152 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020153
20154 /*
20155 * NOTE: Do not jump away, if the facetSet of the given type is
20156 * empty: until now, "pattern" and "enumeration" facets of the
20157 * *base types* need to be checked as well.
20158 */
20159 if (type->facetSet == NULL)
20160 goto pattern_and_enum;
20161
20162 if (! VARIETY_ATOMIC(type)) {
20163 if (VARIETY_LIST(type))
20164 goto variety_list;
20165 else
20166 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020167 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020168 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020169 * Whitespace handling is only of importance for string-based
20170 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020171 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020172 tmpType = xmlSchemaGetPrimitiveType(type);
20173 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
20174 IS_ANY_SIMPLE_TYPE(tmpType)) {
20175 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20176 } else
20177 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
20178 /*
20179 * If the value was not computed (for string or
20180 * anySimpleType based types), then use the provided
20181 * type.
20182 */
20183 if (val == NULL)
20184 valType = valType;
20185 else
20186 valType = xmlSchemaGetValType(val);
20187
20188 ret = 0;
20189 for (facetLink = type->facetSet; facetLink != NULL;
20190 facetLink = facetLink->next) {
20191 /*
20192 * Skip the pattern "whiteSpace": it is used to
20193 * format the character content beforehand.
20194 */
20195 switch (facetLink->facet->type) {
20196 case XML_SCHEMA_FACET_WHITESPACE:
20197 case XML_SCHEMA_FACET_PATTERN:
20198 case XML_SCHEMA_FACET_ENUMERATION:
20199 continue;
20200 case XML_SCHEMA_FACET_LENGTH:
20201 case XML_SCHEMA_FACET_MINLENGTH:
20202 case XML_SCHEMA_FACET_MAXLENGTH:
20203 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
20204 valType, value, val, &len, ws);
20205 break;
20206 default:
20207 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
20208 valType, value, val, ws);
20209 break;
20210 }
20211 if (ret < 0) {
20212 AERROR_INT("xmlSchemaValidateFacets",
20213 "validating against a atomic type facet");
20214 return (-1);
20215 } else if (ret > 0) {
20216 if (fireErrors)
20217 xmlSchemaFacetErr(actxt, ret, node,
20218 value, len, type, facetLink->facet, NULL, NULL, NULL);
20219 else
20220 return (ret);
20221 if (error == 0)
20222 error = ret;
20223 }
20224 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020225 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020226
20227variety_list:
20228 if (! VARIETY_LIST(type))
20229 goto pattern_and_enum;
20230 /*
20231 * "length", "minLength" and "maxLength" of list types.
20232 */
20233 ret = 0;
20234 for (facetLink = type->facetSet; facetLink != NULL;
20235 facetLink = facetLink->next) {
20236
20237 switch (facetLink->facet->type) {
20238 case XML_SCHEMA_FACET_LENGTH:
20239 case XML_SCHEMA_FACET_MINLENGTH:
20240 case XML_SCHEMA_FACET_MAXLENGTH:
20241 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
20242 value, length, NULL);
20243 break;
20244 default:
20245 continue;
20246 }
20247 if (ret < 0) {
20248 AERROR_INT("xmlSchemaValidateFacets",
20249 "validating against a list type facet");
20250 return (-1);
20251 } else if (ret > 0) {
20252 if (fireErrors)
20253 xmlSchemaFacetErr(actxt, ret, node,
20254 value, length, type, facetLink->facet, NULL, NULL, NULL);
20255 else
20256 return (ret);
20257 if (error == 0)
20258 error = ret;
20259 }
20260 ret = 0;
20261 }
20262
20263pattern_and_enum:
20264 if (error >= 0) {
20265 int found = 0;
20266 /*
20267 * Process enumerations. Facet values are in the value space
20268 * of the defining type's base type. This seems to be a bug in the
20269 * XML Schema 1.0 spec. Use the whitespace type of the base type.
20270 * Only the first set of enumerations in the ancestor-or-self axis
20271 * is used for validation.
20272 */
20273 ret = 0;
20274 tmpType = type;
20275 do {
20276 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
20277 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
20278 continue;
20279 found = 1;
20280 ret = xmlSchemaAreValuesEqual(facet->val, val);
20281 if (ret == 1)
20282 break;
20283 else if (ret < 0) {
20284 AERROR_INT("xmlSchemaValidateFacets",
20285 "validating against an enumeration facet");
20286 return (-1);
20287 }
20288 }
20289 if (ret != 0)
20290 break;
20291 tmpType = tmpType->baseType;
20292 } while ((tmpType != NULL) &&
20293 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20294 if (found && (ret == 0)) {
20295 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
20296 if (fireErrors) {
20297 xmlSchemaFacetErr(actxt, ret, node,
20298 value, 0, type, NULL, NULL, NULL, NULL);
20299 } else
20300 return (ret);
20301 if (error == 0)
20302 error = ret;
20303 }
20304 }
20305
20306 if (error >= 0) {
20307 int found;
20308 /*
20309 * Process patters. Pattern facets are ORed at type level
20310 * and ANDed if derived. Walk the base type axis.
20311 */
20312 tmpType = type;
20313 facet = NULL;
20314 do {
20315 found = 0;
20316 for (facetLink = tmpType->facetSet; facetLink != NULL;
20317 facetLink = facetLink->next) {
20318 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
20319 continue;
20320 found = 1;
20321 /*
20322 * NOTE that for patterns, @value needs to be the
20323 * normalized vaule.
20324 */
20325 ret = xmlRegexpExec(facetLink->facet->regexp, value);
20326 if (ret == 1)
20327 break;
20328 else if (ret < 0) {
20329 AERROR_INT("xmlSchemaValidateFacets",
20330 "validating against a pattern facet");
20331 return (-1);
20332 } else {
20333 /*
20334 * Save the last non-validating facet.
20335 */
20336 facet = facetLink->facet;
20337 }
20338 }
20339 if (found && (ret != 1)) {
20340 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
20341 if (fireErrors) {
20342 xmlSchemaFacetErr(actxt, ret, node,
20343 value, 0, type, facet, NULL, NULL, NULL);
20344 } else
20345 return (ret);
20346 if (error == 0)
20347 error = ret;
20348 break;
20349 }
20350 tmpType = tmpType->baseType;
20351 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20352 }
20353
20354 return (error);
20355}
20356
20357static xmlChar *
20358xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
20359 const xmlChar *value)
20360{
20361 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
20362 case XML_SCHEMA_WHITESPACE_COLLAPSE:
20363 return (xmlSchemaCollapseString(value));
20364 case XML_SCHEMA_WHITESPACE_REPLACE:
20365 return (xmlSchemaWhiteSpaceReplace(value));
20366 default:
20367 return (NULL);
20368 }
20369}
20370
20371static int
20372xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
20373 const xmlChar *value,
20374 xmlSchemaValPtr *val,
20375 int valNeeded)
20376{
20377 int ret;
20378 const xmlChar *nsName;
20379 xmlChar *local, *prefix = NULL;
20380
20381 ret = xmlValidateQName(value, 1);
20382 if (ret != 0) {
20383 if (ret == -1) {
20384 VERROR_INT("xmlSchemaValidateQName",
20385 "calling xmlValidateQName()");
20386 return (-1);
20387 }
20388 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
20389 }
20390 /*
20391 * NOTE: xmlSplitQName2 will always return a duplicated
20392 * strings.
20393 */
20394 local = xmlSplitQName2(value, &prefix);
20395 if (local == NULL)
20396 local = xmlStrdup(value);
20397 /*
20398 * OPTIMIZE TODO: Use flags for:
20399 * - is there any namespace binding?
20400 * - is there a default namespace?
20401 */
20402 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20403
20404 if (prefix != NULL) {
20405 xmlFree(prefix);
20406 /*
20407 * A namespace must be found if the prefix is
20408 * NOT NULL.
20409 */
20410 if (nsName == NULL) {
20411 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20412 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, ret, NULL,
20413 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20414 "The QName value '%s' has no "
20415 "corresponding namespace declaration in "
20416 "scope", value, NULL);
20417 if (local != NULL)
20418 xmlFree(local);
20419 return (ret);
20420 }
20421 }
20422 if (valNeeded && val) {
20423 if (nsName != NULL)
20424 *val = xmlSchemaNewQNameValue(
20425 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
20426 else
20427 *val = xmlSchemaNewQNameValue(NULL,
20428 BAD_CAST local);
20429 } else
20430 xmlFree(local);
20431 return (0);
20432}
20433
20434/*
20435* cvc-simple-type
20436*/
20437static int
20438xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
20439 xmlNodePtr node,
20440 xmlSchemaTypePtr type,
20441 const xmlChar *value,
20442 xmlSchemaValPtr *retVal,
20443 int fireErrors,
20444 int normalize,
20445 int isNormalized)
20446{
20447 int ret = 0, valNeeded = (retVal) ? 1 : 0;
20448 xmlSchemaValPtr val = NULL;
20449 xmlSchemaWhitespaceValueType ws;
20450 xmlChar *normValue = NULL;
20451
20452#define NORMALIZE(atype) \
20453 if ((! isNormalized) && \
20454 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
20455 normValue = xmlSchemaNormalizeValue(atype, value); \
20456 if (normValue != NULL) \
20457 value = normValue; \
20458 isNormalized = 1; \
20459 }
20460
20461 if ((retVal != NULL) && (*retVal != NULL)) {
20462 xmlSchemaFreeValue(*retVal);
20463 *retVal = NULL;
20464 }
20465 /*
20466 * 3.14.4 Simple Type Definition Validation Rules
20467 * Validation Rule: String Valid
20468 */
20469 /*
20470 * 1 It is schema-valid with respect to that definition as defined
20471 * by Datatype Valid in [XML Schemas: Datatypes].
20472 */
20473 /*
20474 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
20475 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
20476 * the string must be a ·declared entity name·.
20477 */
20478 /*
20479 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
20480 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
20481 * then every whitespace-delimited substring of the string must be a ·declared
20482 * entity name·.
20483 */
20484 /*
20485 * 2.3 otherwise no further condition applies.
20486 */
20487 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
20488 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000020489 if (value == NULL)
20490 value = BAD_CAST "";
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020491 if (IS_ANY_SIMPLE_TYPE(type) || VARIETY_ATOMIC(type)) {
20492 xmlSchemaTypePtr biType; /* The built-in type. */
20493 /*
20494 * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match·
20495 * a literal in the ·lexical space· of {base type definition}"
20496 */
20497 /*
20498 * Whitespace-normalize.
20499 */
20500 NORMALIZE(type);
20501 if (type->type != XML_SCHEMA_TYPE_BASIC) {
20502 /*
20503 * Get the built-in type.
20504 */
20505 biType = type->baseType;
20506 while ((biType != NULL) &&
20507 (biType->type != XML_SCHEMA_TYPE_BASIC))
20508 biType = biType->baseType;
20509
20510 if (biType == NULL) {
20511 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20512 "could not get the built-in type");
20513 goto internal_error;
20514 }
20515 } else
20516 biType = type;
20517 /*
20518 * NOTATIONs need to be processed here, since they need
20519 * to lookup in the hashtable of NOTATION declarations of the schema.
20520 */
20521 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
20522 switch (biType->builtInType) {
20523 case XML_SCHEMAS_NOTATION:
20524 ret = xmlSchemaValidateNotation(
20525 (xmlSchemaValidCtxtPtr) actxt,
20526 ((xmlSchemaValidCtxtPtr) actxt)->schema,
20527 NULL, value, &val, valNeeded);
20528 break;
20529 case XML_SCHEMAS_QNAME:
20530 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
20531 value, &val, valNeeded);
20532 break;
20533 default:
20534 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20535 if (valNeeded)
20536 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20537 value, &val, NULL);
20538 else
20539 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20540 value, NULL, NULL);
20541 break;
20542 }
20543 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
20544 switch (biType->builtInType) {
20545 case XML_SCHEMAS_NOTATION:
20546 ret = xmlSchemaValidateNotation(NULL,
20547 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
20548 value, &val, valNeeded);
20549 break;
20550 default:
20551 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20552 if (valNeeded)
20553 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20554 value, &val, node);
20555 else
20556 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20557 value, NULL, node);
20558 break;
20559 }
20560 } else {
20561 /*
20562 * Validation via a public API is not implemented yet.
20563 */
20564 TODO
20565 goto internal_error;
20566 }
20567 if (ret != 0) {
20568 if (ret < 0) {
20569 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20570 "validating against a built-in type");
20571 goto internal_error;
20572 }
20573 if (VARIETY_LIST(type))
20574 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20575 else
20576 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20577 }
20578 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20579 /*
20580 * Check facets.
20581 */
20582 ret = xmlSchemaValidateFacets(actxt, node, type,
20583 (xmlSchemaValType) biType->builtInType, value, val,
20584 0, fireErrors);
20585 if (ret != 0) {
20586 if (ret < 0) {
20587 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20588 "validating facets of atomic simple type");
20589 goto internal_error;
20590 }
20591 if (VARIETY_LIST(type))
20592 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20593 else
20594 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20595 }
20596 }
20597 if (fireErrors && (ret > 0))
20598 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20599 } else if (VARIETY_LIST(type)) {
20600
20601 xmlSchemaTypePtr itemType;
20602 const xmlChar *cur, *end;
20603 xmlChar *tmpValue = NULL;
20604 unsigned long len = 0;
20605 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
20606 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
20607 * of white space separated tokens, each of which ·match·es a literal
20608 * in the ·lexical space· of {item type definition}
20609 */
20610 /*
20611 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
20612 * the list type has an enum or pattern facet.
20613 */
20614 NORMALIZE(type);
20615 /*
20616 * VAL TODO: Optimize validation of empty values.
20617 * VAL TODO: We do not have computed values for lists.
20618 */
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000020619 itemType = GET_LIST_ITEM_TYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020620 cur = value;
20621 do {
20622 while (IS_BLANK_CH(*cur))
20623 cur++;
20624 end = cur;
20625 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
20626 end++;
20627 if (end == cur)
20628 break;
20629 tmpValue = xmlStrndup(cur, end - cur);
20630 len++;
20631
20632 if (valNeeded)
20633 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20634 tmpValue, &curVal, fireErrors, 0, 1);
20635 else
20636 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20637 tmpValue, NULL, fireErrors, 0, 1);
20638 FREE_AND_NULL(tmpValue);
20639 if (curVal != NULL) {
20640 /*
20641 * Add to list of computed values.
20642 */
20643 if (val == NULL)
20644 val = curVal;
20645 else
20646 xmlSchemaValueAppend(prevVal, curVal);
20647 prevVal = curVal;
20648 curVal = NULL;
20649 }
20650 if (ret != 0) {
20651 if (ret < 0) {
20652 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20653 "validating an item of list simple type");
20654 goto internal_error;
20655 }
20656 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20657 break;
20658 }
20659 cur = end;
20660 } while (*cur != 0);
20661 FREE_AND_NULL(tmpValue);
20662 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20663 /*
20664 * Apply facets (pattern, enumeration).
20665 */
20666 ret = xmlSchemaValidateFacets(actxt, node, type,
20667 XML_SCHEMAS_UNKNOWN, value, val,
20668 len, fireErrors);
20669 if (ret != 0) {
20670 if (ret < 0) {
20671 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20672 "validating facets of list simple type");
20673 goto internal_error;
20674 }
20675 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20676 }
20677 }
20678 if (fireErrors && (ret > 0)) {
20679 /*
20680 * Report the normalized value.
20681 */
20682 normalize = 1;
20683 NORMALIZE(type);
20684 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20685 }
20686 } else if (VARIETY_UNION(type)) {
20687 xmlSchemaTypeLinkPtr memberLink;
20688 /*
20689 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
20690 * not apply directly; however, the normalization behavior of ·union·
20691 * types is controlled by the value of whiteSpace on that one of the
20692 * ·memberTypes· against which the ·union· is successfully validated.
20693 *
20694 * This means that the value is normalized by the first validating
20695 * member type, then the facets of the union type are applied. This
20696 * needs changing of the value!
20697 */
20698
20699 /*
20700 * 1.2.3 if {variety} is ·union· then the string must ·match· a
20701 * literal in the ·lexical space· of at least one member of
20702 * {member type definitions}
20703 */
20704 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
20705 if (memberLink == NULL) {
20706 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20707 "union simple type has no member types");
20708 goto internal_error;
20709 }
20710 /*
20711 * Always normalize union type values, since we currently
20712 * cannot store the whitespace information with the value
20713 * itself; otherwise a later value-comparison would be
20714 * not possible.
20715 */
20716 while (memberLink != NULL) {
20717 if (valNeeded)
20718 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20719 memberLink->type, value, &val, 0, 1, 0);
20720 else
20721 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20722 memberLink->type, value, NULL, 0, 1, 0);
20723 if (ret <= 0)
20724 break;
20725 memberLink = memberLink->next;
20726 }
20727 if (ret != 0) {
20728 if (ret < 0) {
20729 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20730 "validating members of union simple type");
20731 goto internal_error;
20732 }
20733 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20734 }
20735 /*
20736 * Apply facets (pattern, enumeration).
20737 */
20738 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20739 /*
20740 * The normalization behavior of ·union· types is controlled by
20741 * the value of whiteSpace on that one of the ·memberTypes·
20742 * against which the ·union· is successfully validated.
20743 */
20744 NORMALIZE(memberLink->type);
20745 ret = xmlSchemaValidateFacets(actxt, node, type,
20746 XML_SCHEMAS_UNKNOWN, value, val,
20747 0, fireErrors);
20748 if (ret != 0) {
20749 if (ret < 0) {
20750 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20751 "validating facets of union simple type");
20752 goto internal_error;
20753 }
20754 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20755 }
20756 }
20757 if (fireErrors && (ret > 0))
20758 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20759 }
20760
20761 if (normValue != NULL)
20762 xmlFree(normValue);
20763 if (ret == 0) {
20764 if (retVal != NULL)
20765 *retVal = val;
20766 else if (val != NULL)
20767 xmlSchemaFreeValue(val);
20768 } else if (val != NULL)
20769 xmlSchemaFreeValue(val);
20770 return (ret);
20771internal_error:
20772 if (normValue != NULL)
20773 xmlFree(normValue);
20774 if (val != NULL)
20775 xmlSchemaFreeValue(val);
20776 return (-1);
20777}
20778
20779static int
20780xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
20781 const xmlChar *value,
20782 const xmlChar **nsName,
20783 const xmlChar **localName)
20784{
20785 int ret = 0;
20786
20787 if ((nsName == NULL) || (localName == NULL))
20788 return (-1);
20789 *nsName = NULL;
20790 *localName = NULL;
20791
20792 ret = xmlValidateQName(value, 1);
20793 if (ret == -1)
20794 return (-1);
20795 if (ret > 0) {
20796 xmlSchemaSimpleTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
20797 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20798 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
20799 return (1);
20800 }
20801 {
20802 xmlChar *local = NULL;
20803 xmlChar *prefix;
20804
20805 /*
20806 * NOTE: xmlSplitQName2 will return a duplicated
20807 * string.
20808 */
20809 local = xmlSplitQName2(value, &prefix);
20810 VAL_CREATE_DICT;
20811 if (local == NULL)
20812 *localName = xmlDictLookup(vctxt->dict, value, -1);
20813 else {
20814 *localName = xmlDictLookup(vctxt->dict, local, -1);
20815 xmlFree(local);
20816 }
20817
20818 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20819
20820 if (prefix != NULL) {
20821 xmlFree(prefix);
20822 /*
20823 * A namespace must be found if the prefix is NOT NULL.
20824 */
20825 if (*nsName == NULL) {
20826 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20827 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20828 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20829 "The QName value '%s' has no "
20830 "corresponding namespace declaration in scope",
20831 value, NULL);
20832 return (2);
20833 }
20834 }
20835 }
20836 return (0);
20837}
20838
20839static int
20840xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
20841 xmlSchemaAttrInfoPtr iattr,
20842 xmlSchemaTypePtr *localType,
20843 xmlSchemaElementPtr elemDecl)
20844{
20845 int ret = 0;
20846 /*
20847 * cvc-elt (3.3.4) : (4)
20848 * AND
20849 * Schema-Validity Assessment (Element) (cvc-assess-elt)
20850 * (1.2.1.2.1) - (1.2.1.2.4)
20851 * Handle 'xsi:type'.
20852 */
20853 if (localType == NULL)
20854 return (-1);
20855 *localType = NULL;
20856 if (iattr == NULL)
20857 return (0);
20858 else {
20859 const xmlChar *nsName = NULL, *local = NULL;
20860 /*
20861 * TODO: We should report a *warning* that the type was overriden
20862 * by the instance.
20863 */
20864 ACTIVATE_ATTRIBUTE(iattr);
20865 /*
20866 * (cvc-elt) (3.3.4) : (4.1)
20867 * (cvc-assess-elt) (1.2.1.2.2)
20868 */
20869 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
20870 &nsName, &local);
20871 if (ret != 0) {
20872 if (ret < 0) {
20873 VERROR_INT("xmlSchemaValidateElementByDeclaration",
20874 "calling xmlSchemaQNameExpand() to validate the "
20875 "attribute 'xsi:type'");
20876 goto internal_error;
20877 }
20878 goto exit;
20879 }
20880 /*
20881 * (cvc-elt) (3.3.4) : (4.2)
20882 * (cvc-assess-elt) (1.2.1.2.3)
20883 */
20884 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
20885 if (*localType == NULL) {
20886 xmlChar *str = NULL;
20887
20888 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20889 XML_SCHEMAV_CVC_ELT_4_2, NULL,
20890 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20891 "The QName value '%s' of the xsi:type attribute does not "
20892 "resolve to a type definition",
20893 xmlSchemaFormatQName(&str, nsName, local), NULL);
20894 FREE_AND_NULL(str);
20895 ret = vctxt->err;
20896 goto exit;
20897 }
20898 if (elemDecl != NULL) {
20899 int set = 0;
20900
20901 /*
20902 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
20903 * "The ·local type definition· must be validly
20904 * derived from the {type definition} given the union of
20905 * the {disallowed substitutions} and the {type definition}'s
20906 * {prohibited substitutions}, as defined in
20907 * Type Derivation OK (Complex) (§3.4.6)
20908 * (if it is a complex type definition),
20909 * or given {disallowed substitutions} as defined in Type
20910 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
20911 * definition)."
20912 *
20913 * {disallowed substitutions}: the "block" on the element decl.
20914 * {prohibited substitutions}: the "block" on the type def.
20915 */
20916 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
20917 (elemDecl->subtypes->flags &
20918 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
20919 set |= SUBSET_EXTENSION;
20920
20921 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
20922 (elemDecl->subtypes->flags &
20923 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
20924 set |= SUBSET_RESTRICTION;
20925
20926 if (xmlSchemaCheckCOSDerivedOK(*localType,
20927 elemDecl->subtypes, set) != 0) {
20928 xmlChar *str = NULL;
20929
20930 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20931 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
20932 "The type definition '%s', specified by xsi:type, is "
20933 "blocked or not validly derived from the type definition "
20934 "of the element declaration",
20935 xmlSchemaFormatQName(&str,
20936 (*localType)->targetNamespace,
20937 (*localType)->name),
20938 NULL);
20939 FREE_AND_NULL(str);
20940 ret = vctxt->err;
20941 *localType = NULL;
20942 }
20943 }
20944 }
20945exit:
20946 ACTIVATE_ELEM;
20947 return (ret);
20948internal_error:
20949 ACTIVATE_ELEM;
20950 return (-1);
20951}
20952
20953static int
20954xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
20955{
20956 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
20957 xmlSchemaTypePtr actualType = ELEM_TYPE(elemDecl);
20958
20959 /*
20960 * cvc-elt (3.3.4) : 1
20961 */
20962 if (elemDecl == NULL) {
20963 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
20964 "No matching declaration available");
20965 return (vctxt->err);
20966 }
20967 /*
20968 * cvc-elt (3.3.4) : 2
20969 */
20970 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
20971 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
20972 "The element declaration is abstract");
20973 return (vctxt->err);
20974 }
20975 if (actualType == NULL) {
20976 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
20977 "The type definition is absent");
20978 return (XML_SCHEMAV_CVC_TYPE_1);
20979 }
20980 if (vctxt->nbAttrInfos != 0) {
20981 int ret;
20982 xmlSchemaAttrInfoPtr iattr;
20983 /*
20984 * cvc-elt (3.3.4) : 3
20985 * Handle 'xsi:nil'.
20986 */
20987 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
20988 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
20989 if (iattr) {
20990 ACTIVATE_ATTRIBUTE(iattr);
20991 /*
20992 * Validate the value.
20993 */
20994 ret = xmlSchemaVCheckCVCSimpleType(
20995 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
20996 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
20997 iattr->value, &(iattr->val), 1, 0, 0);
20998 ACTIVATE_ELEM;
20999 if (ret < 0) {
21000 VERROR_INT("xmlSchemaValidateElemDecl",
21001 "calling xmlSchemaVCheckCVCSimpleType() to "
21002 "validate the attribute 'xsi:nil'");
21003 return (-1);
21004 }
21005 if (ret == 0) {
21006 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
21007 /*
21008 * cvc-elt (3.3.4) : 3.1
21009 */
21010 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
21011 "The element is not 'nillable'");
21012 /* Does not return an error on purpose. */
21013 } else {
21014 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
21015 /*
21016 * cvc-elt (3.3.4) : 3.2.2
21017 */
21018 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
21019 (elemDecl->value != NULL)) {
21020 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
21021 "The element cannot be 'nilled' because "
21022 "there is a fixed value constraint defined "
21023 "for it");
21024 /* Does not return an error on purpose. */
21025 } else
21026 vctxt->inode->flags |=
21027 XML_SCHEMA_ELEM_INFO_NILLED;
21028 }
21029 }
21030 }
21031 }
21032 /*
21033 * cvc-elt (3.3.4) : 4
21034 * Handle 'xsi:type'.
21035 */
21036 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21037 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21038 if (iattr) {
21039 xmlSchemaTypePtr localType = NULL;
21040
21041 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
21042 elemDecl);
21043 if (ret != 0) {
21044 if (ret == -1) {
21045 VERROR_INT("xmlSchemaValidateElemDecl",
21046 "calling xmlSchemaProcessXSIType() to "
21047 "process the attribute 'xsi:type'");
21048 return (-1);
21049 }
21050 /* Does not return an error on purpose. */
21051 }
21052 if (localType != NULL) {
21053 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
21054 actualType = localType;
21055 }
21056 }
21057 }
21058 /*
21059 * IDC: Register identity-constraint XPath matchers.
21060 */
21061 if ((elemDecl->idcs != NULL) &&
21062 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
21063 return (-1);
21064 /*
21065 * No actual type definition.
21066 */
21067 if (actualType == NULL) {
21068 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21069 "The type definition is absent");
21070 return (XML_SCHEMAV_CVC_TYPE_1);
21071 }
21072 /*
21073 * Remember the actual type definition.
21074 */
21075 vctxt->inode->typeDef = actualType;
21076
21077 return (0);
21078}
21079
21080static int
21081xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
21082{
21083 xmlSchemaAttrInfoPtr iattr;
21084 int ret = 0, i;
21085
21086 /*
21087 * SPEC cvc-type (3.1.1)
21088 * "The attributes of must be empty, excepting those whose namespace
21089 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
21090 * whose local name is one of type, nil, schemaLocation or
21091 * noNamespaceSchemaLocation."
21092 */
21093 if (vctxt->nbAttrInfos == 0)
21094 return (0);
21095 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21096 iattr = vctxt->attrInfos[i];
21097 if (! iattr->metaType) {
21098 ACTIVATE_ATTRIBUTE(iattr)
21099 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21100 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
21101 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
21102 }
21103 }
21104 ACTIVATE_ELEM
21105 return (ret);
21106}
21107
21108/*
21109* Cleanup currently used attribute infos.
21110*/
21111static void
21112xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
21113{
21114 int i;
21115 xmlSchemaAttrInfoPtr attr;
21116
21117 if (vctxt->nbAttrInfos == 0)
21118 return;
21119 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21120 attr = vctxt->attrInfos[i];
21121 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
21122 if (attr->localName != NULL)
21123 xmlFree((xmlChar *) attr->localName);
21124 if (attr->nsName != NULL)
21125 xmlFree((xmlChar *) attr->nsName);
21126 }
21127 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
21128 if (attr->value != NULL)
21129 xmlFree((xmlChar *) attr->value);
21130 }
21131 if (attr->val != NULL) {
21132 xmlSchemaFreeValue(attr->val);
21133 attr->val = NULL;
21134 }
21135 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
21136 }
21137 vctxt->nbAttrInfos = 0;
21138}
21139
21140/*
21141* 3.4.4 Complex Type Definition Validation Rules
21142* Element Locally Valid (Complex Type) (cvc-complex-type)
21143* 3.2.4 Attribute Declaration Validation Rules
21144* Validation Rule: Attribute Locally Valid (cvc-attribute)
21145* Attribute Locally Valid (Use) (cvc-au)
21146*
21147* Only "assessed" attribute information items will be visible to
21148* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
21149*/
21150static int
21151xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
21152{
21153 xmlSchemaTypePtr type = vctxt->inode->typeDef;
21154 xmlSchemaAttributeLinkPtr attrUseLink;
21155 xmlSchemaAttributePtr attrUse = NULL, attrDecl = NULL;
21156 xmlSchemaAttrInfoPtr attr, tmpAttr;
21157 int i, found, nbAttrs;
21158 int xpathRes = 0, res, wildIDs = 0, fixed;
21159
21160 /*
21161 * SPEC (cvc-attribute)
21162 * (1) "The declaration must not be ·absent· (see Missing
21163 * Sub-components (§5.3) for how this can fail to be
21164 * the case)."
21165 * (2) "Its {type definition} must not be absent."
21166 *
21167 * NOTE (1) + (2): This is not handled here, since we currently do not
21168 * allow validation against schemas which have missing sub-components.
21169 *
21170 * SPEC (cvc-complex-type)
21171 * (3) "For each attribute information item in the element information
21172 * item's [attributes] excepting those whose [namespace name] is
21173 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
21174 * [local name] is one of type, nil, schemaLocation or
21175 * noNamespaceSchemaLocation, the appropriate case among the following
21176 * must be true:
21177 *
21178 */
21179 nbAttrs = vctxt->nbAttrInfos;
21180 for (attrUseLink = type->attributeUses; attrUseLink != NULL;
21181 attrUseLink = attrUseLink->next) {
21182
21183 found = 0;
21184 attrUse = attrUseLink->attr;
21185 /*
21186 * VAL TODO: Implement a real "attribute use" component.
21187 */
21188 if (attrUse->refDecl != NULL)
21189 attrDecl = attrUse->refDecl;
21190 else
21191 attrDecl = attrUse;
21192 for (i = 0; i < nbAttrs; i++) {
21193 attr = vctxt->attrInfos[i];
21194 /*
21195 * SPEC (cvc-complex-type) (3)
21196 * Skip meta attributes.
21197 */
21198 if (attr->metaType)
21199 continue;
21200 if (attr->localName[0] != attrDecl->name[0])
21201 continue;
21202 if (!xmlStrEqual(attr->localName, attrDecl->name))
21203 continue;
21204 if (!xmlStrEqual(attr->nsName, attrDecl->targetNamespace))
21205 continue;
21206 found = 1;
21207 /*
21208 * SPEC (cvc-complex-type)
21209 * (3.1) "If there is among the {attribute uses} an attribute
21210 * use with an {attribute declaration} whose {name} matches
21211 * the attribute information item's [local name] and whose
21212 * {target namespace} is identical to the attribute information
21213 * item's [namespace name] (where an ·absent· {target namespace}
21214 * is taken to be identical to a [namespace name] with no value),
21215 * then the attribute information must be ·valid· with respect
21216 * to that attribute use as per Attribute Locally Valid (Use)
21217 * (§3.5.4). In this case the {attribute declaration} of that
21218 * attribute use is the ·context-determined declaration· for the
21219 * attribute information item with respect to Schema-Validity
21220 * Assessment (Attribute) (§3.2.4) and
21221 * Assessment Outcome (Attribute) (§3.2.5).
21222 */
21223 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21224 attr->use = attrUse;
21225 /*
21226 * Context-determined declaration.
21227 */
21228 attr->decl = attrDecl;
21229 attr->typeDef = attrDecl->subtypes;
21230 break;
21231 }
21232
21233 if (found)
21234 continue;
21235
21236 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
21237 /*
21238 * Handle non-existent, required attributes.
21239 *
21240 * SPEC (cvc-complex-type)
21241 * (4) "The {attribute declaration} of each attribute use in
21242 * the {attribute uses} whose {required} is true matches one
21243 * of the attribute information items in the element information
21244 * item's [attributes] as per clause 3.1 above."
21245 */
21246 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21247 if (tmpAttr == NULL) {
21248 VERROR_INT(
21249 "xmlSchemaVAttributesComplex",
21250 "calling xmlSchemaGetFreshAttrInfo()");
21251 return (-1);
21252 }
21253 tmpAttr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
21254 tmpAttr->use = attrUse;
21255 tmpAttr->decl = attrDecl;
21256 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
21257 ((attrUse->defValue != NULL) ||
21258 (attrDecl->defValue != NULL))) {
21259 /*
21260 * Handle non-existent, optional, default/fixed attributes.
21261 */
21262 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21263 if (tmpAttr == NULL) {
21264 VERROR_INT(
21265 "xmlSchemaVAttributesComplex",
21266 "calling xmlSchemaGetFreshAttrInfo()");
21267 return (-1);
21268 }
21269 tmpAttr->state = XML_SCHEMAS_ATTR_DEFAULT;
21270 tmpAttr->use = attrUse;
21271 tmpAttr->decl = attrDecl;
21272 tmpAttr->typeDef = attrDecl->subtypes;
21273 tmpAttr->localName = attrDecl->name;
21274 tmpAttr->nsName = attrDecl->targetNamespace;
21275 }
21276 }
21277 if (vctxt->nbAttrInfos == 0)
21278 return (0);
21279 /*
21280 * Validate against the wildcard.
21281 */
21282 if (type->attributeWildcard != NULL) {
21283 /*
21284 * SPEC (cvc-complex-type)
21285 * (3.2.1) "There must be an {attribute wildcard}."
21286 */
21287 for (i = 0; i < nbAttrs; i++) {
21288 attr = vctxt->attrInfos[i];
21289 /*
21290 * SPEC (cvc-complex-type) (3)
21291 * Skip meta attributes.
21292 */
21293 if (attr->state != XML_SCHEMAS_ATTR_UNKNOWN)
21294 continue;
21295 /*
21296 * SPEC (cvc-complex-type)
21297 * (3.2.2) "The attribute information item must be ·valid· with
21298 * respect to it as defined in Item Valid (Wildcard) (§3.10.4)."
21299 *
21300 * SPEC Item Valid (Wildcard) (cvc-wildcard)
21301 * "... its [namespace name] must be ·valid· with respect to
21302 * the wildcard constraint, as defined in Wildcard allows
21303 * Namespace Name (§3.10.4)."
21304 */
21305 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
21306 attr->nsName)) {
21307 /*
21308 * Handle processContents.
21309 *
21310 * SPEC (cvc-wildcard):
21311 * processContents | context-determined declaration:
21312 * "strict" "mustFind"
21313 * "lax" "none"
21314 * "skip" "skip"
21315 */
21316 if (type->attributeWildcard->processContents ==
21317 XML_SCHEMAS_ANY_SKIP) {
21318 /*
21319 * context-determined declaration = "skip"
21320 *
21321 * SPEC PSVI Assessment Outcome (Attribute)
21322 * [validity] = "notKnown"
21323 * [validation attempted] = "none"
21324 */
21325 attr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
21326 continue;
21327 }
21328 /*
21329 * Find an attribute declaration.
21330 */
21331 attr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
21332 attr->localName, attr->nsName);
21333 if (attr->decl != NULL) {
21334 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21335 /*
21336 * SPEC (cvc-complex-type)
21337 * (5) "Let [Definition:] the wild IDs be the set of
21338 * all attribute information item to which clause 3.2
21339 * applied and whose ·validation· resulted in a
21340 * ·context-determined declaration· of mustFind or no
21341 * ·context-determined declaration· at all, and whose
21342 * [local name] and [namespace name] resolve (as
21343 * defined by QName resolution (Instance) (§3.15.4)) to
21344 * an attribute declaration whose {type definition} is
21345 * or is derived from ID. Then all of the following
21346 * must be true:"
21347 */
21348 attr->typeDef = attr->decl->subtypes;
21349 if (xmlSchemaIsDerivedFromBuiltInType(
21350 attr->typeDef, XML_SCHEMAS_ID)) {
21351 /*
21352 * SPEC (5.1) "There must be no more than one
21353 * item in ·wild IDs·."
21354 */
21355 if (wildIDs != 0) {
21356 /* VAL TODO */
21357 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
21358 TODO
21359 continue;
21360 }
21361 wildIDs++;
21362 /*
21363 * SPEC (cvc-complex-type)
21364 * (5.2) "If ·wild IDs· is non-empty, there must not
21365 * be any attribute uses among the {attribute uses}
21366 * whose {attribute declaration}'s {type definition}
21367 * is or is derived from ID."
21368 */
21369 for (attrUseLink = type->attributeUses;
21370 attrUseLink != NULL;
21371 attrUseLink = attrUseLink->next) {
21372 if (xmlSchemaIsDerivedFromBuiltInType(
21373 attrUseLink->attr->subtypes,
21374 XML_SCHEMAS_ID)) {
21375 /* VAL TODO */
21376 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
21377 TODO
21378 }
21379 }
21380 }
21381 } else if (type->attributeWildcard->processContents ==
21382 XML_SCHEMAS_ANY_LAX) {
21383 attr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
21384 /*
21385 * SPEC PSVI Assessment Outcome (Attribute)
21386 * [validity] = "notKnown"
21387 * [validation attempted] = "none"
21388 */
21389 } else {
21390 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
21391 }
21392 }
21393 }
21394 }
21395
21396
21397 if (vctxt->nbAttrInfos == 0)
21398 return (0);
21399
21400 /*
21401 * Validate values, create default attributes, evaluate IDCs.
21402 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021403 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21404 attr = vctxt->attrInfos[i];
21405 /*
21406 * VAL TODO: Note that we won't try to resolve IDCs to
21407 * "lax" and "skip" validated attributes. Check what to
21408 * do in this case.
21409 */
21410 if ((attr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
21411 (attr->state != XML_SCHEMAS_ATTR_DEFAULT))
21412 continue;
21413 /*
21414 * VAL TODO: What to do if the type definition is missing?
21415 */
21416 if (attr->typeDef == NULL) {
21417 attr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
21418 continue;
21419 }
21420
21421 ACTIVATE_ATTRIBUTE(attr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021422 fixed = 0;
21423 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021424
21425 if (vctxt->xpathStates != NULL) {
21426 /*
21427 * Evaluate IDCs.
21428 */
21429 xpathRes = xmlSchemaXPathEvaluate(vctxt,
21430 XML_ATTRIBUTE_NODE);
21431 if (xpathRes == -1) {
21432 VERROR_INT("xmlSchemaVAttributesComplex",
21433 "calling xmlSchemaXPathEvaluate()");
21434 goto internal_error;
21435 }
21436 }
21437
21438 if (attr->state == XML_SCHEMAS_ATTR_DEFAULT) {
21439 /*
21440 * Default/fixed attributes.
21441 */
21442 if (xpathRes) {
21443 if (attr->use->defValue == NULL) {
21444 attr->value = (xmlChar *) attr->use->defValue;
21445 attr->val = attr->use->defVal;
21446 } else {
21447 attr->value = (xmlChar *) attr->decl->defValue;
21448 attr->val = attr->decl->defVal;
21449 }
21450 /*
21451 * IDCs will consume the precomputed default value,
21452 * so we need to clone it.
21453 */
21454 if (attr->val == NULL) {
21455 VERROR_INT("xmlSchemaVAttributesComplex",
21456 "default/fixed value on an attribute use was "
21457 "not precomputed");
21458 goto internal_error;
21459 }
21460 attr->val = xmlSchemaCopyValue(attr->val);
21461 if (attr->val == NULL) {
21462 VERROR_INT("xmlSchemaVAttributesComplex",
21463 "calling xmlSchemaCopyValue()");
21464 goto internal_error;
21465 }
21466 }
21467 /*
21468 * PSVI: Add the default attribute to the current element.
21469 * VAL TODO: Should we use the *normalized* value? This currently
21470 * uses the *initial* value.
21471 */
21472 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
21473 (attr->node != NULL) && (attr->node->doc != NULL)) {
21474 xmlChar *normValue;
21475 const xmlChar *value;
21476
21477 value = attr->value;
21478 /*
21479 * Normalize the value.
21480 */
21481 normValue = xmlSchemaNormalizeValue(attr->typeDef,
21482 attr->value);
21483 if (normValue != NULL)
21484 value = BAD_CAST normValue;
21485
21486 if (attr->nsName == NULL) {
21487 if (xmlNewProp(attr->node->parent,
21488 attr->localName, value) == NULL) {
21489 VERROR_INT("xmlSchemaVAttributesComplex",
21490 "callling xmlNewProp()");
21491 if (normValue != NULL)
21492 xmlFree(normValue);
21493 goto internal_error;
21494 }
21495 } else {
21496 xmlNsPtr ns;
21497
21498 ns = xmlSearchNsByHref(attr->node->doc,
21499 attr->node->parent, attr->nsName);
21500 if (ns == NULL) {
21501 xmlChar prefix[12];
21502 int counter = 0;
21503
21504 /*
21505 * Create a namespace declaration on the validation
21506 * root node if no namespace declaration is in scope.
21507 */
21508 do {
21509 snprintf((char *) prefix, 12, "p%d", counter++);
21510 ns = xmlSearchNs(attr->node->doc,
21511 attr->node->parent, BAD_CAST prefix);
21512 if (counter > 1000) {
21513 VERROR_INT(
21514 "xmlSchemaVAttributesComplex",
21515 "could not compute a ns prefix for a "
21516 "default/fixed attribute");
21517 if (normValue != NULL)
21518 xmlFree(normValue);
21519 goto internal_error;
21520 }
21521 } while (ns != NULL);
21522 ns = xmlNewNs(vctxt->validationRoot,
21523 attr->nsName, BAD_CAST prefix);
21524 }
21525 xmlNewNsProp(attr->node->parent, ns,
21526 attr->localName, value);
21527 }
21528 if (normValue != NULL)
21529 xmlFree(normValue);
21530 }
21531 /*
21532 * Go directly to IDC evaluation.
21533 */
21534 goto eval_idcs;
21535 }
21536 /*
21537 * Validate the value.
21538 */
21539 if (vctxt->value != NULL) {
21540 /*
21541 * Free last computed value; just for safety reasons.
21542 */
21543 xmlSchemaFreeValue(vctxt->value);
21544 vctxt->value = NULL;
21545 }
21546 /*
21547 * Note that the attribute *use* can be unavailable, if
21548 * the attribute was a wild attribute.
21549 */
21550 if ((attr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
21551 ((attr->use != NULL) &&
21552 (attr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
21553 fixed = 1;
21554 else
21555 fixed = 0;
21556 /*
21557 * SPEC (cvc-attribute)
21558 * (3) "The item's ·normalized value· must be locally ·valid·
21559 * with respect to that {type definition} as per
21560 * String Valid (§3.14.4)."
21561 *
21562 * VAL TODO: Do we already have the
21563 * "normalized attribute value" here?
21564 */
21565 if (xpathRes || fixed) {
21566 attr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
21567 /*
21568 * Request a computed value.
21569 */
21570 res = xmlSchemaVCheckCVCSimpleType(
21571 (xmlSchemaAbstractCtxtPtr) vctxt,
21572 attr->node, attr->typeDef, attr->value, &(attr->val),
21573 1, 1, 0);
21574 } else {
21575 res = xmlSchemaVCheckCVCSimpleType(
21576 (xmlSchemaAbstractCtxtPtr) vctxt,
21577 attr->node, attr->typeDef, attr->value, NULL,
21578 1, 0, 0);
21579 }
21580
21581 if (res != 0) {
21582 if (res == -1) {
21583 VERROR_INT("xmlSchemaVAttributesComplex",
21584 "calling xmlSchemaStreamValidateSimpleTypeValue()");
21585 goto internal_error;
21586 }
21587 attr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
21588 /*
21589 * SPEC PSVI Assessment Outcome (Attribute)
21590 * [validity] = "invalid"
21591 */
21592 goto eval_idcs;
21593 }
21594
21595 if (fixed) {
21596 int ws;
21597 /*
21598 * SPEC Attribute Locally Valid (Use) (cvc-au)
21599 * "For an attribute information item to be·valid·
21600 * with respect to an attribute use its *normalized*
21601 * value· must match the *canonical* lexical
21602 * representation of the attribute use's {value
21603 * constraint}value, if it is present and fixed."
21604 *
21605 * VAL TODO: The requirement for the *canonical* value
21606 * will be removed in XML Schema 1.1.
21607 */
21608 /*
21609 * SPEC Attribute Locally Valid (cvc-attribute)
21610 * (4) "The item's *actual* value· must match the *value* of
21611 * the {value constraint}, if it is present and fixed."
21612 */
21613 ws = xmlSchemaGetWhiteSpaceFacetValue(attr->typeDef);
21614 if (attr->val == NULL) {
21615 /* VAL TODO: A value was not precomputed. */
21616 TODO
21617 goto eval_idcs;
21618 }
21619 if ((attr->use != NULL) &&
21620 (attr->use->defValue != NULL)) {
21621 if (attr->use->defVal == NULL) {
21622 /* VAL TODO: A default value was not precomputed. */
21623 TODO
21624 goto eval_idcs;
21625 }
21626 attr->vcValue = attr->use->defValue;
21627 /*
21628 if (xmlSchemaCompareValuesWhtsp(attr->val,
21629 (xmlSchemaWhitespaceValueType) ws,
21630 attr->use->defVal,
21631 (xmlSchemaWhitespaceValueType) ws) != 0) {
21632 */
21633 if (! xmlSchemaAreValuesEqual(attr->val, attr->use->defVal))
21634 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21635 } else {
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021636 if (attr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021637 /* VAL TODO: A default value was not precomputed. */
21638 TODO
21639 goto eval_idcs;
21640 }
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021641 attr->vcValue = attr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021642 /*
21643 if (xmlSchemaCompareValuesWhtsp(attr->val,
21644 (xmlSchemaWhitespaceValueType) ws,
21645 attrDecl->defVal,
21646 (xmlSchemaWhitespaceValueType) ws) != 0) {
21647 */
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021648 if (! xmlSchemaAreValuesEqual(attr->val, attr->decl->defVal))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021649 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21650 }
21651 /*
21652 * [validity] = "valid"
21653 */
21654 }
21655eval_idcs:
21656 /*
21657 * Evaluate IDCs.
21658 */
21659 if (xpathRes) {
21660 if (xmlSchemaXPathProcessHistory(vctxt,
21661 vctxt->depth +1) == -1) {
21662 VERROR_INT("xmlSchemaVAttributesComplex",
21663 "calling xmlSchemaXPathEvaluate()");
21664 goto internal_error;
21665 }
21666 }
21667 }
21668
21669 /*
21670 * Report errors.
21671 */
21672 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21673 attr = vctxt->attrInfos[i];
21674 if ((attr->state == XML_SCHEMAS_ATTR_META) ||
21675 (attr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
21676 (attr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
21677 (attr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
21678 continue;
21679 ACTIVATE_ATTRIBUTE(attr);
21680 switch (attr->state) {
21681 case XML_SCHEMAS_ATTR_ERR_MISSING: {
21682 xmlChar *str = NULL;
21683 ACTIVATE_ELEM;
21684 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21685 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
21686 "The attribute '%s' is required but missing",
21687 xmlSchemaFormatQName(&str,
21688 attr->decl->targetNamespace,
21689 attr->decl->name),
21690 NULL);
21691 FREE_AND_NULL(str)
21692 break;
21693 }
21694 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
21695 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
21696 "The type definition is absent");
21697 break;
21698 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
21699 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21700 XML_SCHEMAV_CVC_AU, NULL, NULL,
21701 "The value '%s' does not match the fixed "
21702 "value constraint '%s'",
21703 attr->value, attr->vcValue);
21704 break;
21705 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
21706 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
21707 "No matching global attribute declaration available, but "
21708 "demanded by the strict wildcard");
21709 break;
21710 case XML_SCHEMAS_ATTR_UNKNOWN:
21711 if (attr->metaType)
21712 break;
21713 /*
21714 * MAYBE VAL TODO: One might report different error messages
21715 * for the following errors.
21716 */
21717 if (type->attributeWildcard == NULL) {
21718 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21719 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr, NULL);
21720 } else {
21721 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21722 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr, NULL);
21723 }
21724 break;
21725 default:
21726 break;
21727 }
21728 }
21729
21730 ACTIVATE_ELEM;
21731 return (0);
21732internal_error:
21733 ACTIVATE_ELEM;
21734 return (-1);
21735}
21736
21737static int
21738xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
21739 int *skip)
21740{
21741 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
21742 /*
21743 * The namespace of the element was already identified to be
21744 * matching the wildcard.
21745 */
21746 if ((skip == NULL) || (wild == NULL) ||
21747 (wild->type != XML_SCHEMA_TYPE_ANY)) {
21748 VERROR_INT("xmlSchemaValidateElemWildcard",
21749 "bad arguments");
21750 return (-1);
21751 }
21752 *skip = 0;
21753 if (wild->negNsSet != NULL) {
21754 /*
21755 * URGENT VAL TODO: Fix the content model to reject
21756 * "##other" wildcards.
21757 */
21758 if (xmlSchemaCheckCVCWildcardNamespace(wild,
21759 vctxt->inode->nsName) != 0) {
21760 if ((wild->minOccurs == 1) && (wild->maxOccurs == 1)) {
21761 xmlSchemaNodeInfoPtr pinode = vctxt->elemInfos[vctxt->depth -1];
21762 /*
21763 * VAL TODO: Workaround possible *only* if minOccurs and
21764 * maxOccurs are 1.
21765 */
21766 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
21767 /* VAL TODO: error code? */
21768 XML_SCHEMAV_ELEMENT_CONTENT, NULL,
21769 (xmlSchemaTypePtr) wild,
21770 "This element is not accepted by the wildcard",
21771 0, 0, NULL);
21772 vctxt->skipDepth = vctxt->depth;
21773 if ((pinode->flags &
21774 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0)
21775 pinode->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
21776 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
21777 return (XML_SCHEMAV_ELEMENT_CONTENT);
21778 }
21779 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
21780 *skip = 1;
21781 return (0);
21782 }
21783 vctxt->inode->typeDef =
21784 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
21785 return (0);
21786 }
21787 }
21788 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
21789 /*
21790 * URGENT VAL TODO: Either we need to position the stream to the
21791 * next sibling, or walk the whole subtree.
21792 */
21793 *skip = 1;
21794 return (0);
21795 }
21796 {
21797 xmlSchemaElementPtr decl = NULL;
21798
21799 decl = xmlHashLookup3(vctxt->schema->elemDecl,
21800 vctxt->inode->localName, vctxt->inode->nsName,
21801 NULL);
21802 if (decl != NULL) {
21803 vctxt->inode->decl = decl;
21804 return (0);
21805 }
21806 }
21807 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
21808 /* VAL TODO: Change to proper error code. */
21809 VERROR(XML_SCHEMAV_CVC_ELT_1, (xmlSchemaTypePtr) wild,
21810 "No matching global element declaration available, but "
21811 "demanded by the strict wildcard");
21812 return (vctxt->err);
21813 }
21814 if (vctxt->nbAttrInfos != 0) {
21815 xmlSchemaAttrInfoPtr iattr;
21816 /*
21817 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21818 * (1.2.1.2.1) - (1.2.1.2.3 )
21819 *
21820 * Use the xsi:type attribute for the type definition.
21821 */
21822 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21823 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21824 if (iattr != NULL) {
21825 if (xmlSchemaProcessXSIType(vctxt, iattr,
21826 &(vctxt->inode->typeDef), NULL) == -1) {
21827 VERROR_INT("xmlSchemaValidateElemWildcard",
21828 "calling xmlSchemaProcessXSIType() to "
21829 "process the attribute 'xsi:nil'");
21830 return (-1);
21831 }
21832 /*
21833 * Don't return an error on purpose.
21834 */
21835 return (0);
21836 }
21837 }
21838 /*
21839 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21840 *
21841 * Fallback to "anyType".
21842 */
21843 vctxt->inode->typeDef =
21844 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
21845 return (0);
21846}
21847
21848/*
21849* xmlSchemaCheckCOSValidDefault:
21850*
21851* This will be called if: not nilled, no content and a default/fixed
21852* value is provided.
21853*/
21854
21855static int
21856xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
21857 const xmlChar *value,
21858 xmlSchemaValPtr *val)
21859{
21860 int ret = 0;
21861 xmlSchemaNodeInfoPtr inode = vctxt->inode;
21862
21863 /*
21864 * cos-valid-default:
21865 * Schema Component Constraint: Element Default Valid (Immediate)
21866 * For a string to be a valid default with respect to a type
21867 * definition the appropriate case among the following must be true:
21868 */
21869 if IS_COMPLEX_TYPE(inode->typeDef) {
21870 /*
21871 * Complex type.
21872 *
21873 * SPEC (2.1) "its {content type} must be a simple type definition
21874 * or mixed."
21875 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
21876 * type}'s particle must be ·emptiable· as defined by
21877 * Particle Emptiable (§3.9.6)."
21878 */
21879 if ((! HAS_SIMPLE_CONTENT(inode->typeDef)) &&
21880 ((! HAS_MIXED_CONTENT(inode->typeDef)) ||
21881 (! IS_PARTICLE_EMPTIABLE(inode->typeDef)))) {
21882 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
21883 /* NOTE that this covers (2.2.2) as well. */
21884 VERROR(ret, NULL,
21885 "For a string to be a valid default, the type definition "
21886 "must be a simple type or a complex type with simple content "
21887 "or mixed content and a particle emptiable");
21888 return(ret);
21889 }
21890 }
21891 /*
21892 * 1 If the type definition is a simple type definition, then the string
21893 * must be ·valid· with respect to that definition as defined by String
21894 * Valid (§3.14.4).
21895 *
21896 * AND
21897 *
21898 * 2.2.1 If the {content type} is a simple type definition, then the
21899 * string must be ·valid· with respect to that simple type definition
21900 * as defined by String Valid (§3.14.4).
21901 */
21902 if (IS_SIMPLE_TYPE(inode->typeDef)) {
21903
21904 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
21905 NULL, inode->typeDef, value, val, 1, 1, 0);
21906
21907 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
21908
21909 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
21910 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
21911 }
21912 if (ret < 0) {
21913 VERROR_INT("xmlSchemaCheckCOSValidDefault",
21914 "calling xmlSchemaVCheckCVCSimpleType()");
21915 }
21916 return (ret);
21917}
21918
21919static void
21920xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
21921 const xmlChar * name ATTRIBUTE_UNUSED,
21922 xmlSchemaElementPtr item,
21923 xmlSchemaNodeInfoPtr inode)
21924{
21925 inode->decl = item;
21926#ifdef DEBUG_CONTENT
21927 {
21928 xmlChar *str = NULL;
21929
21930 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
21931 xmlGenericError(xmlGenericErrorContext,
21932 "AUTOMATON callback for '%s' [declaration]\n",
21933 xmlSchemaFormatQName(&str,
21934 inode->localName, inode->nsName));
21935 } else {
21936 xmlGenericError(xmlGenericErrorContext,
21937 "AUTOMATON callback for '%s' [wildcard]\n",
21938 xmlSchemaFormatQName(&str,
21939 inode->localName, inode->nsName));
21940
21941 }
21942 FREE_AND_NULL(str)
21943 }
21944#endif
21945}
21946
21947static int
21948xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000021949{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021950 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
21951 if (vctxt->inode == NULL) {
21952 VERROR_INT("xmlSchemaValidatorPushElem",
21953 "calling xmlSchemaGetFreshElemInfo()");
21954 return (-1);
21955 }
21956 vctxt->nbAttrInfos = 0;
21957 return (0);
21958}
21959
21960static int
21961xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
21962 xmlSchemaNodeInfoPtr inode,
21963 xmlSchemaTypePtr type,
21964 const xmlChar *value)
21965{
21966 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
21967 return (xmlSchemaVCheckCVCSimpleType(
21968 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
21969 type, value, &(inode->val), 1, 1, 0));
21970 else
21971 return (xmlSchemaVCheckCVCSimpleType(
21972 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
21973 type, value, NULL, 1, 0, 0));
21974}
21975
21976
21977
21978/*
21979* Process END of element.
21980*/
21981static int
21982xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
21983{
21984 int ret = 0;
21985 xmlSchemaNodeInfoPtr inode = vctxt->inode;
21986
21987 if (vctxt->nbAttrInfos != 0)
21988 xmlSchemaClearAttrInfos(vctxt);
21989 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
21990 /*
21991 * This element was not expected;
21992 * we will not validate child elements of broken parents.
21993 * Skip validation of all content of the parent.
21994 */
21995 vctxt->skipDepth = vctxt->depth -1;
21996 goto end_elem;
21997 }
21998 if ((inode->typeDef == NULL) ||
21999 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
22000 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022001 * 1. the type definition might be missing if the element was
22002 * error prone
22003 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022004 */
22005 goto end_elem;
22006 }
22007 /*
22008 * Check the content model.
22009 */
22010 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
22011 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
22012
22013 /*
22014 * Workaround for "anyType".
22015 */
22016 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
22017 goto character_content;
22018
22019 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
22020 xmlChar *values[10];
22021 int terminal, nbval = 10, nbneg;
22022
22023 if (inode->regexCtxt == NULL) {
22024 /*
22025 * Create the regex context.
22026 */
22027 inode->regexCtxt =
22028 xmlRegNewExecCtxt(inode->typeDef->contModel,
22029 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22030 vctxt);
22031 if (inode->regexCtxt == NULL) {
22032 VERROR_INT("xmlSchemaValidatorPopElem",
22033 "failed to create a regex context");
22034 goto internal_error;
22035 }
22036#ifdef DEBUG_AUTOMATA
22037 xmlGenericError(xmlGenericErrorContext,
22038 "AUTOMATON create on '%s'\n", inode->localName);
22039#endif
22040 }
22041 /*
22042 * Get hold of the still expected content, since a further
22043 * call to xmlRegExecPushString() will loose this information.
22044 */
22045 xmlRegExecNextValues(inode->regexCtxt,
22046 &nbval, &nbneg, &values[0], &terminal);
22047 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
22048 if (ret <= 0) {
22049 /*
22050 * Still missing something.
22051 */
22052 ret = 1;
22053 inode->flags |=
22054 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22055 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22056 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
22057 "Missing child element(s)",
22058 nbval, nbneg, values);
22059#ifdef DEBUG_AUTOMATA
22060 xmlGenericError(xmlGenericErrorContext,
22061 "AUTOMATON missing ERROR on '%s'\n",
22062 inode->localName);
22063#endif
22064 } else {
22065 /*
22066 * Content model is satisfied.
22067 */
22068 ret = 0;
22069#ifdef DEBUG_AUTOMATA
22070 xmlGenericError(xmlGenericErrorContext,
22071 "AUTOMATON succeeded on '%s'\n",
22072 inode->localName);
22073#endif
22074 }
22075
22076 }
22077 }
22078 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
22079 goto end_elem;
22080
22081character_content:
22082
22083 if (vctxt->value != NULL) {
22084 xmlSchemaFreeValue(vctxt->value);
22085 vctxt->value = NULL;
22086 }
22087 /*
22088 * Check character content.
22089 */
22090 if (inode->decl == NULL) {
22091 /*
22092 * Speedup if no declaration exists.
22093 */
22094 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22095 ret = xmlSchemaVCheckINodeDataType(vctxt,
22096 inode, inode->typeDef, inode->value);
22097 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22098 ret = xmlSchemaVCheckINodeDataType(vctxt,
22099 inode, inode->typeDef->contentTypeDef,
22100 inode->value);
22101 }
22102 if (ret < 0) {
22103 VERROR_INT("xmlSchemaValidatorPopElem",
22104 "calling xmlSchemaVCheckCVCSimpleType()");
22105 goto internal_error;
22106 }
22107 goto end_elem;
22108 }
22109 /*
22110 * cvc-elt (3.3.4) : 5
22111 * The appropriate case among the following must be true:
22112 */
22113 /*
22114 * cvc-elt (3.3.4) : 5.1
22115 * If the declaration has a {value constraint},
22116 * the item has neither element nor character [children] and
22117 * clause 3.2 has not applied, then all of the following must be true:
22118 */
22119 if ((inode->decl->value != NULL) &&
22120 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
22121 (! INODE_NILLED(inode))) {
22122 /*
22123 * cvc-elt (3.3.4) : 5.1.1
22124 * If the ·actual type definition· is a ·local type definition·
22125 * then the canonical lexical representation of the {value constraint}
22126 * value must be a valid default for the ·actual type definition· as
22127 * defined in Element Default Valid (Immediate) (§3.3.6).
22128 */
22129 /*
22130 * NOTE: 'local' above means types aquired by xsi:type.
22131 * NOTE: Although the *canonical* value is stated, it is not
22132 * relevant if canonical or not. Additionally XML Schema 1.1
22133 * will removed this requirement as well.
22134 */
22135 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
22136
22137 ret = xmlSchemaCheckCOSValidDefault(vctxt,
22138 inode->decl->value, &(inode->val));
22139 if (ret != 0) {
22140 if (ret < 0) {
22141 VERROR_INT("xmlSchemaValidatorPopElem",
22142 "calling xmlSchemaCheckCOSValidDefault()");
22143 goto internal_error;
22144 }
22145 goto end_elem;
22146 }
22147 /*
22148 * Stop here, to avoid redundant validation of the value
22149 * (see following).
22150 */
22151 goto default_psvi;
22152 }
22153 /*
22154 * cvc-elt (3.3.4) : 5.1.2
22155 * The element information item with the canonical lexical
22156 * representation of the {value constraint} value used as its
22157 * ·normalized value· must be ·valid· with respect to the
22158 * ·actual type definition· as defined by Element Locally Valid (Type)
22159 * (§3.3.4).
22160 */
22161 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22162 ret = xmlSchemaVCheckINodeDataType(vctxt,
22163 inode, inode->typeDef, inode->decl->value);
22164 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22165 ret = xmlSchemaVCheckINodeDataType(vctxt,
22166 inode, inode->typeDef->contentTypeDef,
22167 inode->decl->value);
22168 }
22169 if (ret != 0) {
22170 if (ret < 0) {
22171 VERROR_INT("xmlSchemaValidatorPopElem",
22172 "calling xmlSchemaVCheckCVCSimpleType()");
22173 goto internal_error;
22174 }
22175 goto end_elem;
22176 }
22177
22178default_psvi:
22179 /*
22180 * PSVI: Create a text node on the instance element.
22181 */
22182 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
22183 (inode->node != NULL)) {
22184 xmlNodePtr textChild;
22185 xmlChar *normValue;
22186 /*
22187 * VAL TODO: Normalize the value.
22188 */
22189 normValue = xmlSchemaNormalizeValue(inode->typeDef,
22190 inode->decl->value);
22191 if (normValue != NULL) {
22192 textChild = xmlNewText(BAD_CAST normValue);
22193 xmlFree(normValue);
22194 } else
22195 textChild = xmlNewText(inode->decl->value);
22196 if (textChild == NULL) {
22197 VERROR_INT("xmlSchemaValidatorPopElem",
22198 "calling xmlNewText()");
22199 goto internal_error;
22200 } else
22201 xmlAddChild(inode->node, textChild);
22202 }
22203
22204 } else if (! INODE_NILLED(inode)) {
22205 /*
22206 * 5.2.1 The element information item must be ·valid· with respect
22207 * to the ·actual type definition· as defined by Element Locally
22208 * Valid (Type) (§3.3.4).
22209 */
22210 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22211 /*
22212 * SPEC (cvc-type) (3.1)
22213 * "If the type definition is a simple type definition, ..."
22214 * (3.1.3) "If clause 3.2 of Element Locally Valid
22215 * (Element) (§3.3.4) did not apply, then the ·normalized value·
22216 * must be ·valid· with respect to the type definition as defined
22217 * by String Valid (§3.14.4).
22218 */
22219 ret = xmlSchemaVCheckINodeDataType(vctxt,
22220 inode, inode->typeDef, inode->value);
22221 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22222 /*
22223 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
22224 * definition, then the element information item must be
22225 * ·valid· with respect to the type definition as per
22226 * Element Locally Valid (Complex Type) (§3.4.4);"
22227 *
22228 * SPEC (cvc-complex-type) (2.2)
22229 * "If the {content type} is a simple type definition, ...
22230 * the ·normalized value· of the element information item is
22231 * ·valid· with respect to that simple type definition as
22232 * defined by String Valid (§3.14.4)."
22233 */
22234 ret = xmlSchemaVCheckINodeDataType(vctxt,
22235 inode, inode->typeDef->contentTypeDef, inode->value);
22236 }
22237 if (ret != 0) {
22238 if (ret < 0) {
22239 VERROR_INT("xmlSchemaValidatorPopElem",
22240 "calling xmlSchemaVCheckCVCSimpleType()");
22241 goto internal_error;
22242 }
22243 goto end_elem;
22244 }
22245 /*
22246 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
22247 * not applied, all of the following must be true:
22248 */
22249 if ((inode->decl->value != NULL) &&
22250 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
22251
22252 /*
22253 * TODO: We will need a computed value, when comparison is
22254 * done on computed values.
22255 */
22256 /*
22257 * 5.2.2.1 The element information item must have no element
22258 * information item [children].
22259 */
22260 if (inode->flags &
22261 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
22262 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
22263 VERROR(ret, NULL,
22264 "The content must not containt element nodes since "
22265 "there is a fixed value constraint");
22266 goto end_elem;
22267 } else {
22268 /*
22269 * 5.2.2.2 The appropriate case among the following must
22270 * be true:
22271 */
22272 if (HAS_MIXED_CONTENT(inode->typeDef)) {
22273 /*
22274 * 5.2.2.2.1 If the {content type} of the ·actual type
22275 * definition· is mixed, then the *initial value* of the
22276 * item must match the canonical lexical representation
22277 * of the {value constraint} value.
22278 *
22279 * ... the *initial value* of an element information
22280 * item is the string composed of, in order, the
22281 * [character code] of each character information item in
22282 * the [children] of that element information item.
22283 */
22284 if (! xmlStrEqual(inode->value, inode->decl->value)){
22285 /*
22286 * VAL TODO: Report invalid & expected values as well.
22287 * VAL TODO: Implement the canonical stuff.
22288 */
22289 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
22290 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22291 ret, NULL, NULL,
22292 "The initial value '%s' does not match the fixed "
22293 "value constraint '%s'",
22294 inode->value, inode->decl->value);
22295 goto end_elem;
22296 }
22297 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22298 /*
22299 * 5.2.2.2.2 If the {content type} of the ·actual type
22300 * definition· is a simple type definition, then the
22301 * *actual value* of the item must match the canonical
22302 * lexical representation of the {value constraint} value.
22303 */
22304 /*
22305 * VAL TODO: *actual value* is the normalized value, impl.
22306 * this.
22307 * VAL TODO: Report invalid & expected values as well.
22308 * VAL TODO: Implement a comparison with the computed values.
22309 */
22310 if (! xmlStrEqual(inode->value,
22311 inode->decl->value)) {
22312 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
22313 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22314 ret, NULL, NULL,
22315 "The actual value '%s' does not match the fixed "
22316 "value constraint '%s'",
22317 inode->value,
22318 inode->decl->value);
22319 goto end_elem;
22320 }
22321 }
22322 }
22323 }
22324 }
22325
22326end_elem:
22327 if (vctxt->depth < 0) {
22328 /* TODO: raise error? */
22329 return (0);
22330 }
22331 if (vctxt->depth == vctxt->skipDepth)
22332 vctxt->skipDepth = -1;
22333 /*
22334 * Evaluate the history of XPath state objects.
22335 */
22336 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
22337 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022338 /*
22339 * TODO: 6 The element information item must be ·valid· with respect to each of
22340 * the {identity-constraint definitions} as per Identity-constraint
22341 * Satisfied (§3.11.4).
22342 */
22343 /*
22344 * Validate IDC keyrefs.
22345 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022346 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
22347 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022348 /*
22349 * Merge/free the IDC table.
22350 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022351 if (inode->idcTable != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022352#ifdef DEBUG_IDC
22353 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022354 inode->nsName,
22355 inode->localName,
22356 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022357#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022358 if (vctxt->depth > 0) {
22359 /*
22360 * Merge the IDC node table with the table of the parent node.
22361 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022362 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
22363 goto internal_error;
22364 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022365 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022366 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022367 * Clear the current ielem.
22368 * VAL TODO: Don't free the PSVI IDC tables if they are
22369 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022370 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022371 xmlSchemaClearElemInfo(inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022372 /*
22373 * Skip further processing if we are on the validation root.
22374 */
22375 if (vctxt->depth == 0) {
22376 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022377 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022378 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022379 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022380 /*
22381 * Reset the bubbleDepth if needed.
22382 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022383 if (vctxt->aidcs != NULL) {
22384 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
22385 do {
22386 if (aidc->bubbleDepth == vctxt->depth) {
22387 /*
22388 * A bubbleDepth of a key/unique IDC matches the current
22389 * depth, this means that we are leaving the scope of the
22390 * top-most keyref IDC.
22391 */
22392 aidc->bubbleDepth = -1;
22393 }
22394 aidc = aidc->next;
22395 } while (aidc != NULL);
22396 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022397 vctxt->depth--;
22398 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022399 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022400 * VAL TODO: 7 If the element information item is the ·validation root·, it must be
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022401 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
22402 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022403 return (ret);
22404
22405internal_error:
22406 vctxt->err = -1;
22407 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022408}
22409
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022410/*
22411* 3.4.4 Complex Type Definition Validation Rules
22412* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
22413*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000022414static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022415xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000022416{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022417 xmlSchemaNodeInfoPtr pielem;
22418 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022419 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000022420
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022421 if (vctxt->depth <= 0) {
22422 VERROR_INT("xmlSchemaValidateChildElem",
22423 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022424 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022425 }
22426 pielem = vctxt->elemInfos[vctxt->depth -1];
22427 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
22428 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022429 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022430 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022431 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022432 if (INODE_NILLED(pielem)) {
22433 /*
22434 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
22435 */
22436 ACTIVATE_PARENT_ELEM;
22437 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
22438 VERROR(ret, NULL,
22439 "Neither character nor element content is allowed, "
22440 "because the element was 'nilled'");
22441 ACTIVATE_ELEM;
22442 goto unexpected_elem;
22443 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022444
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022445 ptype = pielem->typeDef;
22446
22447 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
22448 /*
22449 * Workaround for "anyType": we have currently no content model
22450 * assigned for "anyType", so handle it explicitely.
22451 * "anyType" has an unbounded, lax "any" wildcard.
22452 */
22453 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22454 vctxt->inode->localName,
22455 vctxt->inode->nsName);
22456
22457 if (vctxt->inode->decl == NULL) {
22458 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022459 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022460 * Process "xsi:type".
22461 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022462 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022463 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
22464 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
22465 if (iattr != NULL) {
22466 ret = xmlSchemaProcessXSIType(vctxt, iattr,
22467 &(vctxt->inode->typeDef), NULL);
22468 if (ret != 0) {
22469 if (ret == -1) {
22470 VERROR_INT("xmlSchemaValidateChildElem",
22471 "calling xmlSchemaProcessXSIType() to "
22472 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022473 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000022474 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022475 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000022476 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022477 } else {
22478 /*
22479 * Fallback to "anyType".
22480 *
22481 * SPEC (cvc-assess-elt)
22482 * "If the item cannot be ·strictly assessed·, [...]
22483 * an element information item's schema validity may be laxly
22484 * assessed if its ·context-determined declaration· is not
22485 * skip by ·validating· with respect to the ·ur-type
22486 * definition· as per Element Locally Valid (Type) (§3.3.4)."
22487 */
22488 vctxt->inode->typeDef =
22489 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022490 }
22491 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022492 return (0);
22493 }
22494
22495 switch (ptype->contentType) {
22496 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022497 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022498 * SPEC (2.1) "If the {content type} is empty, then the
22499 * element information item has no character or element
22500 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022501 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022502 ACTIVATE_PARENT_ELEM
22503 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
22504 VERROR(ret, NULL,
22505 "Element content is not allowed, "
22506 "because the content type is empty");
22507 ACTIVATE_ELEM
22508 goto unexpected_elem;
22509 break;
22510
22511 case XML_SCHEMA_CONTENT_MIXED:
22512 case XML_SCHEMA_CONTENT_ELEMENTS: {
22513 xmlRegExecCtxtPtr regexCtxt;
22514 xmlChar *values[10];
22515 int terminal, nbval = 10, nbneg;
22516
22517 /* VAL TODO: Optimized "anyType" validation.*/
22518
22519 if (ptype->contModel == NULL) {
22520 VERROR_INT("xmlSchemaValidateChildElem",
22521 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022522 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022523 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022524 /*
22525 * Safety belf for evaluation if the cont. model was already
22526 * examined to be invalid.
22527 */
22528 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
22529 VERROR_INT("xmlSchemaValidateChildElem",
22530 "validating elem, but elem content is already invalid");
22531 return (-1);
22532 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022533
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022534 regexCtxt = pielem->regexCtxt;
22535 if (regexCtxt == NULL) {
22536 /*
22537 * Create the regex context.
22538 */
22539 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
22540 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22541 vctxt);
22542 if (regexCtxt == NULL) {
22543 VERROR_INT("xmlSchemaValidateChildElem",
22544 "failed to create a regex context");
22545 return (-1);
22546 }
22547 pielem->regexCtxt = regexCtxt;
22548#ifdef DEBUG_AUTOMATA
22549 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
22550 pielem->localName);
22551#endif
22552 }
22553
22554 /*
22555 * SPEC (2.4) "If the {content type} is element-only or mixed,
22556 * then the sequence of the element information item's
22557 * element information item [children], if any, taken in
22558 * order, is ·valid· with respect to the {content type}'s
22559 * particle, as defined in Element Sequence Locally Valid
22560 * (Particle) (§3.9.4)."
22561 */
22562 ret = xmlRegExecPushString2(regexCtxt,
22563 vctxt->inode->localName,
22564 vctxt->inode->nsName,
22565 vctxt->inode);
22566#ifdef DEBUG_AUTOMATA
22567 if (ret < 0)
22568 xmlGenericError(xmlGenericErrorContext,
22569 "AUTOMATON push ERROR for '%s' on '%s'\n",
22570 vctxt->inode->localName, pielem->localName);
22571 else
22572 xmlGenericError(xmlGenericErrorContext,
22573 "AUTOMATON push OK for '%s' on '%s'\n",
22574 vctxt->inode->localName, pielem->localName);
22575#endif
22576 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
22577 VERROR_INT("xmlSchemaValidateChildElem",
22578 "calling xmlRegExecPushString2()");
22579 return (-1);
22580 }
22581 if (ret < 0) {
22582 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
22583 &values[0], &terminal);
22584 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22585 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
22586 "This element is not expected",
22587 nbval, nbneg, values);
22588 ret = vctxt->err;
22589 goto unexpected_elem;
22590 } else
22591 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022592 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022593 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022594 case XML_SCHEMA_CONTENT_SIMPLE:
22595 case XML_SCHEMA_CONTENT_BASIC:
22596 ACTIVATE_PARENT_ELEM
22597 if (IS_COMPLEX_TYPE(ptype)) {
22598 /*
22599 * SPEC (cvc-complex-type) (2.2)
22600 * "If the {content type} is a simple type definition, then
22601 * the element information item has no element information
22602 * item [children], ..."
22603 */
22604 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
22605 VERROR(ret, NULL, "Element content is not allowed, "
22606 "because the content type is a simple type definition");
22607 } else {
22608 /*
22609 * SPEC (cvc-type) (3.1.2) "The element information item must
22610 * have no element information item [children]."
22611 */
22612 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
22613 VERROR(ret, NULL, "Element content is not allowed, "
22614 "because the type definition is simple");
22615 }
22616 ACTIVATE_ELEM
22617 ret = vctxt->err;
22618 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022619 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022620
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022621 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022622 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022623 }
22624 return (ret);
22625unexpected_elem:
22626 /*
22627 * Pop this element and set the skipDepth to skip
22628 * all further content of the parent element.
22629 */
22630 vctxt->skipDepth = vctxt->depth;
22631 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
22632 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22633 return (ret);
22634}
22635
22636#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
22637#define XML_SCHEMA_PUSH_TEXT_CREATED 2
22638#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
22639
22640static int
22641xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
22642 int nodeType, const xmlChar *value, int len,
22643 int mode, int *consumed)
22644{
22645 /*
22646 * Unfortunately we have to duplicate the text sometimes.
22647 * OPTIMIZE: Maybe we could skip it, if:
22648 * 1. content type is simple
22649 * 2. whitespace is "collapse"
22650 * 3. it consists of whitespace only
22651 *
22652 * Process character content.
22653 */
22654 if (consumed != NULL)
22655 *consumed = 0;
22656 if (INODE_NILLED(vctxt->inode)) {
22657 /*
22658 * SPEC cvc-elt (3.3.4 - 3.2.1)
22659 * "The element information item must have no character or
22660 * element information item [children]."
22661 */
22662 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
22663 "Neither character nor element content is allowed "
22664 "because the element is 'nilled'");
22665 return (vctxt->err);
22666 }
22667 /*
22668 * SPEC (2.1) "If the {content type} is empty, then the
22669 * element information item has no character or element
22670 * information item [children]."
22671 */
22672 if (vctxt->inode->typeDef->contentType ==
22673 XML_SCHEMA_CONTENT_EMPTY) {
22674 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
22675 "Character content is not allowed, "
22676 "because the content type is empty");
22677 return (vctxt->err);
22678 }
22679
22680 if (vctxt->inode->typeDef->contentType ==
22681 XML_SCHEMA_CONTENT_ELEMENTS) {
22682 if ((nodeType != XML_TEXT_NODE) ||
22683 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
22684 /*
22685 * SPEC cvc-complex-type (2.3)
22686 * "If the {content type} is element-only, then the
22687 * element information item has no character information
22688 * item [children] other than those whose [character
22689 * code] is defined as a white space in [XML 1.0 (Second
22690 * Edition)]."
22691 */
22692 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
22693 "Character content other than whitespace is not allowed "
22694 "because the content type is 'element-only'");
22695 return (vctxt->err);
22696 }
22697 return (0);
22698 }
22699
22700 if ((value == NULL) || (value[0] == 0))
22701 return (0);
22702 /*
22703 * Save the value.
22704 * NOTE that even if the content type is *mixed*, we need the
22705 * *initial value* for default/fixed value constraints.
22706 */
22707 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
22708 ((vctxt->inode->decl == NULL) ||
22709 (vctxt->inode->decl->value == NULL)))
22710 return (0);
22711
22712 if (vctxt->inode->value == NULL) {
22713 /*
22714 * Set the value.
22715 */
22716 switch (mode) {
22717 case XML_SCHEMA_PUSH_TEXT_PERSIST:
22718 /*
22719 * When working on a tree.
22720 */
22721 vctxt->inode->value = value;
22722 break;
22723 case XML_SCHEMA_PUSH_TEXT_CREATED:
22724 /*
22725 * When working with the reader.
22726 * The value will be freed by the element info.
22727 */
22728 vctxt->inode->value = value;
22729 if (consumed != NULL)
22730 *consumed = 1;
22731 vctxt->inode->flags |=
22732 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22733 break;
22734 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
22735 /*
22736 * When working with SAX.
22737 * The value will be freed by the element info.
22738 */
22739 if (len != -1)
22740 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
22741 else
22742 vctxt->inode->value = BAD_CAST xmlStrdup(value);
22743 vctxt->inode->flags |=
22744 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22745 break;
22746 default:
22747 break;
22748 }
22749 } else {
22750 /*
22751 * Concat the value.
22752 */
22753 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000022754 vctxt->inode->value = BAD_CAST xmlStrncat(
22755 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022756 } else {
22757 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022758 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022759 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22760 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022761 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022762
22763 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000022764}
22765
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022766static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022767xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022768{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022769 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000022770
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022771 if ((vctxt->skipDepth != -1) &&
22772 (vctxt->depth >= vctxt->skipDepth)) {
22773 VERROR_INT("xmlSchemaValidateElem",
22774 "in skip-state");
22775 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022776 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022777 if (vctxt->xsiAssemble) {
22778 if (xmlSchemaAssembleByXSI(vctxt) == -1)
22779 goto internal_error;
22780 }
22781 if (vctxt->depth > 0) {
22782 /*
22783 * Validate this element against the content model
22784 * of the parent.
22785 */
22786 ret = xmlSchemaValidateChildElem(vctxt);
22787 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022788 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022789 VERROR_INT("xmlSchemaValidateElem",
22790 "calling xmlSchemaStreamValidateChildElement()");
22791 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022792 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022793 goto exit;
22794 }
22795 if (vctxt->depth == vctxt->skipDepth)
22796 goto exit;
22797 if ((vctxt->inode->decl == NULL) &&
22798 (vctxt->inode->typeDef == NULL)) {
22799 VERROR_INT("xmlSchemaValidateElem",
22800 "the child element was valid but neither the "
22801 "declaration nor the type was set");
22802 goto internal_error;
22803 }
22804 } else {
22805 /*
22806 * Get the declaration of the validation root.
22807 */
22808 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22809 vctxt->inode->localName,
22810 vctxt->inode->nsName);
22811 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022812 ret = XML_SCHEMAV_CVC_ELT_1;
22813 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022814 "No matching global declaration available "
22815 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022816 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022817 }
22818 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022819
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022820 if (vctxt->inode->decl == NULL)
22821 goto type_validation;
22822
22823 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
22824 int skip;
22825 /*
22826 * Wildcards.
22827 */
22828 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
22829 if (ret != 0) {
22830 if (ret < 0) {
22831 VERROR_INT("xmlSchemaValidateElem",
22832 "calling xmlSchemaValidateElemWildcard()");
22833 goto internal_error;
22834 }
22835 goto exit;
22836 }
22837 if (skip) {
22838 vctxt->skipDepth = vctxt->depth;
22839 goto exit;
22840 }
22841 /*
22842 * The declaration might be set by the wildcard validation,
22843 * when the processContents is "lax" or "strict".
22844 */
22845 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
22846 /*
22847 * Clear the "decl" field to not confuse further processing.
22848 */
22849 vctxt->inode->decl = NULL;
22850 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022851 }
Daniel Veillard4255d502002-04-16 15:50:10 +000022852 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022853 /*
22854 * Validate against the declaration.
22855 */
22856 ret = xmlSchemaValidateElemDecl(vctxt);
22857 if (ret != 0) {
22858 if (ret < 0) {
22859 VERROR_INT("xmlSchemaValidateElem",
22860 "calling xmlSchemaValidateElemDecl()");
22861 goto internal_error;
22862 }
22863 goto exit;
22864 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022865 /*
22866 * Validate against the type definition.
22867 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022868type_validation:
22869
22870 if (vctxt->inode->typeDef == NULL) {
22871 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
22872 ret = XML_SCHEMAV_CVC_TYPE_1;
22873 VERROR(ret, NULL,
22874 "The type definition is absent");
22875 goto exit;
22876 }
22877 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
22878 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
22879 ret = XML_SCHEMAV_CVC_TYPE_2;
22880 VERROR(ret, NULL,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022881 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022882 goto exit;
22883 }
22884 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022885 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022886 * during validation against the declaration. This must be done
22887 * _before_ attribute validation.
22888 */
22889 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
22890 if (ret == -1) {
22891 VERROR_INT("xmlSchemaValidateElem",
22892 "calling xmlSchemaXPathEvaluate()");
22893 goto internal_error;
22894 }
22895 /*
22896 * Validate attributes.
22897 */
22898 if (IS_COMPLEX_TYPE(vctxt->inode->typeDef)) {
22899 if ((vctxt->nbAttrInfos != 0) ||
22900 (vctxt->inode->typeDef->attributeUses != NULL)) {
22901
22902 ret = xmlSchemaVAttributesComplex(vctxt);
22903 }
22904 } else if (vctxt->nbAttrInfos != 0) {
22905
22906 ret = xmlSchemaVAttributesSimple(vctxt);
22907 }
22908 /*
22909 * Clear registered attributes.
22910 */
22911 if (vctxt->nbAttrInfos != 0)
22912 xmlSchemaClearAttrInfos(vctxt);
22913 if (ret == -1) {
22914 VERROR_INT("xmlSchemaValidateElem",
22915 "calling attributes validation");
22916 goto internal_error;
22917 }
22918 /*
22919 * Don't return an error if attributes are invalid on purpose.
22920 */
22921 ret = 0;
22922
22923exit:
22924 if (ret != 0)
22925 vctxt->skipDepth = vctxt->depth;
22926 return (ret);
22927internal_error:
22928 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022929}
22930
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022931#ifdef XML_SCHEMA_READER_ENABLED
22932static int
22933xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000022934{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022935 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
22936 int depth, nodeType, ret = 0, consumed;
22937 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000022938
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022939 vctxt->depth = -1;
22940 ret = xmlTextReaderRead(vctxt->reader);
22941 /*
22942 * Move to the document element.
22943 */
22944 while (ret == 1) {
22945 nodeType = xmlTextReaderNodeType(vctxt->reader);
22946 if (nodeType == XML_ELEMENT_NODE)
22947 goto root_found;
22948 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022949 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022950 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022951
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022952root_found:
22953
22954 do {
22955 depth = xmlTextReaderDepth(vctxt->reader);
22956 nodeType = xmlTextReaderNodeType(vctxt->reader);
22957
22958 if (nodeType == XML_ELEMENT_NODE) {
22959
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022960 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022961 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
22962 VERROR_INT("xmlSchemaVReaderWalk",
22963 "calling xmlSchemaValidatorPushElem()");
22964 goto internal_error;
22965 }
22966 ielem = vctxt->inode;
22967 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
22968 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
22969 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
22970 /*
22971 * Is the element empty?
22972 */
22973 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
22974 if (ret == -1) {
22975 VERROR_INT("xmlSchemaVReaderWalk",
22976 "calling xmlTextReaderIsEmptyElement()");
22977 goto internal_error;
22978 }
22979 if (ret) {
22980 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
22981 }
22982 /*
22983 * Register attributes.
22984 */
22985 vctxt->nbAttrInfos = 0;
22986 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
22987 if (ret == -1) {
22988 VERROR_INT("xmlSchemaVReaderWalk",
22989 "calling xmlTextReaderMoveToFirstAttribute()");
22990 goto internal_error;
22991 }
22992 if (ret == 1) {
22993 do {
22994 /*
22995 * VAL TODO: How do we know that the reader works on a
22996 * node tree, to be able to pass a node here?
22997 */
22998 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
22999 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
23000 xmlTextReaderNamespaceUri(vctxt->reader), 1,
23001 xmlTextReaderValue(vctxt->reader), 1) == -1) {
23002
23003 VERROR_INT("xmlSchemaVReaderWalk",
23004 "calling xmlSchemaValidatorPushAttribute()");
23005 goto internal_error;
23006 }
23007 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
23008 if (ret == -1) {
23009 VERROR_INT("xmlSchemaVReaderWalk",
23010 "calling xmlTextReaderMoveToFirstAttribute()");
23011 goto internal_error;
23012 }
23013 } while (ret == 1);
23014 /*
23015 * Back to element position.
23016 */
23017 ret = xmlTextReaderMoveToElement(vctxt->reader);
23018 if (ret == -1) {
23019 VERROR_INT("xmlSchemaVReaderWalk",
23020 "calling xmlTextReaderMoveToElement()");
23021 goto internal_error;
23022 }
23023 }
23024 /*
23025 * Validate the element.
23026 */
23027 ret= xmlSchemaValidateElem(vctxt);
23028 if (ret != 0) {
23029 if (ret == -1) {
23030 VERROR_INT("xmlSchemaVReaderWalk",
23031 "calling xmlSchemaValidateElem()");
23032 goto internal_error;
23033 }
23034 goto exit;
23035 }
23036 if (vctxt->depth == vctxt->skipDepth) {
23037 int curDepth;
23038 /*
23039 * Skip all content.
23040 */
23041 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
23042 ret = xmlTextReaderRead(vctxt->reader);
23043 curDepth = xmlTextReaderDepth(vctxt->reader);
23044 while ((ret == 1) && (curDepth != depth)) {
23045 ret = xmlTextReaderRead(vctxt->reader);
23046 curDepth = xmlTextReaderDepth(vctxt->reader);
23047 }
23048 if (ret < 0) {
23049 /*
23050 * VAL TODO: A reader error occured; what to do here?
23051 */
23052 ret = 1;
23053 goto exit;
23054 }
23055 }
23056 goto leave_elem;
23057 }
23058 /*
23059 * READER VAL TODO: Is an END_ELEM really never called
23060 * if the elem is empty?
23061 */
23062 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23063 goto leave_elem;
23064 } else if (nodeType == END_ELEM) {
23065 /*
23066 * Process END of element.
23067 */
23068leave_elem:
23069 ret = xmlSchemaValidatorPopElem(vctxt);
23070 if (ret != 0) {
23071 if (ret < 0) {
23072 VERROR_INT("xmlSchemaVReaderWalk",
23073 "calling xmlSchemaValidatorPopElem()");
23074 goto internal_error;
23075 }
23076 goto exit;
23077 }
23078 if (vctxt->depth >= 0)
23079 ielem = vctxt->inode;
23080 else
23081 ielem = NULL;
23082 } else if ((nodeType == XML_TEXT_NODE) ||
23083 (nodeType == XML_CDATA_SECTION_NODE) ||
23084 (nodeType == WHTSP) ||
23085 (nodeType == SIGN_WHTSP)) {
23086 /*
23087 * Process character content.
23088 */
23089 xmlChar *value;
23090
23091 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
23092 nodeType = XML_TEXT_NODE;
23093
23094 value = xmlTextReaderValue(vctxt->reader);
23095 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
23096 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
23097 if (! consumed)
23098 xmlFree(value);
23099 if (ret == -1) {
23100 VERROR_INT("xmlSchemaVReaderWalk",
23101 "calling xmlSchemaVPushText()");
23102 goto internal_error;
23103 }
23104 } else if ((nodeType == XML_ENTITY_NODE) ||
23105 (nodeType == XML_ENTITY_REF_NODE)) {
23106 /*
23107 * VAL TODO: What to do with entities?
23108 */
23109 TODO
23110 }
23111 /*
23112 * Read next node.
23113 */
23114 ret = xmlTextReaderRead(vctxt->reader);
23115 } while (ret == 1);
23116
23117exit:
23118 return (ret);
23119internal_error:
23120 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023121}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023122#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000023123
23124/************************************************************************
23125 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023126 * SAX validation handlers *
Daniel Veillard4255d502002-04-16 15:50:10 +000023127 * *
23128 ************************************************************************/
23129
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023130#ifdef XML_SCHEMA_SAX_ENABLED
23131/*
23132* Process text content.
23133*/
23134static void
23135xmlSchemaSAXHandleText(void *ctx,
23136 const xmlChar * ch,
23137 int len)
23138{
23139 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23140
23141 if (vctxt->depth < 0)
23142 return;
23143 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23144 return;
23145 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23146 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23147 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
23148 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23149 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23150 "calling xmlSchemaVPushText()");
23151 vctxt->err = -1;
23152 xmlStopParser(vctxt->parserCtxt);
23153 }
23154}
23155
23156/*
23157* Process CDATA content.
23158*/
23159static void
23160xmlSchemaSAXHandleCDataSection(void *ctx,
23161 const xmlChar * ch,
23162 int len)
23163{
23164 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23165
23166 if (vctxt->depth < 0)
23167 return;
23168 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23169 return;
23170 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23171 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23172 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
23173 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23174 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23175 "calling xmlSchemaVPushText()");
23176 vctxt->err = -1;
23177 xmlStopParser(vctxt->parserCtxt);
23178 }
23179}
23180
23181static void
23182xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
23183 const xmlChar * name ATTRIBUTE_UNUSED)
23184{
23185 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23186
23187 if (vctxt->depth < 0)
23188 return;
23189 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23190 return;
23191 /* SAX VAL TODO: What to do here? */
23192 TODO
23193}
23194
23195static void
23196xmlSchemaSAXHandleStartElementNs(void *ctx,
23197 const xmlChar * localname,
23198 const xmlChar * prefix ATTRIBUTE_UNUSED,
23199 const xmlChar * URI,
23200 int nb_namespaces,
23201 const xmlChar ** namespaces,
23202 int nb_attributes,
23203 int nb_defaulted ATTRIBUTE_UNUSED,
23204 const xmlChar ** attributes)
23205{
23206 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23207 int ret;
23208 xmlSchemaNodeInfoPtr ielem;
23209 int i, j;
23210
23211 /*
23212 * SAX VAL TODO: What to do with nb_defaulted?
23213 */
23214 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023215 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023216 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023217 vctxt->depth++;
23218 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023219 return;
23220 /*
23221 * Push the element.
23222 */
23223 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23224 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23225 "calling xmlSchemaValidatorPushElem()");
23226 goto internal_error;
23227 }
23228 ielem = vctxt->inode;
23229 ielem->localName = localname;
23230 ielem->nsName = URI;
23231 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23232 /*
23233 * Register namespaces on the elem info.
23234 */
23235 if (nb_namespaces != 0) {
23236 /*
23237 * Although the parser builds its own namespace list,
23238 * we have no access to it, so we'll use an own one.
23239 */
23240 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
23241 /*
23242 * Store prefix and namespace name.
23243 */
23244 if (ielem->nsBindings == NULL) {
23245 ielem->nsBindings =
23246 (const xmlChar **) xmlMalloc(10 *
23247 sizeof(const xmlChar *));
23248 if (ielem->nsBindings == NULL) {
23249 xmlSchemaVErrMemory(vctxt,
23250 "allocating namespace bindings for SAX validation",
23251 NULL);
23252 goto internal_error;
23253 }
23254 ielem->nbNsBindings = 0;
23255 ielem->sizeNsBindings = 5;
23256 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
23257 ielem->sizeNsBindings *= 2;
23258 ielem->nsBindings =
23259 (const xmlChar **) xmlRealloc(
23260 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023261 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023262 if (ielem->nsBindings == NULL) {
23263 xmlSchemaVErrMemory(vctxt,
23264 "re-allocating namespace bindings for SAX validation",
23265 NULL);
23266 goto internal_error;
23267 }
23268 }
23269
23270 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
23271 if (namespaces[j+1][0] == 0) {
23272 /*
23273 * Handle xmlns="".
23274 */
23275 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
23276 } else
23277 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
23278 namespaces[j+1];
23279 ielem->nbNsBindings++;
23280 }
23281 }
23282 /*
23283 * Register attributes.
23284 * SAX VAL TODO: We are not adding namespace declaration
23285 * attributes yet.
23286 */
23287 if (nb_attributes != 0) {
23288 xmlChar *value;
23289
23290 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
23291 /*
23292 * Duplicate the value.
23293 */
23294 value = xmlStrndup(attributes[j+3],
23295 attributes[j+4] - attributes[j+3]);
23296 ret = xmlSchemaValidatorPushAttribute(vctxt,
23297 NULL, attributes[j], attributes[j+2], 0,
23298 value, 1);
23299 if (ret == -1) {
23300 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23301 "calling xmlSchemaValidatorPushAttribute()");
23302 goto internal_error;
23303 }
23304 }
23305 }
23306 /*
23307 * Validate the element.
23308 */
23309 ret = xmlSchemaValidateElem(vctxt);
23310 if (ret != 0) {
23311 if (ret == -1) {
23312 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23313 "calling xmlSchemaValidateElem()");
23314 goto internal_error;
23315 }
23316 goto exit;
23317 }
23318
23319exit:
23320 return;
23321internal_error:
23322 vctxt->err = -1;
23323 xmlStopParser(vctxt->parserCtxt);
23324 return;
23325}
23326
23327static void
23328xmlSchemaSAXHandleEndElementNs(void *ctx,
23329 const xmlChar * localname ATTRIBUTE_UNUSED,
23330 const xmlChar * prefix ATTRIBUTE_UNUSED,
23331 const xmlChar * URI ATTRIBUTE_UNUSED)
23332{
23333 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23334 int res;
23335
23336 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023337 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023338 */
23339 if (vctxt->skipDepth != -1) {
23340 if (vctxt->depth > vctxt->skipDepth) {
23341 vctxt->depth--;
23342 return;
23343 } else
23344 vctxt->skipDepth = -1;
23345 }
23346 /*
23347 * SAX VAL TODO: Just a temporary check.
23348 */
23349 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
23350 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
23351 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23352 "elem pop mismatch");
23353 }
23354 res = xmlSchemaValidatorPopElem(vctxt);
23355 if (res != 0) {
23356 if (res < 0) {
23357 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23358 "calling xmlSchemaValidatorPopElem()");
23359 goto internal_error;
23360 }
23361 goto exit;
23362 }
23363exit:
23364 return;
23365internal_error:
23366 vctxt->err = -1;
23367 xmlStopParser(vctxt->parserCtxt);
23368 return;
23369}
23370#endif
23371
Daniel Veillard4255d502002-04-16 15:50:10 +000023372/************************************************************************
23373 * *
23374 * Validation interfaces *
23375 * *
23376 ************************************************************************/
23377
23378/**
23379 * xmlSchemaNewValidCtxt:
23380 * @schema: a precompiled XML Schemas
23381 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023382 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000023383 *
23384 * Returns the validation context or NULL in case of error
23385 */
23386xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023387xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
23388{
Daniel Veillard4255d502002-04-16 15:50:10 +000023389 xmlSchemaValidCtxtPtr ret;
23390
23391 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
23392 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023393 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000023394 return (NULL);
23395 }
23396 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023397 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
23398 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000023399 return (ret);
23400}
23401
23402/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023403 * xmlSchemaClearValidCtxt:
23404 * @ctxt: the schema validation context
23405 *
23406 * Free the resources associated to the schema validation context;
23407 * leaves some fields alive intended for reuse of the context.
23408 */
23409static void
23410xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
23411{
23412 if (vctxt == NULL)
23413 return;
23414
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000023415 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023416 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023417 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000023418#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023419 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000023420#endif
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023421 if (vctxt->value != NULL) {
23422 xmlSchemaFreeValue(vctxt->value);
23423 vctxt->value = NULL;
23424 }
23425 /*
23426 * Augmented IDC information.
23427 */
23428 if (vctxt->aidcs != NULL) {
23429 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
23430 do {
23431 next = cur->next;
23432 xmlFree(cur);
23433 cur = next;
23434 } while (cur != NULL);
23435 vctxt->aidcs = NULL;
23436 }
23437 if (vctxt->idcNodes != NULL) {
23438 int i;
23439 xmlSchemaPSVIIDCNodePtr item;
23440
23441 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023442 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023443 xmlFree(item->keys);
23444 xmlFree(item);
23445 }
23446 xmlFree(vctxt->idcNodes);
23447 vctxt->idcNodes = NULL;
23448 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023449 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023450 * Note that we won't delete the XPath state pool here.
23451 */
23452 if (vctxt->xpathStates != NULL) {
23453 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
23454 vctxt->xpathStates = NULL;
23455 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023456 /*
23457 * Attribute info.
23458 */
23459 if (vctxt->nbAttrInfos != 0) {
23460 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023461 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023462 /*
23463 * Element info.
23464 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023465 if (vctxt->elemInfos != NULL) {
23466 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023467 xmlSchemaNodeInfoPtr ei;
23468
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023469 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023470 ei = vctxt->elemInfos[i];
23471 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023472 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023473 xmlSchemaClearElemInfo(ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023474 }
23475 }
23476}
23477
23478/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023479 * xmlSchemaFreeValidCtxt:
23480 * @ctxt: the schema validation context
23481 *
23482 * Free the resources associated to the schema validation context
23483 */
23484void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023485xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
23486{
Daniel Veillard4255d502002-04-16 15:50:10 +000023487 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023488 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000023489 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023490 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023491 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023492 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023493 if (ctxt->idcNodes != NULL) {
23494 int i;
23495 xmlSchemaPSVIIDCNodePtr item;
23496
23497 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023498 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023499 xmlFree(item->keys);
23500 xmlFree(item);
23501 }
23502 xmlFree(ctxt->idcNodes);
23503 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023504 if (ctxt->idcKeys != NULL) {
23505 int i;
23506 for (i = 0; i < ctxt->nbIdcKeys; i++)
23507 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
23508 xmlFree(ctxt->idcKeys);
23509 }
23510
23511 if (ctxt->xpathStates != NULL)
23512 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
23513 if (ctxt->xpathStatePool != NULL)
23514 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
23515
23516 /*
23517 * Augmented IDC information.
23518 */
23519 if (ctxt->aidcs != NULL) {
23520 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
23521 do {
23522 next = cur->next;
23523 xmlFree(cur);
23524 cur = next;
23525 } while (cur != NULL);
23526 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023527 if (ctxt->attrInfos != NULL) {
23528 int i;
23529 xmlSchemaAttrInfoPtr attr;
23530
23531 /* Just a paranoid call to the cleanup. */
23532 if (ctxt->nbAttrInfos != 0)
23533 xmlSchemaClearAttrInfos(ctxt);
23534 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
23535 attr = ctxt->attrInfos[i];
23536 xmlFree(attr);
23537 }
23538 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023539 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023540 if (ctxt->elemInfos != NULL) {
23541 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023542 xmlSchemaNodeInfoPtr ei;
23543
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023544 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023545 ei = ctxt->elemInfos[i];
23546 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023547 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023548 xmlSchemaClearElemInfo(ei);
23549 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023550 }
23551 xmlFree(ctxt->elemInfos);
23552 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023553 if (ctxt->dict != NULL)
23554 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000023555 xmlFree(ctxt);
23556}
23557
23558/**
23559 * xmlSchemaSetValidErrors:
23560 * @ctxt: a schema validation context
23561 * @err: the error function
23562 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000023563 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000023564 *
William M. Brack2f2a6632004-08-20 23:09:47 +000023565 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000023566 */
23567void
23568xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023569 xmlSchemaValidityErrorFunc err,
23570 xmlSchemaValidityWarningFunc warn, void *ctx)
23571{
Daniel Veillard4255d502002-04-16 15:50:10 +000023572 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023573 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000023574 ctxt->error = err;
23575 ctxt->warning = warn;
23576 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023577 if (ctxt->pctxt != NULL)
23578 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000023579}
23580
23581/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000023582 * xmlSchemaGetValidErrors:
23583 * @ctxt: a XML-Schema validation context
23584 * @err: the error function result
23585 * @warn: the warning function result
23586 * @ctx: the functions context result
23587 *
23588 * Get the error and warning callback informations
23589 *
23590 * Returns -1 in case of error and 0 otherwise
23591 */
23592int
23593xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
23594 xmlSchemaValidityErrorFunc * err,
23595 xmlSchemaValidityWarningFunc * warn, void **ctx)
23596{
23597 if (ctxt == NULL)
23598 return (-1);
23599 if (err != NULL)
23600 *err = ctxt->error;
23601 if (warn != NULL)
23602 *warn = ctxt->warning;
23603 if (ctx != NULL)
23604 *ctx = ctxt->userData;
23605 return (0);
23606}
23607
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023608
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023609/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023610 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023611 * @ctxt: a schema validation context
23612 * @options: a combination of xmlSchemaValidOption
23613 *
23614 * Sets the options to be used during the validation.
23615 *
23616 * Returns 0 in case of success, -1 in case of an
23617 * API error.
23618 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023619int
23620xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
23621 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023622
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023623{
23624 int i;
23625
23626 if (ctxt == NULL)
23627 return (-1);
23628 /*
23629 * WARNING: Change the start value if adding to the
23630 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023631 * TODO: Is there an other, more easy to maintain,
23632 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023633 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023634 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023635 if (options & 1<<i)
23636 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023637 }
23638 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023639 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023640}
23641
23642/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023643 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023644 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023645 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023646 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023647 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023648 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023649 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023650int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023651xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023652
23653{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023654 if (ctxt == NULL)
23655 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023656 else
23657 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023658}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023659
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023660static int
23661xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
23662{
23663 xmlAttrPtr attr;
23664 int ret = 0;
23665 xmlSchemaNodeInfoPtr ielem = NULL;
23666 xmlNodePtr node, valRoot;
23667 const xmlChar *nsName;
23668
23669 /* DOC VAL TODO: Move this to the start function. */
23670 valRoot = xmlDocGetRootElement(vctxt->doc);
23671 if (valRoot == NULL) {
23672 /* VAL TODO: Error code? */
23673 VERROR(1, NULL, "The document has no document element");
23674 return (1);
23675 }
23676 vctxt->depth = -1;
23677 vctxt->validationRoot = valRoot;
23678 node = valRoot;
23679 while (node != NULL) {
23680 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23681 goto next_sibling;
23682 if (node->type == XML_ELEMENT_NODE) {
23683
23684 /*
23685 * Init the node-info.
23686 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023687 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023688 if (xmlSchemaValidatorPushElem(vctxt) == -1)
23689 goto internal_error;
23690 ielem = vctxt->inode;
23691 ielem->node = node;
23692 ielem->localName = node->name;
23693 if (node->ns != NULL)
23694 ielem->nsName = node->ns->href;
23695 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23696 /*
23697 * Register attributes.
23698 * DOC VAL TODO: We do not register namespace declaration
23699 * attributes yet.
23700 */
23701 vctxt->nbAttrInfos = 0;
23702 if (node->properties != NULL) {
23703 attr = node->properties;
23704 do {
23705 if (attr->ns != NULL)
23706 nsName = attr->ns->href;
23707 else
23708 nsName = NULL;
23709 ret = xmlSchemaValidatorPushAttribute(vctxt,
23710 (xmlNodePtr) attr,
23711 attr->name, nsName, 0,
23712 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
23713 if (ret == -1) {
23714 VERROR_INT("xmlSchemaDocWalk",
23715 "calling xmlSchemaValidatorPushAttribute()");
23716 goto internal_error;
23717 }
23718 attr = attr->next;
23719 } while (attr);
23720 }
23721 /*
23722 * Validate the element.
23723 */
23724 ret = xmlSchemaValidateElem(vctxt);
23725 if (ret != 0) {
23726 if (ret == -1) {
23727 VERROR_INT("xmlSchemaDocWalk",
23728 "calling xmlSchemaValidateElem()");
23729 goto internal_error;
23730 }
23731 /*
23732 * Don't stop validation; just skip the content
23733 * of this element.
23734 */
23735 goto leave_node;
23736 }
23737 if ((vctxt->skipDepth != -1) &&
23738 (vctxt->depth >= vctxt->skipDepth))
23739 goto leave_node;
23740 } else if ((node->type == XML_TEXT_NODE) ||
23741 (node->type == XML_CDATA_SECTION_NODE)) {
23742 /*
23743 * Process character content.
23744 */
23745 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23746 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23747 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
23748 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
23749 if (ret < 0) {
23750 VERROR_INT("xmlSchemaVDocWalk",
23751 "calling xmlSchemaVPushText()");
23752 goto internal_error;
23753 }
23754 /*
23755 * DOC VAL TODO: Should we skip further validation of the
23756 * element content here?
23757 */
23758 } else if ((node->type == XML_ENTITY_NODE) ||
23759 (node->type == XML_ENTITY_REF_NODE)) {
23760 /*
23761 * DOC VAL TODO: What to do with entities?
23762 */
23763 TODO
23764 } else {
23765 goto leave_node;
23766 /*
23767 * DOC VAL TODO: XInclude nodes, etc.
23768 */
23769 }
23770 /*
23771 * Walk the doc.
23772 */
23773 if (node->children != NULL) {
23774 node = node->children;
23775 continue;
23776 }
23777leave_node:
23778 if (node->type == XML_ELEMENT_NODE) {
23779 /*
23780 * Leaving the scope of an element.
23781 */
23782 if (node != vctxt->inode->node) {
23783 VERROR_INT("xmlSchemaVDocWalk",
23784 "element position mismatch");
23785 goto internal_error;
23786 }
23787 ret = xmlSchemaValidatorPopElem(vctxt);
23788 if (ret != 0) {
23789 if (ret < 0) {
23790 VERROR_INT("xmlSchemaVDocWalk",
23791 "calling xmlSchemaValidatorPopElem()");
23792 goto internal_error;
23793 }
23794 }
23795 if (node == valRoot)
23796 goto exit;
23797 }
23798next_sibling:
23799 if (node->next != NULL)
23800 node = node->next;
23801 else {
23802 node = node->parent;
23803 goto leave_node;
23804 }
23805 }
23806
23807exit:
23808 return (ret);
23809internal_error:
23810 return (-1);
23811}
23812
23813static int
23814xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
23815{
23816 int ret = 0;
23817
23818 /*
23819 * Some initialization.
23820 */
23821 vctxt->err = 0;
23822 vctxt->nberrors = 0;
23823 vctxt->depth = -1;
23824 vctxt->skipDepth = -1;
23825 /*
23826 * Create a schema + parser if necessary.
23827 */
23828 if (vctxt->schema == NULL) {
23829
23830 if ((vctxt->pctxt == NULL) &&
23831 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
23832 return (-1);
23833
23834 vctxt->schema = xmlSchemaNewSchema(vctxt->pctxt);
23835 if (vctxt->schema == NULL) {
23836 VERROR_INT("xmlSchemaVStartValidation",
23837 "creating a schema");
23838 return (-1);
23839 }
23840 vctxt->xsiAssemble = 1;
23841 } else
23842 vctxt->xsiAssemble = 0;
23843 /*
23844 * Augment the IDC definitions.
23845 */
23846 if (vctxt->schema->idcDef != NULL) {
23847 xmlHashScan(vctxt->schema->idcDef,
23848 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
23849 }
23850 if (vctxt->doc != NULL) {
23851 /*
23852 * Tree validation.
23853 */
23854 ret = xmlSchemaVDocWalk(vctxt);
Daniel Veillard39e5c892005-07-03 22:48:50 +000023855#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023856 } else if (vctxt->reader != NULL) {
23857 /*
23858 * XML Reader validation.
23859 */
23860#ifdef XML_SCHEMA_READER_ENABLED
23861 ret = xmlSchemaVReaderWalk(vctxt);
23862#endif
Daniel Veillard39e5c892005-07-03 22:48:50 +000023863#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023864 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
23865 /*
23866 * SAX validation.
23867 */
23868 /* ret = xmlSAXUserParseFile(ctxt->sax, ctxt, uri); */
23869 ret = xmlParseDocument(vctxt->parserCtxt);
23870 } else {
23871 VERROR_INT("xmlSchemaVStartValidation",
23872 "no instance to validate");
23873 ret = -1;
23874 }
23875
23876 if (vctxt->xsiAssemble) {
23877 if (vctxt->schema != NULL) {
23878 xmlSchemaFree(vctxt->schema);
23879 vctxt->schema = NULL;
23880 }
23881 }
23882 xmlSchemaClearValidCtxt(vctxt);
23883 if (ret == 0)
23884 ret = vctxt->err;
23885 return (ret);
23886}
23887
23888/**
23889 * xmlSchemaValidateOneElement:
23890 * @ctxt: a schema validation context
23891 * @elem: an element node
23892 *
23893 * Validate a branch of a tree, starting with the given @elem.
23894 *
23895 * Returns 0 if the element and its subtree is valid, a positive error
23896 * code number otherwise and -1 in case of an internal or API error.
23897 */
23898int
23899xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
23900{
23901 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
23902 return (-1);
23903
23904 if (ctxt->schema == NULL)
23905 return (-1);
23906
23907 ctxt->doc = elem->doc;
23908 ctxt->node = elem;
23909 ctxt->validationRoot = elem;
23910 return(xmlSchemaVStart(ctxt));
23911}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023912
Daniel Veillard259f0df2004-08-18 09:13:18 +000023913/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023914 * xmlSchemaValidateDoc:
23915 * @ctxt: a schema validation context
23916 * @doc: a parsed document tree
23917 *
23918 * Validate a document tree in memory.
23919 *
23920 * Returns 0 if the document is schemas valid, a positive error code
23921 * number otherwise and -1 in case of internal or API error.
23922 */
23923int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023924xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
23925{
Daniel Veillard4255d502002-04-16 15:50:10 +000023926 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023927 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023928
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023929 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023930 ctxt->node = xmlDocGetRootElement(doc);
23931 if (ctxt->node == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023932 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023933 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
23934 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023935 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023936 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023937 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023938 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023939 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000023940}
23941
23942/**
23943 * xmlSchemaValidateStream:
23944 * @ctxt: a schema validation context
23945 * @input: the input to use for reading the data
23946 * @enc: an optional encoding information
23947 * @sax: a SAX handler for the resulting events
23948 * @user_data: the context to provide to the SAX handler.
23949 *
23950 * Validate a document tree in memory.
23951 *
23952 * Returns 0 if the document is schemas valid, a positive error code
23953 * number otherwise and -1 in case of internal or API error.
23954 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023955int
Daniel Veillard4255d502002-04-16 15:50:10 +000023956xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023957 xmlParserInputBufferPtr input, xmlCharEncoding enc,
23958 xmlSAXHandlerPtr sax, void *user_data)
23959{
Daniel Veillard4255d502002-04-16 15:50:10 +000023960 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023961 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023962 ctxt->input = input;
23963 ctxt->enc = enc;
23964 ctxt->sax = sax;
23965 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023966 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000023967}
23968
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023969/**
23970 * xmlSchemaValidateFile:
23971 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000023972 * @filename: the URI of the instance
23973 * @options: a future set of options, currently unused
23974 *
23975 * Do a schemas validation of the given resource, it will use the
23976 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023977 *
23978 * Returns 0 if the document is valid, a positive error code
23979 * number otherwise and -1 in case of an internal or API error.
23980 */
23981int
23982xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000023983 const char * filename,
23984 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023985{
Daniel Veillard81562d22005-06-15 13:27:56 +000023986#ifdef XML_SCHEMA_SAX_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023987 int ret;
23988
23989 if ((ctxt == NULL) || (filename == NULL))
23990 return (-1);
23991
23992 ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
23993 if (ctxt->sax == NULL) {
23994 xmlSchemaVErrMemory(ctxt,
23995 "creating SAX handler", NULL);
23996 return (-1);
23997 }
23998 memset(ctxt->sax, 0, sizeof(xmlSAXHandler));
23999 ctxt->parserCtxt = xmlCreateFileParserCtxt(filename);
24000 if (ctxt->parserCtxt == NULL) {
24001 xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) ctxt,
24002 "xmlSchemaValidateFile", "creating a parser context");
24003 xmlFree(ctxt->sax);
24004 return (-1);
24005 }
24006#ifdef LIBXML_SAX1_ENABLED
24007 if (ctxt->parserCtxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
24008#endif /* LIBXML_SAX1_ENABLED */
24009 xmlFree(ctxt->parserCtxt->sax);
24010 /*
24011 * Init the SAX handler.
24012 */
24013 ctxt->sax->startElementNs = xmlSchemaSAXHandleStartElementNs;
24014 ctxt->sax->endElementNs = xmlSchemaSAXHandleEndElementNs;
24015 /*
24016 * Note that we use the same text-function for both, to prevent
24017 * the parser from testing for ignorable whitespace.
24018 */
24019 ctxt->sax->ignorableWhitespace = xmlSchemaSAXHandleText;
24020 ctxt->sax->characters = xmlSchemaSAXHandleText;
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024021
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024022 ctxt->sax->cdataBlock = xmlSchemaSAXHandleCDataSection;
24023 ctxt->sax->reference = xmlSchemaSAXHandleReference;
24024 ctxt->sax->initialized = XML_SAX2_MAGIC;
24025 /*
24026 * Init the parser context.
24027 */
24028 ctxt->parserCtxt->sax = ctxt->sax;
24029 ctxt->parserCtxt->sax2 = 1;
24030 ctxt->parserCtxt->userData = ctxt;
24031 /* VAL TODO: Set error handlers. */
24032
24033 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024034 ret = xmlSchemaVStart(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024035
24036 /*
24037 * URGENT VAL TODO: What to do with well-formedness errors?
24038 */
24039 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
24040 ret = ctxt->parserCtxt->errNo;
24041 if (ret == 0)
24042 /* URGENT VAL TODO: Error code? */
24043 ret = 1;
24044 xmlSchemaErr((xmlSchemaAbstractCtxtPtr) ctxt, ret, NULL,
24045 "The instance document '%s' is not well-formed",
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024046 BAD_CAST filename, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024047 }
24048 ctxt->parserCtxt->sax = NULL;
24049 xmlFreeParserCtxt(ctxt->parserCtxt);
24050 xmlFree(ctxt->sax);
24051 ctxt->sax = NULL;
24052
24053 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000024054#else
24055 return (-1);
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024056#endif /* XML_SCHEMA_SAX_ENABLED */
Daniel Veillard81562d22005-06-15 13:27:56 +000024057}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024058
24059#ifdef XML_SCHEMA_READER_ENABLED
Daniel Veillard81562d22005-06-15 13:27:56 +000024060/**
24061 * xmlSchemaValidateReader:
24062 * @ctxt: a schema validation context
24063 * @reader: an XML reader.
24064 *
24065 * Do a schemas validation of the given resource, using the reader.
24066 *
24067 * Returns 0 if the document is valid, a positive error code
24068 * number otherwise and -1 in case of an internal or API error.
24069 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024070int
24071xmlSchemaValidateReader(xmlSchemaValidCtxtPtr ctxt,
24072 xmlTextReaderPtr reader)
24073{
24074 if ((ctxt == NULL) || (reader == NULL))
24075 return (-1);
24076 ctxt->reader = reader;
24077 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
24078 return(xmlSchemaVStart(ctxt, NULL));
24079}
24080#endif /* XML_SCHEMA_READER_ENABLED */
24081
Daniel Veillard5d4644e2005-04-01 13:11:58 +000024082#define bottom_xmlschemas
24083#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000024084#endif /* LIBXML_SCHEMAS_ENABLED */