blob: 719262e9788d0318dda76e588e26b9ff27cdefd4 [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
667 xmlTextReaderPtr reader;
668
669 xmlSchemaAttrInfoPtr *attrInfos;
670 int nbAttrInfos;
671 int sizeAttrInfos;
672
673 int skipDepth;
Daniel Veillard4255d502002-04-16 15:50:10 +0000674};
675
Daniel Veillard1d913862003-11-21 00:28:39 +0000676/*
677 * These are the entries in the schemas importSchemas hash table
678 */
679typedef struct _xmlSchemaImport xmlSchemaImport;
680typedef xmlSchemaImport *xmlSchemaImportPtr;
681struct _xmlSchemaImport {
682 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000683 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000684 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000685 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000686};
Daniel Veillard4255d502002-04-16 15:50:10 +0000687
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000688/*
689 * These are the entries associated to includes in a schemas
690 */
691typedef struct _xmlSchemaInclude xmlSchemaInclude;
692typedef xmlSchemaInclude *xmlSchemaIncludePtr;
693struct _xmlSchemaInclude {
694 xmlSchemaIncludePtr next;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000695 const xmlChar *schemaLocation;
696 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000697 const xmlChar *origTargetNamespace;
698 const xmlChar *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000699};
700
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000701/**
702 * xmlSchemaSubstGroup:
703 *
704 *
705 */
706typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
707typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
708struct _xmlSchemaSubstGroup {
709 xmlSchemaElementPtr head;
710 xmlSchemaItemListPtr members;
711};
712
Daniel Veillard4255d502002-04-16 15:50:10 +0000713/************************************************************************
714 * *
715 * Some predeclarations *
716 * *
717 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000718
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000719static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
720 xmlSchemaPtr schema,
721 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000722static void
723xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
724 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000725static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +0000726xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
727static int
William M. Brack2f2a6632004-08-20 23:09:47 +0000728xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
729 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000730static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000731xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
732 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +0000733static void
734xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000735static xmlSchemaWhitespaceValueType
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +0000736xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000737static xmlSchemaTreeItemPtr
738xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
739 xmlNodePtr node, xmlSchemaTypeType type,
740 int withParticle);
741static const xmlChar *
742xmlSchemaCompTypeToString(xmlSchemaTypeType type);
743static xmlSchemaTypeLinkPtr
744xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000745static void
746xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
747 const char *funcName,
748 const char *message);
749static int
750xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
751 xmlSchemaTypePtr baseType,
752 int subset);
753static void
754xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
755 xmlSchemaParserCtxtPtr ctxt,
756 const xmlChar * name ATTRIBUTE_UNUSED);
William M. Brack87640d52004-04-17 14:58:15 +0000757
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000758/************************************************************************
759 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000760 * Helper functions *
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000761 * *
762 ************************************************************************/
763
764/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000765 * xmlSchemaCompTypeToString:
766 * @type: the type of the schema item
767 *
768 * Returns the component name of a schema item.
769 */
770static const xmlChar *
771xmlSchemaCompTypeToString(xmlSchemaTypeType type)
772{
773 switch (type) {
774 case XML_SCHEMA_TYPE_SIMPLE:
775 return(BAD_CAST "simple type definition");
776 case XML_SCHEMA_TYPE_COMPLEX:
777 return(BAD_CAST "complex type definition");
778 case XML_SCHEMA_TYPE_ELEMENT:
779 return(BAD_CAST "element declaration");
780 case XML_SCHEMA_TYPE_ATTRIBUTE:
781 return(BAD_CAST "attribute declaration");
782 case XML_SCHEMA_TYPE_GROUP:
783 return(BAD_CAST "model group definition");
784 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
785 return(BAD_CAST "attribute group definition");
786 case XML_SCHEMA_TYPE_NOTATION:
787 return(BAD_CAST "notation declaration");
788 case XML_SCHEMA_TYPE_SEQUENCE:
789 return(BAD_CAST "model group (sequence)");
790 case XML_SCHEMA_TYPE_CHOICE:
791 return(BAD_CAST "model group (choice)");
792 case XML_SCHEMA_TYPE_ALL:
793 return(BAD_CAST "model group (all)");
794 case XML_SCHEMA_TYPE_PARTICLE:
795 return(BAD_CAST "particle");
796 default:
797 return(BAD_CAST "Not a schema component");
798 }
799}
800
801/**
802 * xmlSchemaGetComponentNode:
803 * @item: a schema component
804 *
805 * Returns node associated with the schema component.
806 * NOTE that such a node need not be available; plus, a component's
807 * node need not to reflect the component directly, since there is no
808 * one-to-one relationship between the XML Schema representation and
809 * the component representation.
810 */
811static xmlNodePtr
812xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
813{
814 switch (item->type) {
815 case XML_SCHEMA_TYPE_ELEMENT:
816 return (((xmlSchemaElementPtr) item)->node);
817 case XML_SCHEMA_TYPE_ATTRIBUTE:
818 return (((xmlSchemaAttributePtr) item)->node);
819 case XML_SCHEMA_TYPE_COMPLEX:
820 case XML_SCHEMA_TYPE_SIMPLE:
821 return (((xmlSchemaTypePtr) item)->node);
822 case XML_SCHEMA_TYPE_ANY:
823 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
824 return (((xmlSchemaWildcardPtr) item)->node);
825 case XML_SCHEMA_TYPE_PARTICLE:
826 return (((xmlSchemaParticlePtr) item)->node);
827 case XML_SCHEMA_TYPE_SEQUENCE:
828 case XML_SCHEMA_TYPE_CHOICE:
829 case XML_SCHEMA_TYPE_ALL:
830 return (((xmlSchemaModelGroupPtr) item)->node);
831 case XML_SCHEMA_TYPE_GROUP:
832 return (((xmlSchemaModelGroupDefPtr) item)->node);
833 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
834 return (((xmlSchemaAttributeGroupPtr) item)->node);
835 case XML_SCHEMA_TYPE_IDC_UNIQUE:
836 case XML_SCHEMA_TYPE_IDC_KEY:
837 case XML_SCHEMA_TYPE_IDC_KEYREF:
838 return (((xmlSchemaIDCPtr) item)->node);
839 default:
840 return (NULL);
841 }
842}
843
844#if 0
845/**
846 * xmlSchemaGetNextComponent:
847 * @item: a schema component
848 *
849 * Returns the next sibling of the schema component.
850 */
851static xmlSchemaBasicItemPtr
852xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
853{
854 switch (item->type) {
855 case XML_SCHEMA_TYPE_ELEMENT:
856 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
857 case XML_SCHEMA_TYPE_ATTRIBUTE:
858 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
859 case XML_SCHEMA_TYPE_COMPLEX:
860 case XML_SCHEMA_TYPE_SIMPLE:
861 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
862 case XML_SCHEMA_TYPE_ANY:
863 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
864 return (NULL);
865 case XML_SCHEMA_TYPE_PARTICLE:
866 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
867 case XML_SCHEMA_TYPE_SEQUENCE:
868 case XML_SCHEMA_TYPE_CHOICE:
869 case XML_SCHEMA_TYPE_ALL:
870 return (NULL);
871 case XML_SCHEMA_TYPE_GROUP:
872 return (NULL);
873 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
874 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
875 case XML_SCHEMA_TYPE_IDC_UNIQUE:
876 case XML_SCHEMA_TYPE_IDC_KEY:
877 case XML_SCHEMA_TYPE_IDC_KEYREF:
878 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
879 default:
880 return (NULL);
881 }
882}
883#endif
884
885/**
886 * xmlSchemaGetAttrName:
887 * @attr: the attribute declaration/use
888 *
889 * Returns the name of the attribute; if the attribute
890 * is a reference, the name of the referenced global type will be returned.
891 */
892static const xmlChar *
893xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
894{
895 if (attr->ref != NULL)
896 return(attr->ref);
897 else
898 return(attr->name);
899}
900
901/**
902 * xmlSchemaGetAttrTargetNsURI:
903 * @type: the type (element or attribute)
904 *
905 * Returns the target namespace URI of the type; if the type is a reference,
906 * the target namespace of the referenced type will be returned.
907 */
908static const xmlChar *
909xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
910{
911 if (attr->ref != NULL)
912 return (attr->refNs);
913 else
914 return(attr->targetNamespace);
915}
916
917/**
918 * xmlSchemaFormatQName:
919 * @buf: the string buffer
920 * @namespaceName: the namespace name
921 * @localName: the local name
922 *
923 * Returns the given QName in the format "{namespaceName}localName" or
924 * just "localName" if @namespaceName is NULL.
925 *
926 * Returns the localName if @namespaceName is NULL, a formatted
927 * string otherwise.
928 */
929static const xmlChar*
930xmlSchemaFormatQName(xmlChar **buf,
931 const xmlChar *namespaceName,
932 const xmlChar *localName)
933{
934 FREE_AND_NULL(*buf)
935 if (namespaceName == NULL)
936 return(localName);
937
938 *buf = xmlStrdup(BAD_CAST "{");
939 *buf = xmlStrcat(*buf, namespaceName);
940 *buf = xmlStrcat(*buf, BAD_CAST "}");
941 *buf = xmlStrcat(*buf, localName);
942
943 return ((const xmlChar *) *buf);
944}
945
946static const xmlChar*
947xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
948{
949 if (ns != NULL)
950 return (xmlSchemaFormatQName(buf, ns->href, localName));
951 else
952 return (xmlSchemaFormatQName(buf, NULL, localName));
953}
954
955static const xmlChar *
956xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
957{
958 switch (item->type) {
959 case XML_SCHEMA_TYPE_ELEMENT:
960 return (((xmlSchemaElementPtr) item)->name);
961 case XML_SCHEMA_TYPE_ATTRIBUTE:
962 return (((xmlSchemaAttributePtr) item)->name);
963 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
964 return (((xmlSchemaAttributeGroupPtr) item)->name);
965 case XML_SCHEMA_TYPE_BASIC:
966 case XML_SCHEMA_TYPE_SIMPLE:
967 case XML_SCHEMA_TYPE_COMPLEX:
968 return (((xmlSchemaTypePtr) item)->name);
969 case XML_SCHEMA_TYPE_GROUP:
970 return (((xmlSchemaModelGroupDefPtr) item)->name);
971 case XML_SCHEMA_TYPE_IDC_KEY:
972 case XML_SCHEMA_TYPE_IDC_UNIQUE:
973 case XML_SCHEMA_TYPE_IDC_KEYREF:
974 return (((xmlSchemaIDCPtr) item)->name);
975 default:
976 /*
977 * Other components cannot have names.
978 */
979 break;
980 }
981 return (NULL);
982}
983
984static const xmlChar *
985xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
986{
987 switch (item->type) {
988 case XML_SCHEMA_TYPE_ELEMENT:
989 return (((xmlSchemaElementPtr) item)->targetNamespace);
990 case XML_SCHEMA_TYPE_ATTRIBUTE:
991 return (((xmlSchemaAttributePtr) item)->targetNamespace);
992 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
993 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
994 case XML_SCHEMA_TYPE_BASIC:
995 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
996 case XML_SCHEMA_TYPE_SIMPLE:
997 case XML_SCHEMA_TYPE_COMPLEX:
998 return (((xmlSchemaTypePtr) item)->targetNamespace);
999 case XML_SCHEMA_TYPE_GROUP:
1000 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1001 case XML_SCHEMA_TYPE_IDC_KEY:
1002 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1003 case XML_SCHEMA_TYPE_IDC_KEYREF:
1004 return (((xmlSchemaIDCPtr) item)->targetNamespace);
1005 default:
1006 /*
1007 * Other components cannot have names.
1008 */
1009 break;
1010 }
1011 return (NULL);
1012}
1013
1014static const xmlChar*
1015xmlSchemaGetComponentQName(xmlChar **buf,
1016 void *item)
1017{
1018 return (xmlSchemaFormatQName(buf,
1019 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1020 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1021}
1022
1023/**
1024 * xmlSchemaWildcardPCToString:
1025 * @pc: the type of processContents
1026 *
1027 * Returns a string representation of the type of
1028 * processContents.
1029 */
1030static const xmlChar *
1031xmlSchemaWildcardPCToString(int pc)
1032{
1033 switch (pc) {
1034 case XML_SCHEMAS_ANY_SKIP:
1035 return (BAD_CAST "skip");
1036 case XML_SCHEMAS_ANY_LAX:
1037 return (BAD_CAST "lax");
1038 case XML_SCHEMAS_ANY_STRICT:
1039 return (BAD_CAST "strict");
1040 default:
1041 return (BAD_CAST "invalid process contents");
1042 }
1043}
1044
1045/**
1046 * xmlSchemaGetCanonValueWhtspExt:
1047 * @val: the precomputed value
1048 * @retValue: the returned value
1049 * @ws: the whitespace type of the value
1050 *
1051 * Get a the cononical representation of the value.
1052 * The caller has to free the returned retValue.
1053 *
1054 * Returns 0 if the value could be built and -1 in case of
1055 * API errors or if the value type is not supported yet.
1056 */
1057static int
1058xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1059 xmlSchemaWhitespaceValueType ws,
1060 xmlChar **retValue)
1061{
1062 int list;
1063 xmlSchemaValType valType;
1064 const xmlChar *value, *value2 = NULL;
1065
1066
1067 if ((retValue == NULL) || (val == NULL))
1068 return (-1);
1069 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1070 *retValue = NULL;
1071 do {
1072 value = NULL;
1073 valType = xmlSchemaGetValType(val);
1074 switch (valType) {
1075 case XML_SCHEMAS_STRING:
1076 case XML_SCHEMAS_NORMSTRING:
1077 case XML_SCHEMAS_ANYSIMPLETYPE:
1078 value = xmlSchemaValueGetAsString(val);
1079 if (value != NULL) {
1080 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1081 value2 = xmlSchemaCollapseString(value);
1082 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1083 value2 = xmlSchemaWhiteSpaceReplace(value);
1084 if (value2 != NULL)
1085 value = value2;
1086 }
1087 break;
1088 default:
1089 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1090 if (value2 != NULL)
1091 xmlFree((xmlChar *) value2);
1092 goto internal_error;
1093 }
1094 value = value2;
1095 }
1096 if (*retValue == NULL)
1097 if (value == NULL) {
1098 if (! list)
1099 *retValue = xmlStrdup(BAD_CAST "");
1100 } else
1101 *retValue = xmlStrdup(value);
1102 else if (value != NULL) {
1103 /* List. */
1104 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1105 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1106 }
1107 FREE_AND_NULL(value2)
1108 val = xmlSchemaValueGetNext(val);
1109 } while (val != NULL);
1110
1111 return (0);
1112internal_error:
1113 if (*retValue != NULL)
1114 xmlFree((xmlChar *) (*retValue));
1115 if (value2 != NULL)
1116 xmlFree((xmlChar *) value2);
1117 return (-1);
1118}
1119
1120/**
1121 * xmlSchemaFormatItemForReport:
1122 * @buf: the string buffer
1123 * @itemDes: the designation of the item
1124 * @itemName: the name of the item
1125 * @item: the item as an object
1126 * @itemNode: the node of the item
1127 * @local: the local name
1128 * @parsing: if the function is used during the parse
1129 *
1130 * Returns a representation of the given item used
1131 * for error reports.
1132 *
1133 * The following order is used to build the resulting
1134 * designation if the arguments are not NULL:
1135 * 1a. If itemDes not NULL -> itemDes
1136 * 1b. If (itemDes not NULL) and (itemName not NULL)
1137 * -> itemDes + itemName
1138 * 2. If the preceding was NULL and (item not NULL) -> item
1139 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1140 *
1141 * If the itemNode is an attribute node, the name of the attribute
1142 * will be appended to the result.
1143 *
1144 * Returns the formatted string and sets @buf to the resulting value.
1145 */
1146static xmlChar*
1147xmlSchemaFormatItemForReport(xmlChar **buf,
1148 const xmlChar *itemDes,
1149 xmlSchemaTypePtr item,
1150 xmlNodePtr itemNode)
1151{
1152 xmlChar *str = NULL;
1153 int named = 1;
1154
1155 if (*buf != NULL) {
1156 xmlFree(*buf);
1157 *buf = NULL;
1158 }
1159
1160 if (itemDes != NULL) {
1161 *buf = xmlStrdup(itemDes);
1162 } else if (item != NULL) {
1163 switch (item->type) {
1164 case XML_SCHEMA_TYPE_BASIC:
1165 if (VARIETY_ATOMIC(item))
1166 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1167 else if (VARIETY_LIST(item))
1168 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
1169 else if (VARIETY_UNION(item))
1170 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1171 else
1172 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1173 *buf = xmlStrcat(*buf, item->name);
1174 *buf = xmlStrcat(*buf, BAD_CAST "'");
1175 break;
1176 case XML_SCHEMA_TYPE_SIMPLE:
1177 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1178 *buf = xmlStrdup(BAD_CAST"");
1179 } else {
1180 *buf = xmlStrdup(BAD_CAST "local ");
1181 }
1182 if (VARIETY_ATOMIC(item))
1183 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1184 else if (VARIETY_LIST(item))
1185 *buf = xmlStrcat(*buf, BAD_CAST "list type");
1186 else if (VARIETY_UNION(item))
1187 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1188 else
1189 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
1190 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1191 *buf = xmlStrcat(*buf, BAD_CAST " '");
1192 *buf = xmlStrcat(*buf, item->name);
1193 *buf = xmlStrcat(*buf, BAD_CAST "'");
1194 }
1195 break;
1196 case XML_SCHEMA_TYPE_COMPLEX:
1197 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1198 *buf = xmlStrdup(BAD_CAST "");
1199 else
1200 *buf = xmlStrdup(BAD_CAST "local ");
1201 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1202 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1203 *buf = xmlStrcat(*buf, BAD_CAST " '");
1204 *buf = xmlStrcat(*buf, item->name);
1205 *buf = xmlStrcat(*buf, BAD_CAST "'");
1206 }
1207 break;
1208 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1209 xmlSchemaAttributePtr attr;
1210
1211 attr = (xmlSchemaAttributePtr) item;
1212 if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
1213 (attr->ref == NULL)) {
1214 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1215 *buf = xmlStrcat(*buf, BAD_CAST " '");
1216 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1217 attr->targetNamespace, attr->name));
1218 FREE_AND_NULL(str)
1219 *buf = xmlStrcat(*buf, BAD_CAST "'");
1220 } else {
1221 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1222 *buf = xmlStrcat(*buf, BAD_CAST " '");
1223 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1224 attr->refNs, attr->ref));
1225 FREE_AND_NULL(str)
1226 *buf = xmlStrcat(*buf, BAD_CAST "'");
1227 }
1228 }
1229 break;
1230 case XML_SCHEMA_TYPE_ELEMENT: {
1231 xmlSchemaElementPtr elem;
1232
1233 elem = (xmlSchemaElementPtr) item;
1234 if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) ||
1235 (elem->ref == NULL)) {
1236 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1237 *buf = xmlStrcat(*buf, BAD_CAST " '");
1238 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1239 elem->targetNamespace, elem->name));
1240 *buf = xmlStrcat(*buf, BAD_CAST "'");
1241 }
1242 }
1243 break;
1244 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1245 case XML_SCHEMA_TYPE_IDC_KEY:
1246 case XML_SCHEMA_TYPE_IDC_KEYREF:
1247 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1248 *buf = xmlStrdup(BAD_CAST "unique '");
1249 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1250 *buf = xmlStrdup(BAD_CAST "key '");
1251 else
1252 *buf = xmlStrdup(BAD_CAST "keyRef '");
1253 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1254 *buf = xmlStrcat(*buf, BAD_CAST "'");
1255 break;
1256 case XML_SCHEMA_TYPE_ANY:
1257 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1258 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1259 ((xmlSchemaWildcardPtr) item)->processContents));
1260 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1261 break;
1262 case XML_SCHEMA_FACET_MININCLUSIVE:
1263 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1264 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1265 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1266 case XML_SCHEMA_FACET_TOTALDIGITS:
1267 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1268 case XML_SCHEMA_FACET_PATTERN:
1269 case XML_SCHEMA_FACET_ENUMERATION:
1270 case XML_SCHEMA_FACET_WHITESPACE:
1271 case XML_SCHEMA_FACET_LENGTH:
1272 case XML_SCHEMA_FACET_MAXLENGTH:
1273 case XML_SCHEMA_FACET_MINLENGTH:
1274 *buf = xmlStrdup(BAD_CAST "facet '");
1275 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1276 *buf = xmlStrcat(*buf, BAD_CAST "'");
1277 break;
1278 case XML_SCHEMA_TYPE_NOTATION:
1279 *buf = xmlStrdup(BAD_CAST "notation");
1280 break;
1281 case XML_SCHEMA_TYPE_GROUP: {
1282 *buf = xmlStrdup(xmlSchemaElemModelGrDef);
1283 *buf = xmlStrcat(*buf, BAD_CAST " '");
1284 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1285 ((xmlSchemaModelGroupDefPtr) item)->targetNamespace,
1286 ((xmlSchemaModelGroupDefPtr) item)->name));
1287 *buf = xmlStrcat(*buf, BAD_CAST "'");
1288 FREE_AND_NULL(str)
1289 }
1290 break;
1291 case XML_SCHEMA_TYPE_SEQUENCE:
1292 case XML_SCHEMA_TYPE_CHOICE:
1293 case XML_SCHEMA_TYPE_ALL:
1294 case XML_SCHEMA_TYPE_PARTICLE:
1295 *buf = xmlStrdup(xmlSchemaCompTypeToString(item->type));
1296 break;
1297 default:
1298 named = 0;
1299 }
1300 } else
1301 named = 0;
1302
1303 if ((named == 0) && (itemNode != NULL)) {
1304 xmlNodePtr elem;
1305
1306 if (itemNode->type == XML_ATTRIBUTE_NODE)
1307 elem = itemNode->parent;
1308 else
1309 elem = itemNode;
1310 *buf = xmlStrdup(BAD_CAST "Element '");
1311 if (elem->ns != NULL) {
1312 *buf = xmlStrcat(*buf,
1313 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1314 FREE_AND_NULL(str)
1315 } else
1316 *buf = xmlStrcat(*buf, elem->name);
1317 *buf = xmlStrcat(*buf, BAD_CAST "'");
1318
1319 }
1320 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1321 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1322 if (itemNode->ns != NULL) {
1323 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1324 itemNode->ns->href, itemNode->name));
1325 FREE_AND_NULL(str)
1326 } else
1327 *buf = xmlStrcat(*buf, itemNode->name);
1328 *buf = xmlStrcat(*buf, BAD_CAST "'");
1329 }
1330 FREE_AND_NULL(str)
1331
1332 return (*buf);
1333}
1334
1335/**
1336 * xmlSchemaFormatFacetEnumSet:
1337 * @buf: the string buffer
1338 * @type: the type holding the enumeration facets
1339 *
1340 * Builds a string consisting of all enumeration elements.
1341 *
1342 * Returns a string of all enumeration elements.
1343 */
1344static const xmlChar *
1345xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1346 xmlChar **buf, xmlSchemaTypePtr type)
1347{
1348 xmlSchemaFacetPtr facet;
1349 xmlSchemaWhitespaceValueType ws;
1350 xmlChar *value = NULL;
1351 int res;
1352
1353 if (*buf != NULL)
1354 xmlFree(*buf);
1355 *buf = NULL;
1356
1357 do {
1358 /*
1359 * Use the whitespace type of the base type.
1360 */
1361 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1362 for (facet = type->facets; facet != NULL; facet = facet->next) {
1363 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1364 continue;
1365 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1366 ws, &value);
1367 if (res == -1) {
1368 xmlSchemaInternalErr(actxt,
1369 "xmlSchemaFormatFacetEnumSet",
1370 "compute the canonical lexical representation");
1371 if (*buf != NULL)
1372 xmlFree(*buf);
1373 *buf = NULL;
1374 return (NULL);
1375 }
1376 if (*buf == NULL)
1377 *buf = xmlStrdup(BAD_CAST "'");
1378 else
1379 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1380 *buf = xmlStrcat(*buf, BAD_CAST value);
1381 *buf = xmlStrcat(*buf, BAD_CAST "'");
1382 if (value != NULL) {
1383 xmlFree((xmlChar *)value);
1384 value = NULL;
1385 }
1386 }
1387 type = type->baseType;
1388 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1389
1390 return ((const xmlChar *) *buf);
1391}
1392
1393/************************************************************************
1394 * *
1395 * Error functions *
1396 * *
1397 ************************************************************************/
1398
1399#if 0
1400static void
1401xmlSchemaErrMemory(const char *msg)
1402{
1403 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1404 msg);
1405}
1406#endif
1407
1408/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001409 * xmlSchemaPErrMemory:
1410 * @node: a context node
1411 * @extra: extra informations
1412 *
1413 * Handle an out of memory condition
1414 */
1415static void
1416xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1417 const char *extra, xmlNodePtr node)
1418{
1419 if (ctxt != NULL)
1420 ctxt->nberrors++;
1421 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1422 extra);
1423}
1424
1425/**
1426 * xmlSchemaPErr:
1427 * @ctxt: the parsing context
1428 * @node: the context node
1429 * @error: the error code
1430 * @msg: the error message
1431 * @str1: extra data
1432 * @str2: extra data
1433 *
1434 * Handle a parser error
1435 */
1436static void
1437xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1438 const char *msg, const xmlChar * str1, const xmlChar * str2)
1439{
1440 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001441 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001442 void *data = NULL;
1443
1444 if (ctxt != NULL) {
1445 ctxt->nberrors++;
1446 channel = ctxt->error;
1447 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001448 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001449 }
Daniel Veillard659e71e2003-10-10 14:10:40 +00001450 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001451 error, XML_ERR_ERROR, NULL, 0,
1452 (const char *) str1, (const char *) str2, NULL, 0, 0,
1453 msg, str1, str2);
1454}
1455
1456/**
1457 * xmlSchemaPErr2:
1458 * @ctxt: the parsing context
1459 * @node: the context node
1460 * @node: the current child
1461 * @error: the error code
1462 * @msg: the error message
1463 * @str1: extra data
1464 * @str2: extra data
1465 *
1466 * Handle a parser error
1467 */
1468static void
1469xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1470 xmlNodePtr child, int error,
1471 const char *msg, const xmlChar * str1, const xmlChar * str2)
1472{
1473 if (child != NULL)
1474 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1475 else
1476 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1477}
1478
Daniel Veillard01fa6152004-06-29 17:04:39 +00001479
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001480/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001481 * xmlSchemaPErrExt:
1482 * @ctxt: the parsing context
1483 * @node: the context node
1484 * @error: the error code
1485 * @strData1: extra data
1486 * @strData2: extra data
1487 * @strData3: extra data
1488 * @msg: the message
1489 * @str1: extra parameter for the message display
1490 * @str2: extra parameter for the message display
1491 * @str3: extra parameter for the message display
1492 * @str4: extra parameter for the message display
1493 * @str5: extra parameter for the message display
1494 *
1495 * Handle a parser error
1496 */
1497static void
1498xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1499 const xmlChar * strData1, const xmlChar * strData2,
1500 const xmlChar * strData3, const char *msg, const xmlChar * str1,
1501 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1502 const xmlChar * str5)
1503{
1504
1505 xmlGenericErrorFunc channel = NULL;
1506 xmlStructuredErrorFunc schannel = NULL;
1507 void *data = NULL;
1508
1509 if (ctxt != NULL) {
1510 ctxt->nberrors++;
1511 channel = ctxt->error;
1512 data = ctxt->userData;
1513 schannel = ctxt->serror;
1514 }
1515 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1516 error, XML_ERR_ERROR, NULL, 0,
1517 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +00001518 (const char *) strData3, 0, 0, msg, str1, str2,
1519 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +00001520}
Daniel Veillard01fa6152004-06-29 17:04:39 +00001521
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001522/************************************************************************
1523 * *
1524 * Allround error functions *
1525 * *
1526 ************************************************************************/
Daniel Veillard3646d642004-06-02 19:19:14 +00001527
1528/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001529 * xmlSchemaVTypeErrMemory:
1530 * @node: a context node
1531 * @extra: extra informations
1532 *
1533 * Handle an out of memory condition
1534 */
1535static void
1536xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1537 const char *extra, xmlNodePtr node)
1538{
1539 if (ctxt != NULL) {
1540 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001541 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001542 }
1543 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1544 extra);
1545}
1546
1547/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001548 * xmlSchemaErr3:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001549 * @ctxt: the validation context
1550 * @node: the context node
1551 * @error: the error code
1552 * @msg: the error message
1553 * @str1: extra data
1554 * @str2: extra data
1555 * @str3: extra data
1556 *
1557 * Handle a validation error
1558 */
1559static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001560xmlSchemaErr3(xmlSchemaAbstractCtxtPtr ctxt,
1561 int error, xmlNodePtr node, const char *msg,
1562 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001563{
Daniel Veillard659e71e2003-10-10 14:10:40 +00001564 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001565 xmlGenericErrorFunc channel = NULL;
1566 void *data = NULL;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001567
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001568 if (ctxt != NULL) {
1569 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1570 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
1571
1572 vctxt->nberrors++;
1573 vctxt->err = error;
1574 channel = vctxt->error;
1575 schannel = vctxt->serror;
1576 data = vctxt->userData;
1577 if ((node == NULL) && (vctxt->depth >= 0) &&
1578 (vctxt->inode != NULL))
1579 node = vctxt->inode->node;
1580 __xmlRaiseError(schannel, channel, data, ctxt,
1581 node, XML_FROM_SCHEMASV,
1582 error, XML_ERR_ERROR, NULL, 0,
1583 (const char *) str1, (const char *) str2,
1584 (const char *) str3, 0, 0, msg, str1, str2, str3);
1585
1586 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
1587 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
1588
1589 pctxt->nberrors++;
1590 pctxt->err = error;
1591 channel = pctxt->error;
1592 schannel = pctxt->serror;
1593 data = pctxt->userData;
1594 __xmlRaiseError(schannel, channel, data, ctxt,
1595 node, XML_FROM_SCHEMASP,
1596 error, XML_ERR_ERROR, NULL, 0,
1597 (const char *) str1, (const char *) str2,
1598 (const char *) str3, 0, 0, msg, str1, str2, str3);
1599 } else {
1600 TODO
1601 }
1602 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001603}
1604
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001605static void
1606xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
1607 int error, xmlNodePtr node, const char *msg,
1608 const xmlChar *str1, const xmlChar *str2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001609{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001610 xmlSchemaErr3(actxt, error, node, msg, str1, str2, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001611}
1612
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001613static xmlChar *
1614xmlSchemaFormatNodeForError(xmlChar ** msg,
1615 xmlSchemaAbstractCtxtPtr actxt,
1616 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001617{
1618 xmlChar *str = NULL;
1619
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001620 if (node != NULL) {
1621 /*
1622 * Work on tree nodes.
1623 */
1624 if (node->type == XML_ATTRIBUTE_NODE) {
1625 xmlNodePtr elem = node->parent;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001626
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001627 *msg = xmlStrdup(BAD_CAST "Element '");
1628 if (elem->ns != NULL)
1629 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1630 elem->ns->href, elem->name));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001631 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001632 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1633 NULL, elem->name));
1634 FREE_AND_NULL(str);
1635 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1636 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1637 } else {
1638 *msg = xmlStrdup(BAD_CAST "Element '");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001639 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001640 if (node->ns != NULL)
1641 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1642 node->ns->href, node->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001643 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001644 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1645 NULL, node->name));
1646 FREE_AND_NULL(str);
1647 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1648 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1649 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
1650 /*
1651 * Work on node infos.
1652 */
1653 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
1654 xmlSchemaNodeInfoPtr ielem =
1655 vctxt->elemInfos[vctxt->depth];
1656
1657 *msg = xmlStrdup(BAD_CAST "Element '");
1658 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1659 ielem->nsName, ielem->localName));
1660 FREE_AND_NULL(str);
1661 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1662 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1663 } else {
1664 *msg = xmlStrdup(BAD_CAST "Element '");
1665 }
1666 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1667 vctxt->inode->nsName, vctxt->inode->localName));
1668 FREE_AND_NULL(str);
1669 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1670 } else {
1671 TODO
1672 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001673 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001674 /*
1675 * VAL TODO: The output of the given schema component is currently
1676 * disabled.
1677 */
1678#if 0
1679 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
1680 *msg = xmlStrcat(*msg, BAD_CAST " [");
1681 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
1682 NULL, type, NULL, 0));
1683 FREE_AND_NULL(str)
1684 *msg = xmlStrcat(*msg, BAD_CAST "]");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001685 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001686#endif
1687 return (*msg);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001688}
1689
Daniel Veillardc0826a72004-08-10 14:17:33 +00001690static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001691xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1692 const char *funcName,
1693 const char *message)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001694{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001695 xmlChar *msg = NULL;
1696
1697 msg = xmlStrdup(BAD_CAST "Internal error: ");
1698 msg = xmlStrcat(msg, BAD_CAST funcName);
1699 msg = xmlStrcat(msg, BAD_CAST ", ");
1700 msg = xmlStrcat(msg, BAD_CAST message);
1701 msg = xmlStrcat(msg, BAD_CAST ".\n");
1702
1703 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
1704 xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
1705 (const char *) msg, NULL, NULL);
1706
1707 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
1708 xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
1709 (const char *) msg, NULL, NULL);
1710
1711 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001712}
1713
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001714static void
1715xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
1716 xmlParserErrors error,
1717 xmlNodePtr node,
1718 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
1719 const char *message,
1720 const xmlChar *str1,
1721 const xmlChar *str2)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001722{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001723 xmlChar *msg = NULL;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001724
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001725 xmlSchemaFormatNodeForError(&msg, actxt, node);
1726 msg = xmlStrcat(msg, (const xmlChar *) message);
1727 msg = xmlStrcat(msg, BAD_CAST ".\n");
1728 xmlSchemaErr(actxt, error, node,
1729 (const char *) msg, str1, str2);
1730 FREE_AND_NULL(msg)
1731}
1732
1733static int
1734xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
1735 xmlNodePtr node)
1736{
1737 if (node != NULL)
1738 return (node->type);
1739 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
1740 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
1741 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
1742 return (-1);
1743}
1744
1745static int
1746xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
1747{
1748 switch (item->type) {
1749 case XML_SCHEMA_TYPE_COMPLEX:
1750 case XML_SCHEMA_TYPE_SIMPLE:
1751 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1752 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001753 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001754 case XML_SCHEMA_TYPE_GROUP:
1755 return (1);
1756 case XML_SCHEMA_TYPE_ELEMENT:
1757 if ( ((xmlSchemaElementPtr) item)->flags &
1758 XML_SCHEMAS_ELEM_GLOBAL)
1759 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001760 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001761 case XML_SCHEMA_TYPE_ATTRIBUTE:
1762 if ( ((xmlSchemaAttributePtr) item)->flags &
1763 XML_SCHEMAS_ATTR_GLOBAL)
1764 return(1);
1765 break;
1766 /* Note that attribute groups are always global. */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001767 default:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001768 return(1);
1769 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001770 return (0);
1771}
1772
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001773static void
1774xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1775 xmlParserErrors error,
1776 xmlNodePtr node,
1777 const xmlChar *value,
1778 xmlSchemaTypePtr type,
1779 int displayValue)
1780{
1781 xmlChar *msg = NULL;
1782
1783 xmlSchemaFormatNodeForError(&msg, actxt, node);
1784
1785 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1786 XML_ATTRIBUTE_NODE))
1787 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
1788 else
1789 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
1790 "value of ");
1791
1792 if (! xmlSchemaIsGlobalItem(type))
1793 msg = xmlStrcat(msg, BAD_CAST "the local ");
1794 else
1795 msg = xmlStrcat(msg, BAD_CAST "the ");
1796
1797 if (VARIETY_ATOMIC(type))
1798 msg = xmlStrcat(msg, BAD_CAST "atomic type");
1799 else if (VARIETY_LIST(type))
1800 msg = xmlStrcat(msg, BAD_CAST "list type");
1801 else if (VARIETY_UNION(type))
1802 msg = xmlStrcat(msg, BAD_CAST "union type");
1803
1804 if (xmlSchemaIsGlobalItem(type)) {
1805 xmlChar *str = NULL;
1806 msg = xmlStrcat(msg, BAD_CAST " '");
1807 if (type->builtInType != 0) {
1808 msg = xmlStrcat(msg, BAD_CAST "xs:");
1809 msg = xmlStrcat(msg, type->name);
1810 } else
1811 msg = xmlStrcat(msg,
1812 xmlSchemaFormatQName(&str,
1813 type->targetNamespace, type->name));
1814 msg = xmlStrcat(msg, BAD_CAST "'");
1815 FREE_AND_NULL(str);
1816 }
1817 msg = xmlStrcat(msg, BAD_CAST ".\n");
1818 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1819 XML_ATTRIBUTE_NODE))
1820 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
1821 else
1822 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
1823 FREE_AND_NULL(msg)
1824}
1825
Daniel Veillardc0826a72004-08-10 14:17:33 +00001826static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001827xmlSchemaFormatErrorNodeQName(xmlChar ** str,
1828 xmlSchemaNodeInfoPtr ni,
1829 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001830{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001831 if (node != NULL) {
1832 if (node->ns != NULL)
1833 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
1834 else
1835 return (xmlSchemaFormatQName(str, NULL, node->name));
1836 } else if (ni != NULL)
1837 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
1838 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001839}
1840
Daniel Veillardc0826a72004-08-10 14:17:33 +00001841static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001842xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
1843 xmlParserErrors error,
1844 xmlSchemaAttrInfoPtr ni,
1845 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001846{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001847 xmlChar *msg = NULL, *str = NULL;
1848
1849 xmlSchemaFormatNodeForError(&msg, actxt, node);
1850 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
1851 xmlSchemaErr(actxt, error, node, (const char *) msg,
1852 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
1853 NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001854 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001855 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001856}
1857
Daniel Veillardc0826a72004-08-10 14:17:33 +00001858static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001859xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1860 xmlParserErrors error,
1861 xmlNodePtr node,
1862 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001863 const char *message,
1864 int nbval,
1865 int nbneg,
1866 xmlChar **values)
1867{
1868 xmlChar *str = NULL, *msg = NULL;
1869 xmlChar *localName, *nsName;
1870 const xmlChar *cur, *end;
1871 int i;
1872
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001873 xmlSchemaFormatNodeForError(&msg, actxt, node);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001874 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001875 msg = xmlStrcat(msg, BAD_CAST ".");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001876 /*
1877 * Note that is does not make sense to report that we have a
1878 * wildcard here, since the wildcard might be unfolded into
1879 * multiple transitions.
1880 */
1881 if (nbval + nbneg > 0) {
1882 if (nbval + nbneg > 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001883 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001884 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001885 str = xmlStrdup(BAD_CAST " Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001886 nsName = NULL;
1887
1888 for (i = 0; i < nbval + nbneg; i++) {
1889 cur = values[i];
1890 /*
1891 * Get the local name.
1892 */
1893 localName = NULL;
1894
1895 end = cur;
1896 if (*end == '*') {
1897 localName = xmlStrdup(BAD_CAST "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001898 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001899 } else {
1900 while ((*end != 0) && (*end != '|'))
1901 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001902 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001903 }
1904 if (*end != 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001905 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001906 /*
1907 * Skip "*|*" if they come with negated expressions, since
1908 * they represent the same negated wildcard.
1909 */
1910 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1911 /*
1912 * Get the namespace name.
1913 */
1914 cur = end;
1915 if (*end == '*') {
1916 nsName = xmlStrdup(BAD_CAST "{*}");
1917 } else {
1918 while (*end != 0)
1919 end++;
1920
1921 if (i >= nbval)
1922 nsName = xmlStrdup(BAD_CAST "{##other:");
1923 else
1924 nsName = xmlStrdup(BAD_CAST "{");
1925
1926 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1927 nsName = xmlStrcat(nsName, BAD_CAST "}");
1928 }
1929 str = xmlStrcat(str, BAD_CAST nsName);
1930 FREE_AND_NULL(nsName)
1931 } else {
1932 FREE_AND_NULL(localName);
1933 continue;
1934 }
1935 }
1936 str = xmlStrcat(str, BAD_CAST localName);
1937 FREE_AND_NULL(localName);
1938
1939 if (i < nbval + nbneg -1)
1940 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001941 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001942 str = xmlStrcat(str, BAD_CAST " ).\n");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001943 msg = xmlStrcat(msg, BAD_CAST str);
1944 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001945 } else
1946 msg = xmlStrcat(msg, BAD_CAST "\n");
1947 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001948 xmlFree(msg);
1949}
1950
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001951static void
1952xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
1953 xmlParserErrors error,
1954 xmlNodePtr node,
1955 const xmlChar *value,
1956 unsigned long length,
1957 xmlSchemaTypePtr type,
1958 xmlSchemaFacetPtr facet,
1959 const char *message,
1960 const xmlChar *str1,
1961 const xmlChar *str2)
1962{
1963 xmlChar *str = NULL, *msg = NULL;
1964 xmlSchemaTypeType facetType;
1965 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
1966
1967 xmlSchemaFormatNodeForError(&msg, actxt, node);
1968 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
1969 facetType = XML_SCHEMA_FACET_ENUMERATION;
1970 /*
1971 * If enumerations are validated, one must not expect the
1972 * facet to be given.
1973 */
1974 } else
1975 facetType = facet->type;
1976 msg = xmlStrcat(msg, BAD_CAST "[");
1977 msg = xmlStrcat(msg, BAD_CAST "facet '");
1978 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
1979 msg = xmlStrcat(msg, BAD_CAST "'] ");
1980 if (message == NULL) {
1981 /*
1982 * Use a default message.
1983 */
1984 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
1985 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
1986 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
1987
1988 char len[25], actLen[25];
1989
1990 /* FIXME, TODO: What is the max expected string length of the
1991 * this value?
1992 */
1993 if (nodeType == XML_ATTRIBUTE_NODE)
1994 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
1995 else
1996 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
1997
1998 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
1999 snprintf(actLen, 24, "%lu", length);
2000
2001 if (facetType == XML_SCHEMA_FACET_LENGTH)
2002 msg = xmlStrcat(msg,
2003 BAD_CAST "this differs from the allowed length of '%s'.\n");
2004 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2005 msg = xmlStrcat(msg,
2006 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2007 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2008 msg = xmlStrcat(msg,
2009 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2010
2011 if (nodeType == XML_ATTRIBUTE_NODE)
2012 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2013 value, (const xmlChar *) actLen, (const xmlChar *) len);
2014 else
2015 xmlSchemaErr(actxt, error, node, (const char *) msg,
2016 (const xmlChar *) actLen, (const xmlChar *) len);
2017
2018 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2019 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2020 "of the set {%s}.\n");
2021 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2022 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2023 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2024 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2025 "by the pattern '%s'.\n");
2026 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2027 facet->value);
2028 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2029 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2030 "minimum value allowed ('%s').\n");
2031 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2032 facet->value);
2033 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2034 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2035 "maximum value allowed ('%s').\n");
2036 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2037 facet->value);
2038 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2039 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2040 "'%s'.\n");
2041 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2042 facet->value);
2043 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2044 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be more than "
2045 "'%s'.\n");
2046 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2047 facet->value);
2048 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2049 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2050 "digits than are allowed ('%s').\n");
2051 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2052 facet->value);
2053 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2054 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2055 "digits than are allowed ('%s').\n");
2056 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2057 facet->value);
2058 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2059 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2060 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2061 } else {
2062 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2063 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2064 }
2065 } else {
2066 msg = xmlStrcat(msg, (const xmlChar *) message);
2067 msg = xmlStrcat(msg, BAD_CAST ".\n");
2068 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2069 }
2070 FREE_AND_NULL(str)
2071 xmlFree(msg);
2072}
2073
2074#define VERROR(err, type, msg) \
2075 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, err, NULL, type, msg, NULL, NULL);
2076
2077#define VERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) vctxt, func, msg);
2078
2079#define PERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) pctxt, func, msg);
2080
2081#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2082
2083
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002084/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00002085 * xmlSchemaPMissingAttrErr:
2086 * @ctxt: the schema validation context
2087 * @ownerDes: the designation of the owner
2088 * @ownerName: the name of the owner
2089 * @ownerItem: the owner as a schema object
2090 * @ownerElem: the owner as an element node
2091 * @node: the parent element node of the missing attribute node
2092 * @type: the corresponding type of the attribute node
2093 *
2094 * Reports an illegal attribute.
2095 */
2096static void
2097xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002098 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002099 xmlSchemaTypePtr ownerItem,
2100 xmlNodePtr ownerElem,
2101 const char *name,
2102 const char *message)
2103{
2104 xmlChar *des = NULL;
2105
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002106 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2107
Daniel Veillardc0826a72004-08-10 14:17:33 +00002108 if (message != NULL)
2109 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002110 else
2111 xmlSchemaPErr(ctxt, ownerElem, error,
2112 "%s: The attribute '%s' is required but missing.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002113 BAD_CAST des, BAD_CAST name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002114 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002115}
2116
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002117
Daniel Veillardc0826a72004-08-10 14:17:33 +00002118/**
2119 * xmlSchemaPResCompAttrErr:
2120 * @ctxt: the schema validation context
2121 * @error: the error code
2122 * @ownerDes: the designation of the owner
2123 * @ownerItem: the owner as a schema object
2124 * @ownerElem: the owner as an element node
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002125 * @name: the name of the attribute holding the QName
Daniel Veillardc0826a72004-08-10 14:17:33 +00002126 * @refName: the referenced local name
2127 * @refURI: the referenced namespace URI
2128 * @message: optional message
2129 *
2130 * Used to report QName attribute values that failed to resolve
2131 * to schema components.
2132 */
2133static void
2134xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002135 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002136 xmlSchemaTypePtr ownerItem,
2137 xmlNodePtr ownerElem,
2138 const char *name,
2139 const xmlChar *refName,
2140 const xmlChar *refURI,
2141 xmlSchemaTypeType refType,
2142 const char *refTypeStr)
2143{
2144 xmlChar *des = NULL, *strA = NULL;
2145
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002146 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002147 if (refTypeStr == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002148 refTypeStr = (const char *) xmlSchemaCompTypeToString(refType);
2149 xmlSchemaPErrExt(ctxt, ownerElem, error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002150 NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002151 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2152 "%s.\n", BAD_CAST des, BAD_CAST name,
2153 xmlSchemaFormatQName(&strA, refURI, refName),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002154 BAD_CAST refTypeStr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002155 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002156 FREE_AND_NULL(strA)
2157}
2158
William M. Brack2f2a6632004-08-20 23:09:47 +00002159/**
2160 * xmlSchemaPCustomAttrErr:
2161 * @ctxt: the schema parser context
2162 * @error: the error code
2163 * @ownerDes: the designation of the owner
2164 * @ownerItem: the owner as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002165 * @attr: the illegal attribute node
William M. Brack2f2a6632004-08-20 23:09:47 +00002166 *
2167 * Reports an illegal attribute during the parse.
2168 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002169static void
2170xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002171 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002172 xmlChar **ownerDes,
2173 xmlSchemaTypePtr ownerItem,
2174 xmlAttrPtr attr,
2175 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002176{
2177 xmlChar *des = NULL;
2178
2179 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002180 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002181 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002182 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002183 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002184 } else
2185 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002186 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002187 "%s, attribute '%s': %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002188 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2189 if (ownerDes == NULL)
2190 FREE_AND_NULL(des);
2191}
2192
2193/**
2194 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002195 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002196 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002197 * @ownerDes: the designation of the attribute's owner
2198 * @ownerItem: the attribute's owner item
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002199 * @attr: the illegal attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00002200 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002201 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002202 */
2203static void
2204xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002205 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002206 xmlChar **ownerDes,
2207 xmlSchemaTypePtr ownerItem,
2208 xmlAttrPtr attr)
2209{
2210 xmlChar *des = NULL, *strA = NULL;
2211
2212 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002213 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002214 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002215 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002216 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002217 } else
2218 des = *ownerDes;
2219 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
2220 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
2221 xmlSchemaFormatQNameNs(&strA, attr->ns, attr->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002222 if (ownerDes == NULL)
2223 FREE_AND_NULL(des);
2224 FREE_AND_NULL(strA);
2225}
2226
William M. Brack2f2a6632004-08-20 23:09:47 +00002227/**
2228 * xmlSchemaPAquireDes:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002229 * @des: the first designation
William M. Brack2f2a6632004-08-20 23:09:47 +00002230 * @itemDes: the second designation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002231 * @item: the schema item
William M. Brack2f2a6632004-08-20 23:09:47 +00002232 * @itemElem: the node of the schema item
2233 *
2234 * Creates a designation for an item.
2235 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002236static void
2237xmlSchemaPAquireDes(xmlChar **des,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002238 xmlChar **itemDes,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002239 xmlSchemaTypePtr item,
2240 xmlNodePtr itemElem)
2241{
2242 if (itemDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002243 xmlSchemaFormatItemForReport(des, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002244 else if (*itemDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002245 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002246 *des = *itemDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002247 } else
2248 *des = *itemDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002249}
2250
William M. Brack2f2a6632004-08-20 23:09:47 +00002251/**
2252 * xmlSchemaPCustomErr:
2253 * @ctxt: the schema parser context
2254 * @error: the error code
2255 * @itemDes: the designation of the schema item
2256 * @item: the schema item
2257 * @itemElem: the node of the schema item
2258 * @message: the error message
2259 * @str1: an optional param for the error message
2260 * @str2: an optional param for the error message
2261 * @str3: an optional param for the error message
2262 *
2263 * Reports an error during parsing.
2264 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002265static void
2266xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002267 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002268 xmlChar **itemDes,
2269 xmlSchemaTypePtr item,
2270 xmlNodePtr itemElem,
2271 const char *message,
2272 const xmlChar *str1,
2273 const xmlChar *str2,
2274 const xmlChar *str3)
2275{
2276 xmlChar *des = NULL, *msg = NULL;
2277
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002278 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002279 msg = xmlStrdup(BAD_CAST "%s: ");
2280 msg = xmlStrcat(msg, (const xmlChar *) message);
2281 msg = xmlStrcat(msg, BAD_CAST ".\n");
2282 if ((itemElem == NULL) && (item != NULL))
2283 itemElem = item->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002284 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002285 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2286 if (itemDes == NULL)
2287 FREE_AND_NULL(des);
2288 FREE_AND_NULL(msg);
2289}
2290
William M. Brack2f2a6632004-08-20 23:09:47 +00002291/**
2292 * xmlSchemaPCustomErr:
2293 * @ctxt: the schema parser context
2294 * @error: the error code
2295 * @itemDes: the designation of the schema item
2296 * @item: the schema item
2297 * @itemElem: the node of the schema item
2298 * @message: the error message
2299 * @str1: the optional param for the error message
2300 *
2301 * Reports an error during parsing.
2302 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002303static void
2304xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002305 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002306 xmlChar **itemDes,
2307 xmlSchemaTypePtr item,
2308 xmlNodePtr itemElem,
2309 const char *message,
2310 const xmlChar *str1)
2311{
2312 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
2313 str1, NULL, NULL);
2314}
2315
William M. Brack2f2a6632004-08-20 23:09:47 +00002316/**
2317 * xmlSchemaPAttrUseErr:
2318 * @ctxt: the schema parser context
2319 * @error: the error code
2320 * @itemDes: the designation of the schema type
2321 * @item: the schema type
2322 * @itemElem: the node of the schema type
2323 * @attr: the invalid schema attribute
2324 * @message: the error message
2325 * @str1: the optional param for the error message
2326 *
2327 * Reports an attribute use error during parsing.
2328 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002329static void
2330xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002331 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002332 xmlSchemaTypePtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002333 const xmlSchemaAttributePtr attr,
2334 const char *message,
2335 const xmlChar *str1)
2336{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002337 xmlChar *str = NULL, *msg = NULL;
2338 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2339 msg = xmlStrcat(msg, BAD_CAST ", ");
2340 msg = xmlStrcat(msg,
2341 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2342 (xmlSchemaTypePtr) attr, NULL));
2343 FREE_AND_NULL(str);
2344 msg = xmlStrcat(msg, BAD_CAST ": ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002345 msg = xmlStrcat(msg, (const xmlChar *) message);
2346 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002347 xmlSchemaPErr(ctxt, attr->node, error,
2348 (const char *) msg, str1, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002349 xmlFree(msg);
2350}
2351
William M. Brack2f2a6632004-08-20 23:09:47 +00002352/**
2353 * xmlSchemaPIllegalFacetAtomicErr:
2354 * @ctxt: the schema parser context
2355 * @error: the error code
2356 * @itemDes: the designation of the type
2357 * @item: the schema type
2358 * @baseItem: the base type of type
2359 * @facet: the illegal facet
2360 *
2361 * Reports an illegal facet for atomic simple types.
2362 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002363static void
2364xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002365 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002366 xmlChar **itemDes,
2367 xmlSchemaTypePtr item,
2368 xmlSchemaTypePtr baseItem,
2369 xmlSchemaFacetPtr facet)
2370{
2371 xmlChar *des = NULL, *strT = NULL;
2372
2373 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2374 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
2375 "%s: The facet '%s' is not allowed on types derived from the "
2376 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002377 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002378 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002379 NULL, NULL);
2380 if (itemDes == NULL)
2381 FREE_AND_NULL(des);
2382 FREE_AND_NULL(strT);
2383}
2384
William M. Brack2f2a6632004-08-20 23:09:47 +00002385/**
2386 * xmlSchemaPIllegalFacetListUnionErr:
2387 * @ctxt: the schema parser context
2388 * @error: the error code
2389 * @itemDes: the designation of the schema item involved
2390 * @item: the schema item involved
2391 * @facet: the illegal facet
2392 *
2393 * Reports an illegal facet for <list> and <union>.
2394 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002395static void
2396xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002397 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002398 xmlChar **itemDes,
2399 xmlSchemaTypePtr item,
2400 xmlSchemaFacetPtr facet)
2401{
2402 xmlChar *des = NULL, *strT = NULL;
2403
2404 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002405 xmlSchemaPErr(ctxt, item->node, error,
2406 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002407 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002408 if (itemDes == NULL)
2409 FREE_AND_NULL(des);
2410 FREE_AND_NULL(strT);
2411}
2412
2413/**
2414 * xmlSchemaPMutualExclAttrErr:
2415 * @ctxt: the schema validation context
2416 * @error: the error code
2417 * @elemDes: the designation of the parent element node
2418 * @attr: the bad attribute node
2419 * @type: the corresponding type of the attribute node
2420 *
2421 * Reports an illegal attribute.
2422 */
2423static void
2424xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
2425 xmlParserErrors error,
2426 xmlChar **ownerDes,
2427 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002428 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002429 const char *name1,
2430 const char *name2)
2431{
2432 xmlChar *des = NULL;
2433
2434 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002435 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002436 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002437 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002438 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002439 } else
2440 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002441 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002442 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002443 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
2444 if (ownerDes == NULL)
2445 FREE_AND_NULL(des)
2446}
2447
2448/**
2449 * xmlSchemaPSimpleTypeErr:
2450 * @ctxt: the schema validation context
2451 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002452 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00002453 * @ownerDes: the designation of the owner
2454 * @ownerItem: the schema object if existent
2455 * @node: the validated node
2456 * @value: the validated value
2457 *
2458 * Reports a simple type validation error.
2459 * TODO: Should this report the value of an element as well?
2460 */
2461static void
2462xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
2463 xmlParserErrors error,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002464 xmlSchemaTypePtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002465 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00002466 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002467 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002468 const xmlChar *value,
2469 const char *message,
2470 const xmlChar *str1,
2471 const xmlChar *str2)
2472{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002473 xmlChar *msg = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002474
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002475 xmlSchemaFormatNodeForError(&msg, (xmlSchemaAbstractCtxtPtr) ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002476 if (message == NULL) {
2477 /*
2478 * Use default messages.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002479 */
2480 if (type != NULL) {
2481 if (node->type == XML_ATTRIBUTE_NODE)
2482 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2483 else
2484 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
2485 "valid value of ");
2486 if (! xmlSchemaIsGlobalItem(type))
2487 msg = xmlStrcat(msg, BAD_CAST "the local ");
2488 else
2489 msg = xmlStrcat(msg, BAD_CAST "the ");
2490
2491 if (VARIETY_ATOMIC(type))
2492 msg = xmlStrcat(msg, BAD_CAST "atomic type");
2493 else if (VARIETY_LIST(type))
2494 msg = xmlStrcat(msg, BAD_CAST "list type");
2495 else if (VARIETY_UNION(type))
2496 msg = xmlStrcat(msg, BAD_CAST "union type");
2497
2498 if (xmlSchemaIsGlobalItem(type)) {
2499 xmlChar *str = NULL;
2500 msg = xmlStrcat(msg, BAD_CAST " '");
2501 if (type->builtInType != 0) {
2502 msg = xmlStrcat(msg, BAD_CAST "xs:");
2503 msg = xmlStrcat(msg, type->name);
2504 } else
2505 msg = xmlStrcat(msg,
2506 xmlSchemaFormatQName(&str,
2507 type->targetNamespace, type->name));
2508 msg = xmlStrcat(msg, BAD_CAST "'.");
2509 FREE_AND_NULL(str);
2510 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00002511 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002512 if (node->type == XML_ATTRIBUTE_NODE)
2513 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
2514 else
2515 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
2516 "valid.");
2517 }
2518 if (expected) {
2519 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
2520 msg = xmlStrcat(msg, BAD_CAST expected);
2521 msg = xmlStrcat(msg, BAD_CAST "'.\n");
2522 } else
2523 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002524 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002525 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
2526 else
2527 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
2528 } else {
2529 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2530 "%s%s.\n", msg, BAD_CAST message, str1, str2, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002531 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002532 /* Cleanup. */
2533 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002534}
2535
William M. Brack2f2a6632004-08-20 23:09:47 +00002536/**
2537 * xmlSchemaPContentErr:
2538 * @ctxt: the schema parser context
2539 * @error: the error code
2540 * @onwerDes: the designation of the holder of the content
2541 * @ownerItem: the owner item of the holder of the content
2542 * @ownerElem: the node of the holder of the content
2543 * @child: the invalid child node
2544 * @message: the optional error message
2545 * @content: the optional string describing the correct content
2546 *
2547 * Reports an error concerning the content of a schema element.
2548 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002549static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002550xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002551 xmlParserErrors error,
2552 xmlChar **ownerDes,
2553 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002554 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002555 xmlNodePtr child,
2556 const char *message,
2557 const char *content)
2558{
2559 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002560
Daniel Veillardc0826a72004-08-10 14:17:33 +00002561 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002562 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002563 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002564 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002565 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002566 } else
2567 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002568 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002569 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2570 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002571 BAD_CAST des, BAD_CAST message);
2572 else {
2573 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002574 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2575 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002576 BAD_CAST des, BAD_CAST content);
2577 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002578 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2579 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002580 BAD_CAST des, NULL);
2581 }
2582 }
2583 if (ownerDes == NULL)
2584 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002585}
2586
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002587/************************************************************************
2588 * *
2589 * Streamable error functions *
2590 * *
2591 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002592
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002593
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002594
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002595
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002596/************************************************************************
2597 * *
2598 * Validation helper functions *
2599 * *
2600 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002601
Daniel Veillardc0826a72004-08-10 14:17:33 +00002602
Daniel Veillard4255d502002-04-16 15:50:10 +00002603/************************************************************************
2604 * *
2605 * Allocation functions *
2606 * *
2607 ************************************************************************/
2608
2609/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002610 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002611 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002612 *
2613 * Allocate a new Schema structure.
2614 *
2615 * Returns the newly allocated structure or NULL in case or error
2616 */
2617static xmlSchemaPtr
2618xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2619{
2620 xmlSchemaPtr ret;
2621
2622 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2623 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002624 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002625 return (NULL);
2626 }
2627 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002628 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002629 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002630
2631 return (ret);
2632}
2633
2634/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002635 * xmlSchemaNewSchema:
2636 * @ctxt: a schema validation context
2637 *
2638 * Allocate a new Schema structure.
2639 *
2640 * Returns the newly allocated structure or NULL in case or error
2641 */
2642static xmlSchemaAssemblePtr
2643xmlSchemaNewAssemble(void)
2644{
2645 xmlSchemaAssemblePtr ret;
2646
2647 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2648 if (ret == NULL) {
2649 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2650 return (NULL);
2651 }
2652 memset(ret, 0, sizeof(xmlSchemaAssemble));
2653 ret->items = NULL;
2654 return (ret);
2655}
2656
2657/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002658 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002659 *
2660 * Allocate a new Facet structure.
2661 *
2662 * Returns the newly allocated structure or NULL in case or error
2663 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002664xmlSchemaFacetPtr
2665xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002666{
2667 xmlSchemaFacetPtr ret;
2668
2669 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2670 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002671 return (NULL);
2672 }
2673 memset(ret, 0, sizeof(xmlSchemaFacet));
2674
2675 return (ret);
2676}
2677
2678/**
2679 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002680 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002681 * @node: a node
2682 *
2683 * Allocate a new annotation structure.
2684 *
2685 * Returns the newly allocated structure or NULL in case or error
2686 */
2687static xmlSchemaAnnotPtr
2688xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2689{
2690 xmlSchemaAnnotPtr ret;
2691
2692 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2693 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002694 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002695 return (NULL);
2696 }
2697 memset(ret, 0, sizeof(xmlSchemaAnnot));
2698 ret->content = node;
2699 return (ret);
2700}
2701
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002702static xmlSchemaItemListPtr
2703xmlSchemaNewItemList(void)
2704{
2705 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002706
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002707 ret = xmlMalloc(sizeof(xmlSchemaItemList));
2708 if (ret == NULL) {
2709 xmlSchemaPErrMemory(NULL,
2710 "allocating an item list structure", NULL);
2711 return (NULL);
2712 }
2713 memset(ret, 0, sizeof(xmlSchemaItemList));
2714 return (ret);
2715}
2716
2717/**
2718 * xmlSchemaAddElementSubstitutionMember:
2719 * @pctxt: a schema parser context
2720 * @head: the head of the substitution group
2721 * @member: the new member of the substitution group
2722 *
2723 * Allocate a new annotation structure.
2724 *
2725 * Returns the newly allocated structure or NULL in case or error
2726 */
2727static int
2728xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
2729 xmlSchemaElementPtr head,
2730 xmlSchemaElementPtr member)
2731{
2732 xmlSchemaSubstGroupPtr substGroup;
2733
2734 if (pctxt == NULL)
2735 return (-1);
2736
2737 if (pctxt->substGroups == NULL) {
2738 pctxt->substGroups = xmlHashCreateDict(10, pctxt->dict);
2739 if (pctxt->substGroups == NULL)
2740 return (-1);
2741 }
2742 substGroup = xmlHashLookup2(pctxt->substGroups, head->name,
2743 head->targetNamespace);
2744 if (substGroup == NULL) {
2745 int res;
2746
2747 substGroup = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
2748 if (substGroup == NULL) {
2749 xmlSchemaPErrMemory(NULL,
2750 "xmlSchemaAddElementSubstitution, allocating a substitution "
2751 "group container",
2752 NULL);
2753 return (-1);
2754 }
2755 substGroup->members = xmlSchemaNewItemList();
2756 if (substGroup->members == NULL) {
2757 xmlFree(substGroup);
2758 return (-1);
2759 }
2760 substGroup->head = head;
2761
2762 res = xmlHashAddEntry2(pctxt->substGroups,
2763 head->name, head->targetNamespace, substGroup);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002764 if (res != 0) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002765 xmlFree(substGroup->members);
2766 xmlFree(substGroup);
2767 xmlSchemaPErr(pctxt, member->node,
2768 XML_SCHEMAP_INTERNAL,
2769 "Internal error: xmlSchemaAddElementSubstitution, "
2770 "failed to add a new substitution group container for "
2771 "'%s'.\n", head->name, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002772 return (-1);
2773 }
2774 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002775 if (substGroup->members->items == NULL) {
2776 substGroup->members->items = (void **) xmlMalloc(
2777 5 * sizeof(xmlSchemaElementPtr));
2778 if (substGroup->members->items == NULL) {
2779 xmlSchemaPErrMemory(NULL,
2780 "allocating list of substitution group members", NULL);
2781 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002782 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002783 substGroup->members->sizeItems = 5;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002784 } else if (substGroup->members->sizeItems <=
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002785 substGroup->members->nbItems) {
2786 substGroup->members->sizeItems *= 2;
2787 substGroup->members->items = (void **) xmlRealloc(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002788 substGroup->members->items,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002789 substGroup->members->sizeItems * sizeof(xmlSchemaElementPtr));
2790 if (substGroup->members->items == NULL) {
2791 xmlSchemaPErrMemory(NULL,
2792 "re-allocating list of substitution group members", NULL);
2793 substGroup->members->sizeItems = 0;
2794 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002795 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002796 }
2797 ((xmlSchemaElementPtr *) substGroup->members->items)
2798 [substGroup->members->nbItems++] = (void *) member;
2799 return (0);
2800}
2801
2802/**
2803 * xmlSchemaGetElementSubstitutionGroup:
2804 * @pctxt: a schema parser context
2805 * @head: the head of the substitution group
2806 * @member: the new member of the substitution group
2807 *
2808 * Allocate a new annotation structure.
2809 *
2810 * Returns the newly allocated structure or NULL in case or error
2811 */
2812static xmlSchemaSubstGroupPtr
2813xmlSchemaGetElementSubstitutionGroup(xmlSchemaParserCtxtPtr pctxt,
2814 xmlSchemaElementPtr head)
2815{
2816 if (pctxt == NULL)
2817 return (NULL);
2818
2819 if (pctxt->substGroups == NULL)
2820 return (NULL);
2821
2822 return ((xmlSchemaSubstGroupPtr) xmlHashLookup2(pctxt->substGroups,
2823 head->name, head->targetNamespace));
2824}
2825
2826/**
2827 * xmlSchemaFreeItemList:
2828 * @annot: a schema type structure
2829 *
2830 * Deallocate a annotation structure
2831 */
2832static void
2833xmlSchemaFreeItemList(xmlSchemaItemListPtr list)
2834{
2835 if (list == NULL)
2836 return;
2837 if (list->items != NULL)
2838 xmlFree(list->items);
2839 xmlFree(list);
2840}
2841
Daniel Veillard4255d502002-04-16 15:50:10 +00002842/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002843 * xmlSchemaFreeAnnot:
2844 * @annot: a schema type structure
2845 *
2846 * Deallocate a annotation structure
2847 */
2848static void
2849xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2850{
2851 if (annot == NULL)
2852 return;
2853 xmlFree(annot);
2854}
2855
2856/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002857 * xmlSchemaFreeImport:
2858 * @import: a schema import structure
2859 *
2860 * Deallocate an import structure
2861 */
2862static void
2863xmlSchemaFreeImport(xmlSchemaImportPtr import)
2864{
2865 if (import == NULL)
2866 return;
2867
2868 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002869 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002870 xmlFree(import);
2871}
2872
2873/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002874 * xmlSchemaFreeInclude:
2875 * @include: a schema include structure
2876 *
2877 * Deallocate an include structure
2878 */
2879static void
2880xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2881{
2882 if (include == NULL)
2883 return;
2884
2885 xmlFreeDoc(include->doc);
2886 xmlFree(include);
2887}
2888
2889/**
2890 * xmlSchemaFreeIncludeList:
2891 * @includes: a schema include list
2892 *
2893 * Deallocate an include structure
2894 */
2895static void
2896xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2897{
2898 xmlSchemaIncludePtr next;
2899
2900 while (includes != NULL) {
2901 next = includes->next;
2902 xmlSchemaFreeInclude(includes);
2903 includes = next;
2904 }
2905}
2906
2907/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002908 * xmlSchemaFreeNotation:
2909 * @schema: a schema notation structure
2910 *
2911 * Deallocate a Schema Notation structure.
2912 */
2913static void
2914xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2915{
2916 if (nota == NULL)
2917 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002918 xmlFree(nota);
2919}
2920
2921/**
2922 * xmlSchemaFreeAttribute:
2923 * @schema: a schema attribute structure
2924 *
2925 * Deallocate a Schema Attribute structure.
2926 */
2927static void
2928xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2929{
2930 if (attr == NULL)
2931 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002932 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002933 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002934 if (attr->defVal != NULL)
2935 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002936 xmlFree(attr);
2937}
2938
2939/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002940 * xmlSchemaFreeWildcardNsSet:
2941 * set: a schema wildcard namespace
2942 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002943 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002944 */
2945static void
2946xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2947{
2948 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002949
Daniel Veillard3646d642004-06-02 19:19:14 +00002950 while (set != NULL) {
2951 next = set->next;
2952 xmlFree(set);
2953 set = next;
2954 }
2955}
2956
2957/**
2958 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002959 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002960 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002961 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002962 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002963void
Daniel Veillard3646d642004-06-02 19:19:14 +00002964xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2965{
2966 if (wildcard == NULL)
2967 return;
2968 if (wildcard->annot != NULL)
2969 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002970 if (wildcard->nsSet != NULL)
2971 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2972 if (wildcard->negNsSet != NULL)
2973 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00002974 xmlFree(wildcard);
2975}
2976
2977/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002978 * xmlSchemaFreeAttributeGroup:
2979 * @schema: a schema attribute group structure
2980 *
2981 * Deallocate a Schema Attribute Group structure.
2982 */
2983static void
2984xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2985{
2986 if (attr == NULL)
2987 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002988 if (attr->annot != NULL)
2989 xmlSchemaFreeAnnot(attr->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002990 xmlFree(attr);
2991}
2992
2993/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002994 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002995 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00002996 *
2997 * Deallocate a list of schema attribute uses.
2998 */
2999static void
3000xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
3001{
3002 xmlSchemaAttributeLinkPtr next;
3003
3004 while (attrUse != NULL) {
3005 next = attrUse->next;
3006 xmlFree(attrUse);
3007 attrUse = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003008 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003009}
3010
3011/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003012 * xmlSchemaFreeQNameRef:
3013 * @item: a QName reference structure
3014 *
3015 * Deallocatea a QName reference structure.
3016 */
3017static void
3018xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3019{
3020 xmlFree(item);
3021}
3022
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003023/**
3024 * xmlSchemaFreeQNameRef:
3025 * @item: a QName reference structure
3026 *
3027 * Deallocatea a QName reference structure.
3028 */
3029static void
3030xmlSchemaFreeSubstGroup(xmlSchemaSubstGroupPtr item)
3031{
3032 if (item == NULL)
3033 return;
3034 if (item->members != NULL)
3035 xmlSchemaFreeItemList(item->members);
3036 xmlFree(item);
3037}
3038
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003039static int
3040xmlSchemaAddVolatile(xmlSchemaPtr schema,
3041 xmlSchemaBasicItemPtr item)
3042{
3043 xmlSchemaItemListPtr list;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003044
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003045 if (schema->volatiles == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003046 schema->volatiles = (void *) xmlSchemaNewItemList();
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003047 if (schema->volatiles == NULL) {
3048 xmlSchemaPErrMemory(NULL,
3049 "allocating list of volatiles", NULL);
3050 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003051 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003052 }
3053 list = (xmlSchemaItemListPtr) schema->volatiles;
3054 if (list->items == NULL) {
3055 list->items = (void **) xmlMalloc(
3056 20 * sizeof(xmlSchemaBasicItemPtr));
3057 if (list->items == NULL) {
3058 xmlSchemaPErrMemory(NULL,
3059 "allocating new volatile item buffer", NULL);
3060 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003061 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003062 list->sizeItems = 20;
3063 } else if (list->sizeItems <= list->nbItems) {
3064 list->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003065 list->items = (void **) xmlRealloc(list->items,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003066 list->sizeItems * sizeof(xmlSchemaTypePtr));
3067 if (list->items == NULL) {
3068 xmlSchemaPErrMemory(NULL,
3069 "growing volatile item buffer", NULL);
3070 list->sizeItems = 0;
3071 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003072 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003073 }
3074 ((xmlSchemaBasicItemPtr *) list->items)[list->nbItems++] = (void *) item;
3075 return (0);
3076}
3077
3078/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003079 * xmlSchemaFreeTypeLinkList:
3080 * @alink: a type link
3081 *
3082 * Deallocate a list of types.
3083 */
3084static void
3085xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3086{
3087 xmlSchemaTypeLinkPtr next;
3088
3089 while (link != NULL) {
3090 next = link->next;
3091 xmlFree(link);
3092 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003093 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003094}
3095
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003096static void
3097xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3098{
3099 xmlSchemaIDCStateObjPtr next;
3100 while (sto != NULL) {
3101 next = sto->next;
3102 if (sto->history != NULL)
3103 xmlFree(sto->history);
3104 if (sto->xpathCtxt != NULL)
3105 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3106 xmlFree(sto);
3107 sto = next;
3108 }
3109}
3110
3111/**
3112 * xmlSchemaFreeIDC:
3113 * @idc: a identity-constraint definition
3114 *
3115 * Deallocates an identity-constraint definition.
3116 */
3117static void
3118xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3119{
3120 xmlSchemaIDCSelectPtr cur, prev;
3121
3122 if (idcDef == NULL)
3123 return;
3124 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003125 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003126 /* Selector */
3127 if (idcDef->selector != NULL) {
3128 if (idcDef->selector->xpathComp != NULL)
3129 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3130 xmlFree(idcDef->selector);
3131 }
3132 /* Fields */
3133 if (idcDef->fields != NULL) {
3134 cur = idcDef->fields;
3135 do {
3136 prev = cur;
3137 cur = cur->next;
3138 if (prev->xpathComp != NULL)
3139 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003140 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003141 } while (cur != NULL);
3142 }
3143 xmlFree(idcDef);
3144}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003145
Daniel Veillard01fa6152004-06-29 17:04:39 +00003146/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003147 * xmlSchemaFreeElement:
3148 * @schema: a schema element structure
3149 *
3150 * Deallocate a Schema Element structure.
3151 */
3152static void
3153xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3154{
3155 if (elem == NULL)
3156 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003157 if (elem->annot != NULL)
3158 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003159 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003160 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003161 if (elem->defVal != NULL)
3162 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003163 xmlFree(elem);
3164}
3165
3166/**
3167 * xmlSchemaFreeFacet:
3168 * @facet: a schema facet structure
3169 *
3170 * Deallocate a Schema Facet structure.
3171 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003172void
Daniel Veillard4255d502002-04-16 15:50:10 +00003173xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3174{
3175 if (facet == NULL)
3176 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003177 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003178 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003179 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003180 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003181 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003182 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003183 xmlFree(facet);
3184}
3185
3186/**
3187 * xmlSchemaFreeType:
3188 * @type: a schema type structure
3189 *
3190 * Deallocate a Schema Type structure.
3191 */
3192void
3193xmlSchemaFreeType(xmlSchemaTypePtr type)
3194{
3195 if (type == NULL)
3196 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003197 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003198 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003199 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003200 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003201
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003202 facet = type->facets;
3203 while (facet != NULL) {
3204 next = facet->next;
3205 xmlSchemaFreeFacet(facet);
3206 facet = next;
3207 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003208 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003209 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3210 if (type->attributeUses != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003211 xmlSchemaFreeAttributeUseList(type->attributeUses);
Daniel Veillard3646d642004-06-02 19:19:14 +00003212 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003213 if (type->memberTypes != NULL)
3214 xmlSchemaFreeTypeLinkList(type->memberTypes);
3215 if (type->facetSet != NULL) {
3216 xmlSchemaFacetLinkPtr next, link;
3217
3218 link = type->facetSet;
3219 do {
3220 next = link->next;
3221 xmlFree(link);
3222 link = next;
3223 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003224 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003225 if (type->contModel != NULL)
3226 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003227 xmlFree(type);
3228}
3229
3230/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003231 * xmlSchemaFreeModelGroupDef:
3232 * @item: a schema model group definition
3233 *
3234 * Deallocates a schema model group definition.
3235 */
3236static void
3237xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3238{
3239 if (item->annot != NULL)
3240 xmlSchemaFreeAnnot(item->annot);
3241 xmlFree(item);
3242}
3243
3244/**
3245 * xmlSchemaFreeModelGroup:
3246 * @item: a schema model group
3247 *
3248 * Deallocates a schema model group structure.
3249 */
3250static void
3251xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3252{
3253 if (item->annot != NULL)
3254 xmlSchemaFreeAnnot(item->annot);
3255 xmlFree(item);
3256}
3257
3258/**
3259 * xmlSchemaFreeParticle:
3260 * @type: a schema type structure
3261 *
3262 * Deallocate a Schema Type structure.
3263 */
3264static void
3265xmlSchemaFreeParticle(xmlSchemaParticlePtr item)
3266{
3267 if (item->annot != NULL)
3268 xmlSchemaFreeAnnot(item->annot);
3269 xmlFree(item);
3270}
3271
3272/**
3273 * xmlSchemaFreeMiscComponents:
3274 * @item: a schema component
3275 *
3276 * Deallocates misc. schema component structures.
3277 */
3278static void
3279xmlSchemaFreeMiscComponents(xmlSchemaTreeItemPtr item)
3280{
3281 if (item == NULL)
3282 return;
3283 switch (item->type) {
3284 case XML_SCHEMA_TYPE_PARTICLE:
3285 xmlSchemaFreeParticle((xmlSchemaParticlePtr) item);
3286 return;
3287 case XML_SCHEMA_TYPE_SEQUENCE:
3288 case XML_SCHEMA_TYPE_CHOICE:
3289 case XML_SCHEMA_TYPE_ALL:
3290 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
3291 return;
3292 case XML_SCHEMA_TYPE_ANY:
3293 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
3294 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
3295 break;
3296 default:
3297 /* TODO: This should never be hit. */
3298 TODO
3299 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003300 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003301}
3302
3303static void
3304xmlSchemaFreeVolatiles(xmlSchemaPtr schema)
3305{
3306 if (schema->volatiles == NULL)
3307 return;
3308 {
3309 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->volatiles;
3310 xmlSchemaTreeItemPtr item;
3311 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003312
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003313 for (i = 0; i < list->nbItems; i++) {
3314 if (list->items[i] != NULL) {
3315 item = (xmlSchemaTreeItemPtr) list->items[i];
3316 switch (item->type) {
3317 case XML_SCHEMA_EXTRA_QNAMEREF:
3318 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
3319 break;
3320 default:
3321 xmlSchemaFreeMiscComponents(item);
3322 }
3323 }
3324 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003325 xmlSchemaFreeItemList(list);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003326 }
3327}
3328/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003329 * xmlSchemaFreeTypeList:
3330 * @type: a schema type structure
3331 *
3332 * Deallocate a Schema Type structure.
3333 */
3334static void
3335xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
3336{
3337 xmlSchemaTypePtr next;
3338
3339 while (type != NULL) {
3340 next = type->redef;
3341 xmlSchemaFreeType(type);
3342 type = next;
3343 }
3344}
3345
3346/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003347 * xmlSchemaFree:
3348 * @schema: a schema structure
3349 *
3350 * Deallocate a Schema structure.
3351 */
3352void
3353xmlSchemaFree(xmlSchemaPtr schema)
3354{
3355 if (schema == NULL)
3356 return;
3357
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003358 if (schema->volatiles != NULL)
3359 xmlSchemaFreeVolatiles(schema);
Daniel Veillard4255d502002-04-16 15:50:10 +00003360 if (schema->notaDecl != NULL)
3361 xmlHashFree(schema->notaDecl,
3362 (xmlHashDeallocator) xmlSchemaFreeNotation);
3363 if (schema->attrDecl != NULL)
3364 xmlHashFree(schema->attrDecl,
3365 (xmlHashDeallocator) xmlSchemaFreeAttribute);
3366 if (schema->attrgrpDecl != NULL)
3367 xmlHashFree(schema->attrgrpDecl,
3368 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
3369 if (schema->elemDecl != NULL)
3370 xmlHashFree(schema->elemDecl,
3371 (xmlHashDeallocator) xmlSchemaFreeElement);
3372 if (schema->typeDecl != NULL)
3373 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003374 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003375 if (schema->groupDecl != NULL)
3376 xmlHashFree(schema->groupDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003377 (xmlHashDeallocator) xmlSchemaFreeModelGroupDef);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003378 if (schema->idcDef != NULL)
3379 xmlHashFree(schema->idcDef,
3380 (xmlHashDeallocator) xmlSchemaFreeIDC);
Daniel Veillard1d913862003-11-21 00:28:39 +00003381 if (schema->schemasImports != NULL)
3382 xmlHashFree(schema->schemasImports,
3383 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003384 if (schema->includes != NULL) {
3385 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
3386 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003387 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003388 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00003389 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003390 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003391 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003392 xmlFree(schema);
3393}
3394
3395/************************************************************************
3396 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00003397 * Debug functions *
3398 * *
3399 ************************************************************************/
3400
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003401#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003402
Daniel Veillard4255d502002-04-16 15:50:10 +00003403/**
3404 * xmlSchemaElementDump:
3405 * @elem: an element
3406 * @output: the file output
3407 *
3408 * Dump the element
3409 */
3410static void
3411xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003412 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003413 const xmlChar * namespace ATTRIBUTE_UNUSED,
3414 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003415{
3416 if (elem == NULL)
3417 return;
3418
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003419 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
3420 fprintf(output, "Particle: %s", name);
3421 fprintf(output, ", term element: %s", elem->ref);
3422 if (elem->refNs != NULL)
3423 fprintf(output, " ns %s", elem->refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003424 } else {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003425 fprintf(output, "Element");
3426 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
3427 fprintf(output, " (global)");
3428 fprintf(output, ": %s ", elem->name);
3429 if (namespace != NULL)
3430 fprintf(output, "ns %s", namespace);
3431 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003432 fprintf(output, "\n");
3433 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003434 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003435 if (elem->maxOccurs >= UNBOUNDED)
3436 fprintf(output, "max: unbounded\n");
3437 else if (elem->maxOccurs != 1)
3438 fprintf(output, "max: %d\n", elem->maxOccurs);
3439 else
3440 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003441 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003442 /*
3443 * Misc other properties.
3444 */
3445 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
3446 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
3447 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
3448 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
3449 (elem->id != NULL)) {
3450 fprintf(output, " props: ");
3451 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
3452 fprintf(output, "[fixed] ");
3453 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
3454 fprintf(output, "[default] ");
3455 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
3456 fprintf(output, "[abstract] ");
3457 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
3458 fprintf(output, "[nillable] ");
3459 if (elem->id != NULL)
3460 fprintf(output, "[id: '%s'] ", elem->id);
3461 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003462 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003463 /*
3464 * Default/fixed value.
3465 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003466 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003467 fprintf(output, " value: '%s'\n", elem->value);
3468 /*
3469 * Type.
3470 */
3471 if (elem->namedType != NULL) {
3472 fprintf(output, " type: %s ", elem->namedType);
3473 if (elem->namedTypeNs != NULL)
3474 fprintf(output, "ns %s\n", elem->namedTypeNs);
3475 else
3476 fprintf(output, "\n");
3477 }
3478 /*
3479 * Substitution group.
3480 */
3481 if (elem->substGroup != NULL) {
3482 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
3483 if (elem->substGroupNs != NULL)
3484 fprintf(output, "ns %s\n", elem->substGroupNs);
3485 else
3486 fprintf(output, "\n");
3487 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003488}
3489
3490/**
3491 * xmlSchemaAnnotDump:
3492 * @output: the file output
3493 * @annot: a annotation
3494 *
3495 * Dump the annotation
3496 */
3497static void
3498xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
3499{
3500 xmlChar *content;
3501
3502 if (annot == NULL)
3503 return;
3504
3505 content = xmlNodeGetContent(annot->content);
3506 if (content != NULL) {
3507 fprintf(output, " Annot: %s\n", content);
3508 xmlFree(content);
3509 } else
3510 fprintf(output, " Annot: empty\n");
3511}
3512
3513/**
3514 * xmlSchemaTypeDump:
3515 * @output: the file output
3516 * @type: a type structure
3517 *
3518 * Dump a SchemaType structure
3519 */
3520static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003521xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
3522{
3523 xmlChar *str = NULL;
3524 xmlSchemaTreeItemPtr term;
3525 char shift[100];
3526 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003527
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003528 if (particle == NULL)
3529 return;
3530 for (i = 0;((i < depth) && (i < 25));i++)
3531 shift[2 * i] = shift[2 * i + 1] = ' ';
3532 shift[2 * i] = shift[2 * i + 1] = 0;
3533 fprintf(output, shift);
3534 if (particle->children == NULL) {
3535 fprintf(output, "MISSING particle term\n");
3536 return;
3537 }
3538 term = particle->children;
3539 switch (term->type) {
3540 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003541 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003542 ((xmlSchemaElementPtr)term)->targetNamespace,
3543 ((xmlSchemaElementPtr)term)->name));
3544 break;
3545 case XML_SCHEMA_TYPE_SEQUENCE:
3546 fprintf(output, "SEQUENCE");
3547 break;
3548 case XML_SCHEMA_TYPE_CHOICE:
3549 fprintf(output, "CHOICE");
3550 break;
3551 case XML_SCHEMA_TYPE_ALL:
3552 fprintf(output, "ALL");
3553 break;
3554 case XML_SCHEMA_TYPE_ANY:
3555 fprintf(output, "ANY");
3556 break;
3557 default:
3558 fprintf(output, "UNKNOWN\n");
3559 return;
3560 }
3561 if (particle->minOccurs != 1)
3562 fprintf(output, " min: %d", particle->minOccurs);
3563 if (particle->maxOccurs >= UNBOUNDED)
3564 fprintf(output, " max: unbounded");
3565 else if (particle->maxOccurs != 1)
3566 fprintf(output, " max: %d", particle->maxOccurs);
3567 fprintf(output, "\n");
3568 if (((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
3569 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
3570 (term->type == XML_SCHEMA_TYPE_ALL)) &&
3571 (term->children != NULL)) {
3572 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
3573 output, depth +1);
3574 }
3575 if (particle->next != NULL)
3576 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
3577 output, depth);
3578}
3579/**
3580 * xmlSchemaTypeDump:
3581 * @output: the file output
3582 * @type: a type structure
3583 *
3584 * Dump a SchemaType structure
3585 */
3586static void
Daniel Veillard4255d502002-04-16 15:50:10 +00003587xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
3588{
3589 if (type == NULL) {
3590 fprintf(output, "Type: NULL\n");
3591 return;
3592 }
3593 fprintf(output, "Type: ");
3594 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003595 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003596 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003597 fprintf(output, "no name ");
3598 if (type->targetNamespace != NULL)
3599 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003600 switch (type->type) {
3601 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003602 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003603 break;
3604 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003605 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003606 break;
3607 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003608 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003609 break;
3610 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003611 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003612 break;
3613 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003614 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003615 break;
3616 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003617 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003618 break;
3619 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003620 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003621 break;
3622 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003623 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003624 break;
3625 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003626 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003627 break;
3628 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003629 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003630 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003631 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003632 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003633 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003634 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003635 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003636 break;
3637 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003638 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003639 break;
3640 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003641 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003642 break;
3643 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003644 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003645 break;
3646 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003647 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003648 break;
3649 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003650 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003651 break;
3652 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003653 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003654 break;
3655 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003656 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003657 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003658 }
3659 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003660 if (type->base != NULL) {
3661 fprintf(output, " base type: %s", type->base);
3662 if (type->baseNs != NULL)
3663 fprintf(output, " ns %s\n", type->baseNs);
3664 else
3665 fprintf(output, "\n");
3666 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003667 if (type->annot != NULL)
3668 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003669#ifdef DUMP_CONTENT_MODEL
3670 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
3671 (type->subtypes != NULL)) {
3672 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
3673 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003674 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003675#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003676}
3677
3678/**
3679 * xmlSchemaDump:
3680 * @output: the file output
3681 * @schema: a schema structure
3682 *
3683 * Dump a Schema structure.
3684 */
3685void
3686xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3687{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003688 if (output == NULL)
3689 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003690 if (schema == NULL) {
3691 fprintf(output, "Schemas: NULL\n");
3692 return;
3693 }
3694 fprintf(output, "Schemas: ");
3695 if (schema->name != NULL)
3696 fprintf(output, "%s, ", schema->name);
3697 else
3698 fprintf(output, "no name, ");
3699 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00003700 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003701 else
3702 fprintf(output, "no target namespace");
3703 fprintf(output, "\n");
3704 if (schema->annot != NULL)
3705 xmlSchemaAnnotDump(output, schema->annot);
3706
3707 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
3708 output);
3709 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003710 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00003711}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003712
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003713#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003714/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003715 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003716 * @vctxt: the WXS validation context
3717 *
3718 * Displays the current IDC table for debug purposes.
3719 */
3720static void
3721xmlSchemaDebugDumpIDCTable(FILE * output,
3722 const xmlChar *namespaceName,
3723 const xmlChar *localName,
3724 xmlSchemaPSVIIDCBindingPtr bind)
3725{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003726 xmlChar *str = NULL, *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003727 xmlSchemaPSVIIDCNodePtr tab;
3728 xmlSchemaPSVIIDCKeyPtr key;
3729 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003730
3731 fprintf(output, "IDC: TABLES on %s\n",
3732 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003733 FREE_AND_NULL(str)
3734
3735 if (bind == NULL)
3736 return;
3737 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003738 fprintf(output, "IDC: BINDING %s\n",
3739 xmlSchemaFormatQName(&str, bind->definition->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003740 bind->definition->name));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003741 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003742 for (i = 0; i < bind->nbNodes; i++) {
3743 tab = bind->nodeTable[i];
3744 fprintf(output, " ( ");
3745 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003746 key = tab->keys[j];
3747 if ((key != NULL) && (key->val != NULL)) {
3748 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003749 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003750 fprintf(output, "\"%s\" ", value);
3751 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003752 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003753 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003754 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003755 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003756 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003757 else
3758 fprintf(output, "(key missing), ");
3759 }
3760 fprintf(output, ")\n");
3761 }
3762 bind = bind->next;
3763 } while (bind != NULL);
3764}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003765#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003766#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00003767
3768/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003769 * *
3770 * Utilities *
3771 * *
3772 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003773
Daniel Veillardc0826a72004-08-10 14:17:33 +00003774/**
3775 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003776 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003777 * @name: the name of the attribute
3778 *
3779 * Seeks an attribute with a name of @name in
3780 * no namespace.
3781 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003782 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003783 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003784static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003785xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003786{
3787 xmlAttrPtr prop;
3788
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003789 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003790 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003791 prop = node->properties;
3792 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003793 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003794 return(prop);
3795 prop = prop->next;
3796 }
3797 return (NULL);
3798}
3799
3800/**
3801 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003802 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003803 * @uri: the uri
3804 * @name: the name of the attribute
3805 *
3806 * Seeks an attribute with a local name of @name and
3807 * a namespace URI of @uri.
3808 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003809 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003810 */
3811static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003812xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003813{
3814 xmlAttrPtr prop;
3815
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003816 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003817 return(NULL);
3818 prop = node->properties;
3819 while (prop != NULL) {
3820 if ((prop->ns != NULL) &&
3821 xmlStrEqual(prop->name, BAD_CAST name) &&
3822 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003823 return(prop);
3824 prop = prop->next;
3825 }
3826 return (NULL);
3827}
3828
3829static const xmlChar *
3830xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3831{
3832 xmlChar *val;
3833 const xmlChar *ret;
3834
3835 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003836 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00003837 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00003838 ret = xmlDictLookup(ctxt->dict, val, -1);
3839 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003840 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003841}
3842
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003843/**
3844 * xmlSchemaGetProp:
3845 * @ctxt: the parser context
3846 * @node: the node
3847 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003848 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003849 * Read a attribute value and internalize the string
3850 *
3851 * Returns the string or NULL if not present.
3852 */
3853static const xmlChar *
3854xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3855 const char *name)
3856{
3857 xmlChar *val;
3858 const xmlChar *ret;
3859
3860 val = xmlGetProp(node, BAD_CAST name);
3861 if (val == NULL)
3862 return(NULL);
3863 ret = xmlDictLookup(ctxt->dict, val, -1);
3864 xmlFree(val);
3865 return(ret);
3866}
3867
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003868/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003869 * *
3870 * Parsing functions *
3871 * *
3872 ************************************************************************/
3873
3874/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003875 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003876 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003877 * @name: the element name
3878 * @ns: the element namespace
3879 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003880 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003881 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003882 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003883 */
3884static xmlSchemaElementPtr
3885xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003886 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003887{
3888 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003889
3890 if ((name == NULL) || (schema == NULL))
3891 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003892
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003893 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003894 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003895 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003896 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003897 } else
3898 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003899 /*
3900 * This one was removed, since top level element declarations have
3901 * the target namespace specified in targetNamespace of the <schema>
3902 * information element, even if elementFormDefault is "unqualified".
3903 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003904
William M. Bracke7091952004-05-11 15:09:58 +00003905 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003906 if (xmlStrEqual(namespace, schema->targetNamespace))
3907 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3908 else
3909 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003910 if ((ret != NULL) &&
3911 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003912 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003913 }
William M. Bracke7091952004-05-11 15:09:58 +00003914 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003915
William M. Brack2f2a6632004-08-20 23:09:47 +00003916 /*
3917 * Removed since imported components will be hold by the main schema only.
3918 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003919 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003920 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003921 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003922 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003923 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003924 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003925 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3926 return (ret);
3927 } else
3928 ret = NULL;
3929 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003930 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003931#ifdef DEBUG
3932 if (ret == NULL) {
3933 if (namespace == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003934 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003935 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003936 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003937 namespace);
3938 }
3939#endif
3940 return (ret);
3941}
3942
3943/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003944 * xmlSchemaGetType:
3945 * @schema: the schemas context
3946 * @name: the type name
3947 * @ns: the type namespace
3948 *
3949 * Lookup a type in the schemas or the predefined types
3950 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003951 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00003952 */
3953static xmlSchemaTypePtr
3954xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003955 const xmlChar * namespace)
3956{
Daniel Veillard4255d502002-04-16 15:50:10 +00003957 xmlSchemaTypePtr ret;
3958
3959 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003960 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003961 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003962 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003963 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003964 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003965 }
3966 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00003967 if (ret != NULL)
3968 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003969 /*
3970 * Removed, since the imported components will be grafted on the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003971 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00003972 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003973 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003974 else
Daniel Veillard1d913862003-11-21 00:28:39 +00003975 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003976 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003977 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003978 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
3979 return (ret);
3980 } else
3981 ret = NULL;
3982 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003983 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003984#ifdef DEBUG
3985 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003986 if (namespace == NULL)
3987 fprintf(stderr, "Unable to lookup type %s", name);
3988 else
3989 fprintf(stderr, "Unable to lookup type %s:%s", name,
3990 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003991 }
3992#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003993 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003994}
3995
Daniel Veillard3646d642004-06-02 19:19:14 +00003996/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003997 * xmlSchemaGetAttributeDecl:
3998 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00003999 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004000 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004001 *
4002 * Lookup a an attribute in the schema or imported schemas
4003 *
4004 * Returns the attribute declaration or NULL if not found.
4005 */
4006static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004007xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillard3646d642004-06-02 19:19:14 +00004008 const xmlChar * namespace)
4009{
4010 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004011
4012 if ((name == NULL) || (schema == NULL))
4013 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004014
4015
Daniel Veillard3646d642004-06-02 19:19:14 +00004016 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
4017 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004018 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004019 else
4020 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004021 /*
4022 * Removed, since imported components will be hold by the main schema only.
4023 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004024 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004025 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004026 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004027 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004028 if (import != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004029 ret = xmlSchemaGetAttributeDecl(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004030 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
4031 return (ret);
4032 } else
4033 ret = NULL;
4034 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004035 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004036#ifdef DEBUG
4037 if (ret == NULL) {
4038 if (namespace == NULL)
4039 fprintf(stderr, "Unable to lookup attribute %s", name);
4040 else
4041 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4042 namespace);
4043 }
4044#endif
4045 return (ret);
4046}
4047
4048/**
4049 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004050 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004051 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004052 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004053 *
4054 * Lookup a an attribute group in the schema or imported schemas
4055 *
4056 * Returns the attribute group definition or NULL if not found.
4057 */
4058static xmlSchemaAttributeGroupPtr
4059xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4060 const xmlChar * namespace)
4061{
4062 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004063
4064 if ((name == NULL) || (schema == NULL))
4065 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004066
4067
Daniel Veillard3646d642004-06-02 19:19:14 +00004068 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
4069 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004070 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004071 else
4072 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004073 /*
4074 * Removed since imported components will be hold by the main schema only.
4075 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004076 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004077 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004078 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004079 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004080 if (import != NULL) {
4081 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
4082 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
4083 return (ret);
4084 else
4085 ret = NULL;
4086 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004087 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004088#ifdef DEBUG
4089 if (ret == NULL) {
4090 if (namespace == NULL)
4091 fprintf(stderr, "Unable to lookup attribute group %s", name);
4092 else
4093 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4094 namespace);
4095 }
4096#endif
4097 return (ret);
4098}
4099
4100/**
4101 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004102 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004103 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004104 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004105 *
4106 * Lookup a group in the schema or imported schemas
4107 *
4108 * Returns the group definition or NULL if not found.
4109 */
4110static xmlSchemaTypePtr
4111xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4112 const xmlChar * namespace)
4113{
4114 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004115
4116 if ((name == NULL) || (schema == NULL))
4117 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004118
Daniel Veillard3646d642004-06-02 19:19:14 +00004119 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
William M. Brack2f2a6632004-08-20 23:09:47 +00004120 /*
4121 * Removed since imported components will be hold by the main schema only.
4122 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004123 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004124 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004125 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004126 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004127 if (import != NULL) {
4128 ret = xmlSchemaGetGroup(import->schema, name, namespace);
4129 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
4130 return (ret);
4131 else
4132 ret = NULL;
4133 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004134 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004135#ifdef DEBUG
4136 if (ret == NULL) {
4137 if (namespace == NULL)
4138 fprintf(stderr, "Unable to lookup group %s", name);
4139 else
4140 fprintf(stderr, "Unable to lookup group %s:%s", name,
4141 namespace);
4142 }
4143#endif
4144 return (ret);
4145}
4146
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004147/**
4148 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004149 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004150 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004151 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004152 *
4153 * Lookup a group in the schema or imported schemas
4154 *
4155 * Returns the group definition or NULL if not found.
4156 */
4157static xmlSchemaTreeItemPtr
4158xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4159 xmlSchemaTypeType itemType,
4160 const xmlChar *name,
4161 const xmlChar *targetNs)
4162{
4163 switch (itemType) {
4164 case XML_SCHEMA_TYPE_GROUP:
4165 return ((xmlSchemaTreeItemPtr) xmlSchemaGetGroup(schema,
4166 name, targetNs));
4167 case XML_SCHEMA_TYPE_ELEMENT:
4168 return ((xmlSchemaTreeItemPtr) xmlSchemaGetElem(schema,
4169 name, targetNs));
4170 default:
4171 return (NULL);
4172 }
4173}
4174
Daniel Veillard4255d502002-04-16 15:50:10 +00004175/************************************************************************
4176 * *
4177 * Parsing functions *
4178 * *
4179 ************************************************************************/
4180
4181#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004182 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00004183
4184/**
4185 * xmlSchemaIsBlank:
4186 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004187 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00004188 *
4189 * Check if a string is ignorable
4190 *
4191 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4192 */
4193static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004194xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004195{
Daniel Veillard4255d502002-04-16 15:50:10 +00004196 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004197 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004198 if (len < 0) {
4199 while (*str != 0) {
4200 if (!(IS_BLANK_CH(*str)))
4201 return (0);
4202 str++;
4203 }
4204 } else while ((*str != 0) && (len != 0)) {
4205 if (!(IS_BLANK_CH(*str)))
4206 return (0);
4207 str++;
4208 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00004209 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004210
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004211 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004212}
4213
4214/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004215 * xmlSchemaAddAssembledItem:
4216 * @ctxt: a schema parser context
4217 * @schema: the schema being built
4218 * @item: the item
4219 *
4220 * Add a item to the schema's list of current items.
4221 * This is used if the schema was already constructed and
4222 * new schemata need to be added to it.
4223 * *WARNING* this interface is highly subject to change.
4224 *
4225 * Returns 0 if suceeds and -1 if an internal error occurs.
4226 */
4227static int
4228xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
4229 xmlSchemaTypePtr item)
4230{
4231 static int growSize = 100;
4232 xmlSchemaAssemblePtr ass;
4233
4234 ass = ctxt->assemble;
4235 if (ass->sizeItems < 0) {
4236 /* If disabled. */
4237 return (0);
4238 }
4239 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004240 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004241 if (ass->items == NULL) {
4242 xmlSchemaPErrMemory(ctxt,
4243 "allocating new item buffer", NULL);
4244 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004245 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004246 ass->sizeItems = growSize;
4247 } else if (ass->sizeItems <= ass->nbItems) {
4248 ass->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004249 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004250 ass->sizeItems * sizeof(xmlSchemaTypePtr));
4251 if (ass->items == NULL) {
4252 xmlSchemaPErrMemory(ctxt,
4253 "growing item buffer", NULL);
4254 ass->sizeItems = 0;
4255 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004256 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004257 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004258 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004259 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
4260 return (0);
4261}
4262
4263/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004264 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004265 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004266 * @schema: the schema being built
4267 * @name: the item name
4268 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004269 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00004270 * *WARNING* this interface is highly subject to change
4271 *
4272 * Returns the new struture or NULL in case of error
4273 */
4274static xmlSchemaNotationPtr
4275xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004276 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004277{
4278 xmlSchemaNotationPtr ret = NULL;
4279 int val;
4280
4281 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4282 return (NULL);
4283
4284 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004285 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004286 if (schema->notaDecl == NULL)
4287 return (NULL);
4288
4289 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
4290 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004291 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004292 return (NULL);
4293 }
4294 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004295 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004296 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
4297 ret);
4298 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004299 /*
4300 * TODO: This should never happen, since a unique name will be computed.
4301 * If it fails, then an other internal error must have occured.
4302 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004303 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
4304 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004305 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004306 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004307 xmlFree(ret);
4308 return (NULL);
4309 }
4310 return (ret);
4311}
4312
4313
4314/**
4315 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004316 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004317 * @schema: the schema being built
4318 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004319 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004320 *
4321 * Add an XML schema Attrribute declaration
4322 * *WARNING* this interface is highly subject to change
4323 *
4324 * Returns the new struture or NULL in case of error
4325 */
4326static xmlSchemaAttributePtr
4327xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004328 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004329 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004330{
4331 xmlSchemaAttributePtr ret = NULL;
4332 int val;
4333
4334 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4335 return (NULL);
4336
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004337#ifdef DEBUG
4338 fprintf(stderr, "Adding attribute %s\n", name);
4339 if (namespace != NULL)
4340 fprintf(stderr, " target namespace %s\n", namespace);
4341#endif
4342
Daniel Veillard4255d502002-04-16 15:50:10 +00004343 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004344 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004345 if (schema->attrDecl == NULL)
4346 return (NULL);
4347
4348 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
4349 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004350 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004351 return (NULL);
4352 }
4353 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004354 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004355 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00004356 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004357 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004358 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004359 if (topLevel) {
4360 xmlSchemaPCustomErr(ctxt,
4361 XML_SCHEMAP_REDEFINED_ATTR,
4362 NULL, NULL, node,
4363 "A global attribute declaration with the name '%s' does "
4364 "already exist", name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004365 xmlFree(ret);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004366 return (NULL);
4367 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004368 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004369 /*
4370 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
4371 * in the scenario:
4372 * 1. multiple top-level complex types have different target
4373 * namespaces but have the SAME NAME; this can happen if
4374 * schemata are imported
4375 * 2. those complex types contain attributes with an equal name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004376 * 3. those attributes are in no namespace
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004377 * We will compute a new context string.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004378 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004379 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004380 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004381 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004382
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004383 if (val != 0) {
4384 xmlSchemaPCustomErr(ctxt,
4385 XML_SCHEMAP_INTERNAL,
4386 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004387 "Internal error: xmlSchemaAddAttribute, "
4388 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004389 "could not be added to the hash.", name);
4390 xmlFree(ret);
4391 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004392 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004393 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004394 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004395 if (ctxt->assemble != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004396 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004397 return (ret);
4398}
4399
4400/**
4401 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004402 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004403 * @schema: the schema being built
4404 * @name: the item name
4405 *
4406 * Add an XML schema Attrribute Group declaration
4407 *
4408 * Returns the new struture or NULL in case of error
4409 */
4410static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004411xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00004412 xmlSchemaPtr schema, const xmlChar * name,
4413 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004414{
4415 xmlSchemaAttributeGroupPtr ret = NULL;
4416 int val;
4417
4418 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4419 return (NULL);
4420
4421 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004422 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004423 if (schema->attrgrpDecl == NULL)
4424 return (NULL);
4425
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004426 ret =
4427 (xmlSchemaAttributeGroupPtr)
4428 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00004429 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004430 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004431 return (NULL);
4432 }
4433 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004434 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004435 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004436 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004437 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004438 xmlSchemaPCustomErr(ctxt,
4439 XML_SCHEMAP_REDEFINED_ATTRGROUP,
4440 NULL, NULL, node,
4441 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004442 xmlFree(ret);
4443 return (NULL);
4444 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004445 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004446 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004447 return (ret);
4448}
4449
4450/**
4451 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004452 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004453 * @schema: the schema being built
4454 * @name: the type name
4455 * @namespace: the type namespace
4456 *
4457 * Add an XML schema Element declaration
4458 * *WARNING* this interface is highly subject to change
4459 *
4460 * Returns the new struture or NULL in case of error
4461 */
4462static xmlSchemaElementPtr
4463xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004464 const xmlChar * name, const xmlChar * namespace,
4465 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004466{
4467 xmlSchemaElementPtr ret = NULL;
4468 int val;
4469
4470 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4471 return (NULL);
4472
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004473#ifdef DEBUG
4474 fprintf(stderr, "Adding element %s\n", name);
4475 if (namespace != NULL)
4476 fprintf(stderr, " target namespace %s\n", namespace);
4477#endif
4478
Daniel Veillard4255d502002-04-16 15:50:10 +00004479 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004480 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004481 if (schema->elemDecl == NULL)
4482 return (NULL);
4483
4484 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
4485 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004486 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004487 return (NULL);
4488 }
4489 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004490 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004491 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004492 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004493 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004494 if (topLevel) {
4495 xmlSchemaPCustomErr(ctxt,
4496 XML_SCHEMAP_REDEFINED_ELEMENT,
4497 NULL, NULL, node,
4498 "A global element declaration with the name '%s' does "
4499 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004500 xmlFree(ret);
4501 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00004502 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004503 char buf[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00004504
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004505 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004506 val = xmlHashAddEntry3(schema->elemDecl, name,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004507 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004508 if (val != 0) {
4509 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004510 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00004511 NULL, NULL, node,
4512 "Internal error: xmlSchemaAddElement, "
4513 "a dublicate element declaration with the name '%s' "
4514 "could not be added to the hash.", name);
4515 xmlFree(ret);
4516 return (NULL);
4517 }
4518 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004519
Daniel Veillard4255d502002-04-16 15:50:10 +00004520 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004521 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004522 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004523 return (ret);
4524}
4525
4526/**
4527 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004528 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004529 * @schema: the schema being built
4530 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004531 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004532 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00004533 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00004534 * *WARNING* this interface is highly subject to change
4535 *
4536 * Returns the new struture or NULL in case of error
4537 */
4538static xmlSchemaTypePtr
4539xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004540 const xmlChar * name, const xmlChar * namespace,
4541 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004542{
4543 xmlSchemaTypePtr ret = NULL;
4544 int val;
4545
4546 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4547 return (NULL);
4548
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004549#ifdef DEBUG
4550 fprintf(stderr, "Adding type %s\n", name);
4551 if (namespace != NULL)
4552 fprintf(stderr, " target namespace %s\n", namespace);
4553#endif
4554
Daniel Veillard4255d502002-04-16 15:50:10 +00004555 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004556 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004557 if (schema->typeDecl == NULL)
4558 return (NULL);
4559
4560 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
4561 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004562 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004563 return (NULL);
4564 }
4565 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004566 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004567 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004568 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004569 if (val != 0) {
4570 if (ctxt->includes == 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004571 xmlSchemaPCustomErr(ctxt,
4572 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004573 NULL, NULL, node,
4574 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004575 xmlFree(ret);
4576 return (NULL);
4577 } else {
4578 xmlSchemaTypePtr prev;
4579
4580 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
4581 if (prev == NULL) {
4582 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004583 XML_ERR_INTERNAL_ERROR,
4584 "Internal error: xmlSchemaAddType, on type "
4585 "'%s'.\n",
4586 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004587 xmlFree(ret);
4588 return (NULL);
4589 }
4590 ret->redef = prev->redef;
4591 prev->redef = ret;
4592 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004593 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004594 ret->node = node;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004595 ret->minOccurs = 1;
4596 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00004597 ret->attributeUses = NULL;
4598 ret->attributeWildcard = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004599 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004600 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004601 return (ret);
4602}
4603
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004604static xmlSchemaQNameRefPtr
4605xmlSchemaNewQNameRef(xmlSchemaPtr schema,
4606 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004607 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004608 const xmlChar *refNs)
4609{
4610 xmlSchemaQNameRefPtr ret;
4611
4612 ret = (xmlSchemaQNameRefPtr)
4613 xmlMalloc(sizeof(xmlSchemaQNameRef));
4614 if (ret == NULL) {
4615 xmlSchemaPErrMemory(NULL, "allocating QName reference item",
4616 NULL);
4617 return (NULL);
4618 }
4619 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
4620 ret->name = refName;
4621 ret->targetNamespace = refNs;
4622 ret->item = NULL;
4623 ret->itemType = refType;
4624 /*
4625 * Store the reference item in the schema.
4626 */
4627 xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret);
4628 return (ret);
4629}
4630
4631/**
4632 * xmlSchemaAddModelGroup:
4633 * @ctxt: a schema parser context
4634 * @schema: the schema being built
4635 * @type: the "compositor" type of the model group
4636 * @container: the internal component name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004637 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004638 *
4639 * Adds a schema model group
4640 * *WARNING* this interface is highly subject to change
4641 *
4642 * Returns the new struture or NULL in case of error
4643 */
4644static xmlSchemaModelGroupPtr
4645xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4646 xmlSchemaTypeType type, const xmlChar **container,
4647 xmlNodePtr node)
4648{
4649 xmlSchemaModelGroupPtr ret = NULL;
4650 xmlChar buf[30];
4651
4652 if ((ctxt == NULL) || (schema == NULL))
4653 return (NULL);
4654
4655#ifdef DEBUG
4656 fprintf(stderr, "Adding model group component\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004657#endif
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004658 ret = (xmlSchemaModelGroupPtr)
4659 xmlMalloc(sizeof(xmlSchemaModelGroup));
4660 if (ret == NULL) {
4661 xmlSchemaPErrMemory(ctxt, "allocating model group component",
4662 NULL);
4663 return (NULL);
4664 }
4665 ret->type = type;
4666 ret->annot = NULL;
4667 ret->node = node;
4668 ret->children = NULL;
4669 ret->next = NULL;
4670 if (type == XML_SCHEMA_TYPE_SEQUENCE) {
4671 if (container != NULL)
4672 snprintf((char *) buf, 29, "#seq%d", ctxt->counter++ + 1);
4673 } else if (type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004674 if (container != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004675 snprintf((char *) buf, 29, "#cho%d", ctxt->counter++ + 1);
4676 } else {
4677 if (container != NULL)
4678 snprintf((char *) buf, 29, "#all%d", ctxt->counter++ + 1);
4679 }
4680 if (container != NULL)
4681 *container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
4682 /*
4683 * Add to volatile items.
4684 * TODO: this should be changed someday.
4685 */
4686 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4687 xmlFree(ret);
4688 return (NULL);
4689 }
4690 return (ret);
4691}
4692
4693
4694/**
4695 * xmlSchemaAddParticle:
4696 * @ctxt: a schema parser context
4697 * @schema: the schema being built
4698 * @node: the corresponding node in the schema doc
4699 * @min: the minOccurs
4700 * @max: the maxOccurs
4701 *
4702 * Adds an XML schema particle component.
4703 * *WARNING* this interface is highly subject to change
4704 *
4705 * Returns the new struture or NULL in case of error
4706 */
4707static xmlSchemaParticlePtr
4708xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4709 xmlNodePtr node, int min, int max)
4710{
4711 xmlSchemaParticlePtr ret = NULL;
4712 if ((ctxt == NULL) || (schema == NULL))
4713 return (NULL);
4714
4715#ifdef DEBUG
4716 fprintf(stderr, "Adding particle component\n");
4717#endif
4718 ret = (xmlSchemaParticlePtr)
4719 xmlMalloc(sizeof(xmlSchemaParticle));
4720 if (ret == NULL) {
4721 xmlSchemaPErrMemory(ctxt, "allocating particle component",
4722 NULL);
4723 return (NULL);
4724 }
4725 ret->type = XML_SCHEMA_TYPE_PARTICLE;
4726 ret->annot = NULL;
4727 ret->node = node;
4728 ret->minOccurs = min;
4729 ret->maxOccurs = max;
4730 ret->next = NULL;
4731 ret->children = NULL;
4732
4733 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4734 xmlFree(ret);
4735 return (NULL);
4736 }
4737 return (ret);
4738}
4739
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004740/**
4741 * xmlSchemaAddGroup:
4742 * @ctxt: a schema validation context
4743 * @schema: the schema being built
4744 * @name: the group name
4745 *
4746 * Add an XML schema Group definition
4747 *
4748 * Returns the new struture or NULL in case of error
4749 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004750static xmlSchemaModelGroupDefPtr
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004751xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004752 const xmlChar *name, const xmlChar *namespaceName,
4753 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004754{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004755 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004756 int val;
4757
4758 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4759 return (NULL);
4760
4761 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004762 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004763 if (schema->groupDecl == NULL)
4764 return (NULL);
4765
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004766 ret = (xmlSchemaModelGroupDefPtr) xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004767 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004768 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004769 return (NULL);
4770 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004771 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004772 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004773 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004774 ret->node = node;
4775 ret->targetNamespace = namespaceName;
4776 val = xmlHashAddEntry2(schema->groupDecl, ret->name, namespaceName, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004777 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004778 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004779 XML_SCHEMAP_REDEFINED_GROUP,
4780 NULL, NULL, node,
4781 "A global model group definition with the name '%s' does already "
4782 "exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004783 xmlFree(ret);
4784 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004785 }
4786 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004787 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004788 return (ret);
4789}
4790
Daniel Veillard3646d642004-06-02 19:19:14 +00004791/**
4792 * xmlSchemaNewWildcardNs:
4793 * @ctxt: a schema validation context
4794 *
4795 * Creates a new wildcard namespace constraint.
4796 *
4797 * Returns the new struture or NULL in case of error
4798 */
4799static xmlSchemaWildcardNsPtr
4800xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
4801{
4802 xmlSchemaWildcardNsPtr ret;
4803
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004804 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004805 xmlMalloc(sizeof(xmlSchemaWildcardNs));
4806 if (ret == NULL) {
4807 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004808 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00004809 }
4810 ret->value = NULL;
4811 ret->next = NULL;
4812 return (ret);
4813}
4814
4815/**
4816 * xmlSchemaAddWildcard:
4817 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004818 * @schema: a schema
4819 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004820 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004821 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00004822 *
4823 * Returns the new struture or NULL in case of error
4824 */
4825static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004826xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4827 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00004828{
4829 xmlSchemaWildcardPtr ret = NULL;
4830
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004831 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00004832 return (NULL);
4833
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004834#ifdef DEBUG
4835 fprintf(stderr, "Adding wildcard component\n");
4836#endif
4837
Daniel Veillard3646d642004-06-02 19:19:14 +00004838 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
4839 if (ret == NULL) {
4840 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
4841 return (NULL);
4842 }
4843 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004844 ret->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +00004845 ret->minOccurs = 1;
4846 ret->maxOccurs = 1;
4847
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004848 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4849 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, NULL, node,
4850 "Failed to add a wildcard component to the list", NULL);
4851 xmlFree(ret);
4852 return (NULL);
4853 }
Daniel Veillard3646d642004-06-02 19:19:14 +00004854 return (ret);
4855}
4856
Daniel Veillard4255d502002-04-16 15:50:10 +00004857/************************************************************************
4858 * *
4859 * Utilities for parsing *
4860 * *
4861 ************************************************************************/
4862
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004863#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004864/**
4865 * xmlGetQNameProp:
4866 * @ctxt: a schema validation context
4867 * @node: a subtree containing XML Schema informations
4868 * @name: the attribute name
4869 * @namespace: the result namespace if any
4870 *
4871 * Extract a QName Attribute value
4872 *
4873 * Returns the NCName or NULL if not found, and also update @namespace
4874 * with the namespace URI
4875 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004876static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00004877xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004878 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004879{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004880 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004881 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004882 const xmlChar *ret, *prefix;
4883 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004884 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004885
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004886 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004887 attr = xmlSchemaGetPropNode(node, name);
4888 if (attr == NULL)
4889 return (NULL);
4890 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004891
Daniel Veillard4255d502002-04-16 15:50:10 +00004892 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004893 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004894
Daniel Veillardba0153a2004-04-01 10:42:31 +00004895 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00004896 ns = xmlSearchNs(node->doc, node, 0);
4897 if (ns) {
4898 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4899 return (val);
4900 }
4901 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004902 ret = xmlSplitQName3(val, &len);
4903 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004904 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004905 }
4906 ret = xmlDictLookup(ctxt->dict, ret, -1);
4907 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00004908
4909 ns = xmlSearchNs(node->doc, node, prefix);
4910 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004911 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
4912 NULL, NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004913 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004914 "The QName value '%s' has no corresponding namespace "
4915 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004916 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004917 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004918 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004919 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004920}
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004921#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004922
4923/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004924 * xmlSchemaPValAttrNodeQNameValue:
4925 * @ctxt: a schema parser context
4926 * @schema: the schema context
4927 * @ownerDes: the designation of the parent element
4928 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004929 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00004930 * @local: the resulting local part if found, the attribute value otherwise
4931 * @uri: the resulting namespace URI if found
4932 *
4933 * Extracts the local name and the URI of a QName value and validates it.
4934 * This one is intended to be used on attribute values that
4935 * should resolve to schema components.
4936 *
4937 * Returns 0, in case the QName is valid, a positive error code
4938 * if not valid and -1 if an internal error occurs.
4939 */
4940static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004941xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004942 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004943 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004944 xmlSchemaTypePtr ownerItem,
4945 xmlAttrPtr attr,
4946 const xmlChar *value,
4947 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004948 const xmlChar **local)
4949{
4950 const xmlChar *pref;
4951 xmlNsPtr ns;
4952 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004953
Daniel Veillardc0826a72004-08-10 14:17:33 +00004954 *uri = NULL;
4955 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004956 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004957 if (ret > 0) {
4958 xmlSchemaPSimpleTypeErr(ctxt,
4959 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4960 ownerItem, (xmlNodePtr) attr,
4961 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
4962 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004963 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004964 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004965 } else if (ret < 0)
4966 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004967
4968 if (!strchr((char *) value, ':')) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004969 ns = xmlSearchNs(attr->doc, attr->parent, 0);
4970 if (ns)
4971 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4972 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
4973 /*
4974 * This one takes care of included schemas with no
4975 * target namespace.
4976 */
4977 *uri = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004978 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004979 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004980 return (0);
4981 }
4982 /*
4983 * At this point xmlSplitQName3 has to return a local name.
4984 */
4985 *local = xmlSplitQName3(value, &len);
4986 *local = xmlDictLookup(ctxt->dict, *local, -1);
4987 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004988 ns = xmlSearchNs(attr->doc, attr->parent, pref);
4989 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004990 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004991 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004992 ownerItem, (xmlNodePtr) attr,
4993 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
4994 "The value '%s' of simple type 'xs:QName' has no "
4995 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004996 return (ctxt->err);
4997 } else {
4998 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004999 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005000 return (0);
5001}
5002
5003/**
5004 * xmlSchemaPValAttrNodeQName:
5005 * @ctxt: a schema parser context
5006 * @schema: the schema context
5007 * @ownerDes: the designation of the owner element
5008 * @ownerItem: the owner as a schema object
5009 * @attr: the attribute node
5010 * @local: the resulting local part if found, the attribute value otherwise
5011 * @uri: the resulting namespace URI if found
5012 *
5013 * Extracts and validates the QName of an attribute value.
5014 * This one is intended to be used on attribute values that
5015 * should resolve to schema components.
5016 *
5017 * Returns 0, in case the QName is valid, a positive error code
5018 * if not valid and -1 if an internal error occurs.
5019 */
5020static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005021xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005022 xmlSchemaPtr schema,
5023 xmlChar **ownerDes,
5024 xmlSchemaTypePtr ownerItem,
5025 xmlAttrPtr attr,
5026 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005027 const xmlChar **local)
5028{
5029 const xmlChar *value;
5030
5031 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005032 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5033 ownerDes, ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005034}
5035
5036/**
5037 * xmlSchemaPValAttrQName:
5038 * @ctxt: a schema parser context
5039 * @schema: the schema context
5040 * @ownerDes: the designation of the parent element
5041 * @ownerItem: the owner as a schema object
5042 * @ownerElem: the parent node of the attribute
5043 * @name: the name of the attribute
5044 * @local: the resulting local part if found, the attribute value otherwise
5045 * @uri: the resulting namespace URI if found
5046 *
5047 * Extracts and validates the QName of an attribute value.
5048 *
5049 * Returns 0, in case the QName is valid, a positive error code
5050 * if not valid and -1 if an internal error occurs.
5051 */
5052static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005053xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5054 xmlSchemaPtr schema,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005055 xmlChar **ownerDes,
5056 xmlSchemaTypePtr ownerItem,
5057 xmlNodePtr ownerElem,
5058 const char *name,
5059 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005060 const xmlChar **local)
5061{
5062 xmlAttrPtr attr;
5063
5064 attr = xmlSchemaGetPropNode(ownerElem, name);
5065 if (attr == NULL) {
5066 *local = NULL;
5067 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005068 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005069 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005070 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5071 ownerDes, ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005072}
5073
5074/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005075 * xmlSchemaPValAttrID:
5076 * @ctxt: a schema parser context
5077 * @schema: the schema context
5078 * @ownerDes: the designation of the parent element
5079 * @ownerItem: the owner as a schema object
5080 * @ownerElem: the parent node of the attribute
5081 * @name: the name of the attribute
5082 *
5083 * Extracts and validates the ID of an attribute value.
5084 *
5085 * Returns 0, in case the ID is valid, a positive error code
5086 * if not valid and -1 if an internal error occurs.
5087 */
5088static int
5089xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005090 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005091 xmlSchemaTypePtr ownerItem,
5092 xmlNodePtr ownerElem,
5093 const xmlChar *name)
5094{
5095 int ret;
5096 xmlChar *value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005097 xmlAttrPtr attr;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005098
5099 value = xmlGetNoNsProp(ownerElem, name);
5100 if (value == NULL)
5101 return (0);
5102
5103 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5104 if (attr == NULL)
5105 return (-1);
5106
5107 ret = xmlValidateNCName(BAD_CAST value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005108 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005109 /*
5110 * NOTE: the IDness might have already be declared in the DTD
5111 */
5112 if (attr->atype != XML_ATTRIBUTE_ID) {
5113 xmlIDPtr res;
5114 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005115
5116 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005117 * TODO: Use xmlSchemaStrip here; it's not exported at this
5118 * moment.
5119 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005120 strip = xmlSchemaCollapseString(BAD_CAST value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005121 if (strip != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005122 value = strip;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005123 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
5124 if (res == NULL) {
5125 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005126 xmlSchemaPSimpleTypeErr(ctxt,
5127 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5128 ownerItem, (xmlNodePtr) attr,
5129 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5130 NULL, NULL, "Duplicate value '%s' of simple "
5131 "type 'xs:ID'", BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005132 } else
5133 attr->atype = XML_ATTRIBUTE_ID;
5134 if (strip != NULL)
5135 xmlFree(strip);
5136 }
5137 } else if (ret > 0) {
5138 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005139 xmlSchemaPSimpleTypeErr(ctxt,
5140 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5141 ownerItem, (xmlNodePtr) attr,
5142 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5143 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5144 "not a valid 'xs:NCName'",
5145 BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005146 }
5147 xmlFree(value);
5148
5149 return (ret);
5150}
5151
5152/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005153 * xmlGetMaxOccurs:
5154 * @ctxt: a schema validation context
5155 * @node: a subtree containing XML Schema informations
5156 *
5157 * Get the maxOccurs property
5158 *
5159 * Returns the default if not found, or the value
5160 */
5161static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005162xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5163 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005164{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005165 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005166 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005167 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005168
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005169 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5170 if (attr == NULL)
5171 return (def);
5172 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005173
5174 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005175 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005176 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005177 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5178 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005179 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005180 val, NULL, NULL, NULL);
5181 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005182 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005183 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005184 }
5185
5186 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005187 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005188 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005189 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005190 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005191 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5192 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005193 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005194 val, NULL, NULL, NULL);
5195 return (def);
5196 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005197 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005198 ret = ret * 10 + (*cur - '0');
5199 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005200 }
William M. Brack76e95df2003-10-18 16:20:14 +00005201 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005202 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005203 /*
5204 * TODO: Restrict the maximal value to Integer.
5205 */
5206 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005207 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005208 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5209 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005210 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005211 val, NULL, NULL, NULL);
5212 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005213 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005214 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005215}
5216
5217/**
5218 * xmlGetMinOccurs:
5219 * @ctxt: a schema validation context
5220 * @node: a subtree containing XML Schema informations
5221 *
5222 * Get the minOccurs property
5223 *
5224 * Returns the default if not found, or the value
5225 */
5226static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005227xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005228 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005229{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005230 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005231 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005232 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005233
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005234 attr = xmlSchemaGetPropNode(node, "minOccurs");
5235 if (attr == NULL)
5236 return (def);
5237 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005238 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005239 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005240 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005241 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005242 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005243 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5244 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005245 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005246 val, NULL, NULL, NULL);
5247 return (def);
5248 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005249 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005250 ret = ret * 10 + (*cur - '0');
5251 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005252 }
William M. Brack76e95df2003-10-18 16:20:14 +00005253 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005254 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005255 /*
5256 * TODO: Restrict the maximal value to Integer.
5257 */
5258 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005259 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005260 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5261 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005262 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005263 val, NULL, NULL, NULL);
5264 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005265 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005266 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005267}
5268
5269/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005270 * xmlSchemaPGetBoolNodeValue:
5271 * @ctxt: a schema validation context
5272 * @ownerDes: owner designation
5273 * @ownerItem: the owner as a schema item
5274 * @node: the node holding the value
5275 *
5276 * Converts a boolean string value into 1 or 0.
5277 *
5278 * Returns 0 or 1.
5279 */
5280static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005281xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
5282 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005283 xmlSchemaTypePtr ownerItem,
5284 xmlNodePtr node)
5285{
5286 xmlChar *value = NULL;
5287 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005288
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005289 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005290 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005291 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005292 * An instance of a datatype that is defined as ·boolean·
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005293 * can have the following legal literals {true, false, 1, 0}.
5294 */
5295 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
5296 res = 1;
5297 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
5298 res = 0;
5299 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
5300 res = 1;
5301 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005302 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005303 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005304 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005305 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005306 ownerItem, node,
5307 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5308 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005309 NULL, NULL, NULL);
5310 }
5311 if (value != NULL)
5312 xmlFree(value);
5313 return (res);
5314}
5315
5316/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005317 * xmlGetBooleanProp:
5318 * @ctxt: a schema validation context
5319 * @node: a subtree containing XML Schema informations
5320 * @name: the attribute name
5321 * @def: the default value
5322 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005323 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00005324 *
5325 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005326 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00005327 */
5328static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005329xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
5330 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005331 xmlSchemaTypePtr ownerItem,
5332 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005333 const char *name, int def)
5334{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005335 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00005336
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005337 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005338 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005339 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005340 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005341 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005342 * An instance of a datatype that is defined as ·boolean·
Daniel Veillardc0826a72004-08-10 14:17:33 +00005343 * can have the following legal literals {true, false, 1, 0}.
5344 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005345 if (xmlStrEqual(val, BAD_CAST "true"))
5346 def = 1;
5347 else if (xmlStrEqual(val, BAD_CAST "false"))
5348 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005349 else if (xmlStrEqual(val, BAD_CAST "1"))
5350 def = 1;
5351 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005352 def = 0;
5353 else {
5354 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005355 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005356 ownerItem,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005357 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005358 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5359 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005360 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005361 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005362}
5363
5364/************************************************************************
5365 * *
5366 * Shema extraction from an Infoset *
5367 * *
5368 ************************************************************************/
5369static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
5370 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005371 xmlNodePtr node,
5372 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005373static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
5374 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005375 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005376 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00005377 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005378static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
5379 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005380 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005381 xmlNodePtr node,
5382 xmlSchemaTypeType parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005383static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
5384 ctxt,
5385 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005386 xmlNodePtr node,
5387 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005388static xmlSchemaAttributeGroupPtr
5389xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005390 xmlSchemaPtr schema, xmlNodePtr node,
5391 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005392static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
5393 xmlSchemaPtr schema,
5394 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00005395static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005396xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5397 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005398
5399/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005400 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005401 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005402 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00005403 * @ownerDes: the designation of the parent element
5404 * @ownerItem: the schema object owner if existent
5405 * @attr: the schema attribute node being validated
5406 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005407 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00005408 *
5409 * Validates a value against the given built-in type.
5410 * This one is intended to be used internally for validation
5411 * of schema attribute values during parsing of the schema.
5412 *
5413 * Returns 0 if the value is valid, a positive error code
5414 * number otherwise and -1 in case of an internal or API error.
5415 */
5416static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005417xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
5418 xmlChar **ownerDes ATTRIBUTE_UNUSED,
5419 xmlSchemaTypePtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005420 xmlAttrPtr attr,
5421 const xmlChar *value,
5422 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005423{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005424
5425 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005426
5427 /*
5428 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
5429 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005430 */
5431 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00005432 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005433 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5434 PERROR_INT("xmlSchemaPValAttrNodeValue",
5435 "the given type is not a built-in type");
5436 return (-1);
5437 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005438 switch (type->builtInType) {
5439 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005440 case XML_SCHEMAS_QNAME:
5441 case XML_SCHEMAS_ANYURI:
5442 case XML_SCHEMAS_TOKEN:
5443 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005444 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
5445 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005446 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005447 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005448 PERROR_INT("xmlSchemaPValAttrNodeValue",
5449 "validation using the given type is not supported");
Daniel Veillard01fa6152004-06-29 17:04:39 +00005450 return (-1);
5451 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005452 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005453 /*
5454 * TODO: Should we use the S4S error codes instead?
5455 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005456 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005457 PERROR_INT("xmlSchemaPValAttrNodeValue",
5458 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005459 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005460 } else if (ret > 0) {
5461 if (VARIETY_LIST(type))
5462 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
5463 else
5464 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
5465 xmlSchemaPSimpleTypeErr(pctxt,
5466 ret, ownerItem, (xmlNodePtr) attr,
5467 type, NULL, value, NULL, NULL, NULL);
5468 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005469 return (ret);
5470}
5471
5472/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005473 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005474 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005475 * @ctxt: a schema parser context
5476 * @ownerDes: the designation of the parent element
5477 * @ownerItem: the schema object owner if existent
5478 * @attr: the schema attribute node being validated
5479 * @type: the built-in type to be validated against
5480 * @value: the resulting value if any
5481 *
5482 * Extracts and validates a value against the given built-in type.
5483 * This one is intended to be used internally for validation
5484 * of schema attribute values during parsing of the schema.
5485 *
5486 * Returns 0 if the value is valid, a positive error code
5487 * number otherwise and -1 in case of an internal or API error.
5488 */
5489static int
5490xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
5491 xmlChar **ownerDes,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005492 xmlSchemaTypePtr ownerItem,
5493 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005494 xmlSchemaTypePtr type,
5495 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005496{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005497 const xmlChar *val;
5498
5499 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005500 return (-1);
5501
Daniel Veillardc0826a72004-08-10 14:17:33 +00005502 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5503 if (value != NULL)
5504 *value = val;
5505
5506 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005507 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005508}
5509
5510/**
5511 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005512 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005513 * @ctxt: a schema parser context
5514 * @node: the element node of the attribute
5515 * @ownerDes: the designation of the parent element
5516 * @ownerItem: the schema object owner if existent
5517 * @ownerElem: the owner element node
5518 * @name: the name of the schema attribute node
5519 * @type: the built-in type to be validated against
5520 * @value: the resulting value if any
5521 *
5522 * Extracts and validates a value against the given built-in type.
5523 * This one is intended to be used internally for validation
5524 * of schema attribute values during parsing of the schema.
5525 *
5526 * Returns 0 if the value is valid, a positive error code
5527 * number otherwise and -1 in case of an internal or API error.
5528 */
5529static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005530xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005531 xmlChar **ownerDes,
5532 xmlSchemaTypePtr ownerItem,
5533 xmlNodePtr ownerElem,
5534 const char *name,
5535 xmlSchemaTypePtr type,
5536 const xmlChar **value)
5537{
5538 xmlAttrPtr attr;
5539
5540 if ((ctxt == NULL) || (type == NULL)) {
5541 if (value != NULL)
5542 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005543 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005544 }
5545 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5546 if (value != NULL)
5547 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005548 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005549 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005550 "Internal error: xmlSchemaPValAttr, the given "
5551 "type '%s' is not a built-in type.\n",
5552 type->name, NULL);
5553 return (-1);
5554 }
5555 attr = xmlSchemaGetPropNode(ownerElem, name);
5556 if (attr == NULL) {
5557 if (value != NULL)
5558 *value = NULL;
5559 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005560 }
5561 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005562 type, value));
5563}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005564
5565static int
5566xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
5567 xmlSchemaPtr schema,
5568 xmlNodePtr node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005569 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005570 const xmlChar *namespaceName)
5571{
5572 if (xmlStrEqual(schema->targetNamespace, namespaceName))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005573 return (1);
5574 if (xmlStrEqual(xmlSchemaNs, namespaceName))
5575 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005576 if (pctxt->localImports != NULL) {
5577 int i;
5578 for (i = 0; i < pctxt->nbLocalImports; i++)
5579 if (xmlStrEqual(namespaceName, pctxt->localImports[i]))
5580 return (1);
5581 }
5582 if (namespaceName == NULL)
5583 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005584 NULL, (xmlSchemaTypePtr) item, node,
5585 "References from this schema to components in no "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005586 "namespace are not valid, since not indicated by an import "
5587 "statement", NULL);
5588 else
5589 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005590 NULL, (xmlSchemaTypePtr) item, node,
5591 "References from this schema to components in the "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005592 "namespace '%s' are not valid, since not indicated by an import "
5593 "statement", namespaceName);
5594 return (0);
5595}
5596
Daniel Veillardc0826a72004-08-10 14:17:33 +00005597/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005598 * xmlSchemaParseAttrDecls:
5599 * @ctxt: a schema validation context
5600 * @schema: the schema being built
5601 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005602 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00005603 *
5604 * parse a XML schema attrDecls declaration corresponding to
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005605 * <!ENTITY % attrDecls
Daniel Veillard4255d502002-04-16 15:50:10 +00005606 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
5607 */
5608static xmlNodePtr
5609xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5610 xmlNodePtr child, xmlSchemaTypePtr type)
5611{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005612 xmlSchemaAttributePtr lastattr = NULL, attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005613
Daniel Veillard4255d502002-04-16 15:50:10 +00005614 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005615 (IS_SCHEMA(child, "attributeGroup"))) {
5616 attr = NULL;
5617 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00005618 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005619 } else if (IS_SCHEMA(child, "attributeGroup")) {
5620 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005621 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005622 }
5623 if (attr != NULL) {
5624 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005625 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
5626 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
5627 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005628 type->attributes = attr;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005629 lastattr = attr;
5630 } else {
5631 lastattr->next = attr;
5632 lastattr = attr;
5633 }
5634 }
5635 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005636 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005637 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005638}
5639
5640/**
5641 * xmlSchemaParseAnnotation:
5642 * @ctxt: a schema validation context
5643 * @schema: the schema being built
5644 * @node: a subtree containing XML Schema informations
5645 *
5646 * parse a XML schema Attrribute declaration
5647 * *WARNING* this interface is highly subject to change
5648 *
William M. Bracke7091952004-05-11 15:09:58 +00005649 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005650 * 1 in case of success.
5651 */
5652static xmlSchemaAnnotPtr
5653xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5654 xmlNodePtr node)
5655{
5656 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005657 xmlNodePtr child = NULL;
5658 xmlAttrPtr attr;
5659 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005660
Daniel Veillardc0826a72004-08-10 14:17:33 +00005661 /*
5662 * INFO: S4S completed.
5663 */
5664 /*
5665 * id = ID
5666 * {any attributes with non-schema namespace . . .}>
5667 * Content: (appinfo | documentation)*
5668 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005669 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5670 return (NULL);
5671 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005672 attr = node->properties;
5673 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005674 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005675 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005676 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005677 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005678
5679 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005680 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5681 NULL, NULL, attr);
5682 }
5683 attr = attr->next;
5684 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005685 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005686 /*
5687 * And now for the children...
5688 */
5689 child = node->children;
5690 while (child != NULL) {
5691 if (IS_SCHEMA(child, "appinfo")) {
5692 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005693 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005694 * source = anyURI
5695 * {any attributes with non-schema namespace . . .}>
5696 * Content: ({any})*
5697 */
5698 attr = child->properties;
5699 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005700 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005701 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005702 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005703 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005704
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005705 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005706 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5707 NULL, NULL, attr);
5708 }
5709 attr = attr->next;
5710 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005711 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
5712 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005713 child = child->next;
5714 } else if (IS_SCHEMA(child, "documentation")) {
5715 /* TODO: make available the content of "documentation". */
5716 /*
5717 * source = anyURI
5718 * {any attributes with non-schema namespace . . .}>
5719 * Content: ({any})*
5720 */
5721 attr = child->properties;
5722 while (attr != NULL) {
5723 if (attr->ns == NULL) {
5724 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005725 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005726 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5727 NULL, NULL, attr);
5728 }
5729 } else {
5730 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
5731 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
5732 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005733
5734 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005735 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5736 NULL, NULL, attr);
5737 }
5738 }
5739 attr = attr->next;
5740 }
5741 /*
5742 * Attribute "xml:lang".
5743 */
5744 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
5745 if (attr != NULL)
5746 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005747 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005748 child = child->next;
5749 } else {
5750 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005751 xmlSchemaPContentErr(ctxt,
5752 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005753 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
5754 barked = 1;
5755 child = child->next;
5756 }
5757 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005758
Daniel Veillard4255d502002-04-16 15:50:10 +00005759 return (ret);
5760}
5761
5762/**
5763 * xmlSchemaParseFacet:
5764 * @ctxt: a schema validation context
5765 * @schema: the schema being built
5766 * @node: a subtree containing XML Schema informations
5767 *
5768 * parse a XML schema Facet declaration
5769 * *WARNING* this interface is highly subject to change
5770 *
5771 * Returns the new type structure or NULL in case of error
5772 */
5773static xmlSchemaFacetPtr
5774xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005775 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005776{
5777 xmlSchemaFacetPtr facet;
5778 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005779 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00005780
5781 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5782 return (NULL);
5783
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005784 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005785 if (facet == NULL) {
5786 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
5787 return (NULL);
5788 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005789 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005790 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00005791 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005792 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
5793 "Facet %s has no value\n", node->name, NULL);
5794 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00005795 return (NULL);
5796 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005797 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005798 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005799 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005800 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005801 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005802 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005803 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005804 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005805 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005806 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005807 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005808 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005809 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005810 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005811 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005812 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005813 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005814 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005815 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005816 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005817 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005818 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
5819 } else if (IS_SCHEMA(node, "minLength")) {
5820 facet->type = XML_SCHEMA_FACET_MINLENGTH;
5821 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005822 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
5823 "Unknown facet type %s\n", node->name, NULL);
5824 xmlSchemaFreeFacet(facet);
5825 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005826 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005827 xmlSchemaPValAttrID(ctxt, NULL,
5828 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005829 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005830 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
5831 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
5832 const xmlChar *fixed;
5833
5834 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
5835 if (fixed != NULL) {
5836 if (xmlStrEqual(fixed, BAD_CAST "true"))
5837 facet->fixed = 1;
5838 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005839 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005840 child = node->children;
5841
5842 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005843 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5844 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005845 }
5846 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005847 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
5848 "Facet %s has unexpected child content\n",
5849 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005850 }
5851 return (facet);
5852}
5853
5854/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005855 * xmlSchemaParseWildcardNs:
5856 * @ctxt: a schema parser context
5857 * @wildc: the wildcard, already created
5858 * @node: a subtree containing XML Schema informations
5859 *
5860 * Parses the attribute "processContents" and "namespace"
5861 * of a xsd:anyAttribute and xsd:any.
5862 * *WARNING* this interface is highly subject to change
5863 *
5864 * Returns 0 if everything goes fine, a positive error code
5865 * if something is not valid and -1 if an internal error occurs.
5866 */
5867static int
5868xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
5869 xmlSchemaPtr schema,
5870 xmlSchemaWildcardPtr wildc,
5871 xmlNodePtr node)
5872{
5873 const xmlChar *pc, *ns, *dictnsItem;
5874 int ret = 0;
5875 xmlChar *nsItem;
5876 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
5877 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005878
Daniel Veillardc0826a72004-08-10 14:17:33 +00005879 pc = xmlSchemaGetProp(ctxt, node, "processContents");
5880 if ((pc == NULL)
5881 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
5882 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5883 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
5884 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
5885 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
5886 wildc->processContents = XML_SCHEMAS_ANY_LAX;
5887 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005888 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005889 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005890 NULL, node,
5891 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005892 NULL, NULL, NULL);
5893 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005894 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005895 }
5896 /*
5897 * Build the namespace constraints.
5898 */
5899 attr = xmlSchemaGetPropNode(node, "namespace");
5900 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00005901 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00005902 wildc->any = 1;
5903 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
5904 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005905 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005906 return (-1);
5907 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005908 wildc->negNsSet->value = schema->targetNamespace;
5909 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005910 const xmlChar *end, *cur;
5911
5912 cur = ns;
5913 do {
5914 while (IS_BLANK_CH(*cur))
5915 cur++;
5916 end = cur;
5917 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5918 end++;
5919 if (end == cur)
5920 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005921 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005922 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
5923 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005924 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005925 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005926 NULL, (xmlNodePtr) attr,
5927 NULL,
5928 "((##any | ##other) | List of (xs:anyURI | "
5929 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005930 nsItem, NULL, NULL, NULL);
5931 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
5932 } else {
5933 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
5934 dictnsItem = schema->targetNamespace;
5935 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
5936 dictnsItem = NULL;
5937 } else {
5938 /*
5939 * Validate the item (anyURI).
5940 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005941 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005942 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
5943 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
5944 }
5945 /*
5946 * Avoid dublicate namespaces.
5947 */
5948 tmp = wildc->nsSet;
5949 while (tmp != NULL) {
5950 if (dictnsItem == tmp->value)
5951 break;
5952 tmp = tmp->next;
5953 }
5954 if (tmp == NULL) {
5955 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
5956 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005957 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005958 return (-1);
5959 }
5960 tmp->value = dictnsItem;
5961 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005962 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00005963 wildc->nsSet = tmp;
5964 else
5965 lastNs->next = tmp;
5966 lastNs = tmp;
5967 }
5968
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005969 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005970 xmlFree(nsItem);
5971 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005972 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005973 }
5974 return (ret);
5975}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005976
5977static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005978xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
5979 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005980 xmlNodePtr node,
5981 int minOccurs,
5982 int maxOccurs) {
5983
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005984 if ((maxOccurs == 0) && ( minOccurs == 0))
5985 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005986 if (maxOccurs != UNBOUNDED) {
5987 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005988 * TODO: Maybe we should better not create the particle,
5989 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005990 * content model.
5991 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005992 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005993 * 3.9.6 Schema Component Constraint: Particle Correct
5994 *
5995 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005996 if (maxOccurs < 1) {
5997 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005998 * 2.2 {max occurs} must be greater than or equal to 1.
5999 */
6000 xmlSchemaPCustomAttrErr(ctxt,
6001 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006002 NULL, NULL,
6003 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006004 "The value must be greater than or equal to 1");
6005 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6006 } else if (minOccurs > maxOccurs) {
6007 /*
6008 * 2.1 {min occurs} must not be greater than {max occurs}.
6009 */
6010 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006011 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006012 NULL, NULL,
6013 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006014 "The value must not be greater than the value of 'maxOccurs'");
6015 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6016 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006017 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006018 return (0);
6019}
6020
Daniel Veillardc0826a72004-08-10 14:17:33 +00006021/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006022 * xmlSchemaParseAny:
6023 * @ctxt: a schema validation context
6024 * @schema: the schema being built
6025 * @node: a subtree containing XML Schema informations
6026 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006027 * Parsea a XML schema <any> element. A particle and wildcard
6028 * will be created (except if minOccurs==maxOccurs==0, in this case
6029 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006030 * *WARNING* this interface is highly subject to change
6031 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006032 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006033 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006034static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006035xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6036 xmlNodePtr node)
6037{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006038 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006039 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006040 xmlSchemaWildcardPtr wild;
6041 int min, max;
6042 xmlAttrPtr attr;
6043 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006044
6045 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6046 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006047 /*
6048 * Check for illegal attributes.
6049 */
6050 attr = node->properties;
6051 while (attr != NULL) {
6052 if (attr->ns == NULL) {
6053 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6054 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6055 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6056 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6057 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006058 xmlSchemaPIllegalAttrErr(ctxt,
6059 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6060 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006061 }
6062 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006063 xmlSchemaPIllegalAttrErr(ctxt,
6064 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6065 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006066 }
6067 attr = attr->next;
6068 }
6069 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
6070 /*
6071 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006072 */
6073 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6074 "(xs:nonNegativeInteger | unbounded)");
6075 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6076 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006077 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6078 /*
6079 * Create & parse the wildcard.
6080 */
6081 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6082 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006083 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006084 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006085 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006086 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006087 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006088 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006089 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006090 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006091 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006092 }
6093 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006094 xmlSchemaPContentErr(ctxt,
6095 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006096 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006097 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006098 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006099 /*
6100 * No component if minOccurs==maxOccurs==0.
6101 */
6102 if ((min == 0) && (max == 0)) {
6103 /* Don't free the wildcard, since it's already on the list. */
6104 return (NULL);
6105 }
6106 /*
6107 * Create the particle.
6108 */
6109 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6110 if (particle == NULL)
6111 return (NULL);
6112 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006113 wild->minOccurs = min;
6114 wild->maxOccurs = max;
6115 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006116
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006117 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006118}
6119
6120/**
6121 * xmlSchemaParseNotation:
6122 * @ctxt: a schema validation context
6123 * @schema: the schema being built
6124 * @node: a subtree containing XML Schema informations
6125 *
6126 * parse a XML schema Notation declaration
6127 *
6128 * Returns the new structure or NULL in case of error
6129 */
6130static xmlSchemaNotationPtr
6131xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006132 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006133{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006134 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006135 xmlSchemaNotationPtr ret;
6136 xmlNodePtr child = NULL;
6137
6138 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6139 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006140 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006141 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006142 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6143 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006144 return (NULL);
6145 }
6146 ret = xmlSchemaAddNotation(ctxt, schema, name);
6147 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006148 return (NULL);
6149 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006150 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006151
6152 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6153 node, BAD_CAST "id");
6154
6155 if (IS_SCHEMA(child, "annotation")) {
6156 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6157 child = child->next;
6158 }
6159
Daniel Veillard4255d502002-04-16 15:50:10 +00006160 child = node->children;
6161 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006162 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6163 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006164 }
6165 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006166 xmlSchemaPContentErr(ctxt,
6167 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006168 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006169 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006170 }
6171
6172 return (ret);
6173}
6174
6175/**
6176 * xmlSchemaParseAnyAttribute:
6177 * @ctxt: a schema validation context
6178 * @schema: the schema being built
6179 * @node: a subtree containing XML Schema informations
6180 *
6181 * parse a XML schema AnyAttrribute declaration
6182 * *WARNING* this interface is highly subject to change
6183 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006184 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006185 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006186static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006187xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6188 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006189{
Daniel Veillard3646d642004-06-02 19:19:14 +00006190 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006191 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006192 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006193
6194 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6195 return (NULL);
6196
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006197 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6198 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006199 if (ret == NULL) {
6200 return (NULL);
6201 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006202 /*
6203 * Check for illegal attributes.
6204 */
6205 attr = node->properties;
6206 while (attr != NULL) {
6207 if (attr->ns == NULL) {
6208 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6209 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6210 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006211 xmlSchemaPIllegalAttrErr(ctxt,
6212 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6213 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006214 }
6215 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006216 xmlSchemaPIllegalAttrErr(ctxt,
6217 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6218 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006219 }
6220 attr = attr->next;
6221 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006222 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6223 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006224 /*
6225 * Parse the namespace list.
6226 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006227 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006228 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006229 /*
6230 * And now for the children...
6231 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006232 child = node->children;
6233 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006234 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6235 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006236 }
6237 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006238 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006239 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006240 NULL, NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006241 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006242 }
6243
6244 return (ret);
6245}
6246
6247
6248/**
6249 * xmlSchemaParseAttribute:
6250 * @ctxt: a schema validation context
6251 * @schema: the schema being built
6252 * @node: a subtree containing XML Schema informations
6253 *
6254 * parse a XML schema Attrribute declaration
6255 * *WARNING* this interface is highly subject to change
6256 *
William M. Bracke7091952004-05-11 15:09:58 +00006257 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006258 */
6259static xmlSchemaAttributePtr
6260xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00006261 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006262{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006263 const xmlChar *name, *attrValue;
6264 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00006265 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006266 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006267 xmlAttrPtr attr, nameAttr;
6268 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00006269
6270 /*
6271 * Note that the w3c spec assumes the schema to be validated with schema
6272 * for schemas beforehand.
6273 *
6274 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00006275 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006276
6277 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6278 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006279 attr = xmlSchemaGetPropNode(node, "ref");
6280 nameAttr = xmlSchemaGetPropNode(node, "name");
6281
6282 if ((attr == NULL) && (nameAttr == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006283 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006284 * 3.2.3 : 3.1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006285 * One of ref or name must be present, but not both
Daniel Veillardc0826a72004-08-10 14:17:33 +00006286 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006287 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6288 NULL, node, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006289 "One of the attributes 'ref' or 'name' must be present");
6290 return (NULL);
6291 }
6292 if ((topLevel) || (attr == NULL)) {
6293 if (nameAttr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006294 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
6295 NULL, node, "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006296 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006297 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006298 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006299 isRef = 1;
6300
Daniel Veillardc0826a72004-08-10 14:17:33 +00006301 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006302 char buf[50];
6303 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006304
6305 /*
6306 * Parse as attribute reference.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006307 */
6308 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
6309 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
6310 &ref) != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006311 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006312 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006313 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006314 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006315 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006316 if (ret == NULL) {
6317 if (repName != NULL)
6318 xmlFree(repName);
6319 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006320 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006321 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
6322 ret->node = node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006323 ret->refNs = refNs;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006324 ret->ref = ref;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006325 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) ret,
6326 refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006327 /*
6328 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
6329 */
6330 if (nameAttr != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006331 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6332 &repName, (xmlSchemaTypePtr) ret, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006333 "ref", "name");
6334 /*
6335 * Check for illegal attributes.
6336 */
6337 attr = node->properties;
6338 while (attr != NULL) {
6339 if (attr->ns == NULL) {
6340 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
6341 xmlStrEqual(attr->name, BAD_CAST "form")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006342 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006343 * 3.2.3 : 3.2
6344 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006345 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006346 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006347 xmlSchemaPIllegalAttrErr(ctxt,
6348 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006349 (xmlSchemaTypePtr) ret, attr);
6350 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
6351 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
6352 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006353 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6354 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006355 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006356 xmlSchemaPIllegalAttrErr(ctxt,
6357 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6358 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006359 }
6360 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006361 xmlSchemaPIllegalAttrErr(ctxt,
6362 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6363 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006364 }
6365 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006366 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006367 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006368 const xmlChar *ns = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006369
Daniel Veillardc0826a72004-08-10 14:17:33 +00006370 /*
6371 * Parse as attribute declaration.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006372 */
6373 if (xmlSchemaPValAttrNode(ctxt,
6374 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006375 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6376 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006377 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006378 /*
6379 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
6380 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006381 /*
6382 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
6383 * TODO: Move this to the component layer.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006384 */
6385 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006386 xmlSchemaPSimpleTypeErr(ctxt,
6387 XML_SCHEMAP_NO_XMLNS,
6388 NULL, (xmlNodePtr) nameAttr,
6389 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
6390 "The value of type 'xs:NCName' must not match 'xmlns'",
6391 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006392 if (repName != NULL)
6393 xmlFree(repName);
6394 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006395 }
6396 /*
6397 * Evaluate the target namespace
6398 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006399 if (topLevel) {
6400 ns = schema->targetNamespace;
6401 } else {
6402 attr = xmlSchemaGetPropNode(node, "form");
6403 if (attr != NULL) {
6404 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6405 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
6406 ns = schema->targetNamespace;
6407 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006408 xmlSchemaPSimpleTypeErr(ctxt,
6409 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6410 NULL, (xmlNodePtr) attr,
6411 NULL, "(qualified | unqualified)",
6412 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006413 }
6414 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006415 ns = schema->targetNamespace;
6416 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006417 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006418 if (ret == NULL) {
6419 if (repName != NULL)
6420 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00006421 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006422 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006423 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006424 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006425 if (topLevel)
6426 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006427 /*
6428 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
6429 * TODO: Move this to the component layer.
6430 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006431 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006432 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006433 XML_SCHEMAP_NO_XSI,
6434 &repName, (xmlSchemaTypePtr) ret, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006435 "The target namespace must not match '%s'",
6436 xmlSchemaInstanceNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006437 }
6438 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006439 * Check for illegal attributes.
6440 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006441 attr = node->properties;
6442 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006443 if (attr->ns == NULL) {
6444 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6445 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6446 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006447 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6448 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006449 if ((topLevel) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006450 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
6451 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006452 xmlSchemaPIllegalAttrErr(ctxt,
6453 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6454 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006455 }
6456 }
6457 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006458 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6459 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006460 }
6461 attr = attr->next;
6462 }
6463 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006464 node, "type", &ret->typeNs, &ret->typeName);
6465 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006466 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6467 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00006468 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006469 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00006470 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006471 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
6472 if (ret->defValue != NULL)
6473 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006474 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006475 * Attribute "default".
6476 */
6477 attr = xmlSchemaGetPropNode(node, "default");
6478 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006479 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006480 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006481 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006482 */
6483 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
6484 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
6485 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
6486 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006487 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6488 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006489 if (topLevel == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006490 /*
6491 * Attribute "use".
Daniel Veillardc0826a72004-08-10 14:17:33 +00006492 */
6493 attr = xmlSchemaGetPropNode(node, "use");
6494 if (attr != NULL) {
6495 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6496 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
6497 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6498 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
6499 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
6500 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
6501 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
6502 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006503 xmlSchemaPSimpleTypeErr(ctxt,
6504 XML_SCHEMAP_INVALID_ATTR_USE,
6505 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6506 NULL, "(optional | prohibited | required)",
6507 attrValue, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006508 } else
6509 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006510 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006511 * 3.2.3 : 2
6512 * If default and use are both present, use must have
6513 * the actual value optional.
6514 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006515 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6516 (ret->defValue != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006517 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006518 xmlSchemaPSimpleTypeErr(ctxt,
6519 XML_SCHEMAP_SRC_ATTRIBUTE_2,
6520 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6521 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006522 "The value must be 'optional' if the attribute "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006523 "'default' is present as well", NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006524 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006525 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006526 /*
6527 * And now for the children...
6528 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006529 child = node->children;
6530 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006531 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6532 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006533 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006534 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006535 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006536 if (IS_SCHEMA(child, "simpleType"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006537 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006538 * 3.2.3 : 3.2
6539 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006540 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006541 */
6542 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
6543 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6544 "(annotation?)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006545 else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006546 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6547 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006548 "(annotation?)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006549 }
6550 } else {
6551 if (IS_SCHEMA(child, "simpleType")) {
6552 if (ret->typeName != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006553 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006554 * 3.2.3 : 4
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006555 * type and <simpleType> must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006556 */
6557 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
6558 &repName, (xmlSchemaTypePtr) ret, node, child,
6559 "The attribute 'type' and the <simpleType> child "
6560 "are mutually exclusive", NULL);
6561 } else
6562 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6563 child = child->next;
6564 }
6565 if (child != NULL)
6566 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6567 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6568 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006569 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006570 /*
6571 * Cleanup.
6572 */
6573 if (repName != NULL)
6574 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00006575 return (ret);
6576}
6577
6578/**
6579 * xmlSchemaParseAttributeGroup:
6580 * @ctxt: a schema validation context
6581 * @schema: the schema being built
6582 * @node: a subtree containing XML Schema informations
6583 *
6584 * parse a XML schema Attribute Group declaration
6585 * *WARNING* this interface is highly subject to change
6586 *
6587 * Returns the attribute group or NULL in case of error.
6588 */
6589static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006590xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00006591 xmlSchemaPtr schema, xmlNodePtr node,
6592 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006593{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006594 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006595 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006596 xmlNodePtr child = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006597 const xmlChar *oldcontainer;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006598 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006599
6600 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6601 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006602
6603 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006604 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006605 if ((topLevel) || (attr == NULL)) {
6606 /*
6607 * Parse as an attribute group definition.
6608 * Note that those are allowed at top level only.
6609 */
6610 if (nameAttr == NULL) {
6611 xmlSchemaPMissingAttrErr(ctxt,
6612 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006613 NULL, node, "name", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006614 return (NULL);
6615 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006616 /* REDUNDANT: name = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006617 * (xmlNodePtr) nameAttr);
6618 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006619 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006620 * The name is crucial, exit if invalid.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006621 */
6622 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006623 NULL, NULL, nameAttr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006624 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6625 return (NULL);
6626 }
6627 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6628 if (ret == NULL)
6629 return (NULL);
6630 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6631 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
6632 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006633 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006634 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006635 char buf[50];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006636 const xmlChar *refNs = NULL, *ref = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006637
6638 /*
6639 * Parse as an attribute group definition reference.
6640 */
6641 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006642 xmlSchemaPMissingAttrErr(ctxt,
6643 XML_SCHEMAP_S4S_ATTR_MISSING,
6644 NULL, node, "ref", NULL);
6645 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006646 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006647 NULL, NULL, attr, &refNs,&ref);
6648
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006649 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006650 name = (const xmlChar *) buf;
6651 if (name == NULL) {
6652 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
6653 "attribute group definition reference", node);
6654 return (NULL);
6655 }
6656 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6657 if (ret == NULL)
6658 return (NULL);
6659 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6660 ret->ref = ref;
6661 ret->refNs = refNs;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006662 ret->node = node;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006663 xmlSchemaCheckReference(ctxt, schema, node,
6664 (xmlSchemaBasicItemPtr) ret, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006665 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006666 /*
6667 * Check for illegal attributes.
6668 */
6669 attr = node->properties;
6670 while (attr != NULL) {
6671 if (attr->ns == NULL) {
6672 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
6673 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006674 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006675 {
6676 xmlSchemaPIllegalAttrErr(ctxt,
6677 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6678 NULL, NULL, attr);
6679 }
6680 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6681 xmlSchemaPIllegalAttrErr(ctxt,
6682 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6683 NULL, NULL, attr);
6684 }
6685 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006686 }
6687 /* TODO: Validate "id" ? */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006688 /*
6689 * And now for the children...
6690 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006691 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00006692 ctxt->container = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006693 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006694 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006695 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6696 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006697 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006698 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006699 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006700 if (IS_SCHEMA(child, "anyAttribute")) {
6701 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
6702 child = child->next;
6703 }
6704 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006705 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006706 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006707 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6708 NULL, NULL, node, child, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006709 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006710 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006711 ctxt->container = oldcontainer;
6712 return (ret);
6713}
6714
6715/**
William M. Brack2f2a6632004-08-20 23:09:47 +00006716 * xmlSchemaPValAttrFormDefault:
6717 * @value: the value
6718 * @flags: the flags to be modified
6719 * @flagQualified: the specific flag for "qualified"
6720 *
6721 * Returns 0 if the value is valid, 1 otherwise.
6722 */
6723static int
6724xmlSchemaPValAttrFormDefault(const xmlChar *value,
6725 int *flags,
6726 int flagQualified)
6727{
6728 if (xmlStrEqual(value, BAD_CAST "qualified")) {
6729 if ((*flags & flagQualified) == 0)
6730 *flags |= flagQualified;
6731 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006732 return (1);
6733
William M. Brack2f2a6632004-08-20 23:09:47 +00006734 return (0);
6735}
6736
6737/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006738 * xmlSchemaPValAttrBlockFinal:
6739 * @value: the value
6740 * @flags: the flags to be modified
6741 * @flagAll: the specific flag for "#all"
6742 * @flagExtension: the specific flag for "extension"
6743 * @flagRestriction: the specific flag for "restriction"
6744 * @flagSubstitution: the specific flag for "substitution"
6745 * @flagList: the specific flag for "list"
6746 * @flagUnion: the specific flag for "union"
6747 *
6748 * Validates the value of the attribute "final" and "block". The value
6749 * is converted into the specified flag values and returned in @flags.
6750 *
6751 * Returns 0 if the value is valid, 1 otherwise.
6752 */
6753
6754static int
6755xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006756 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006757 int flagAll,
6758 int flagExtension,
6759 int flagRestriction,
6760 int flagSubstitution,
6761 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006762 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006763{
6764 int ret = 0;
6765
6766 /*
6767 * TODO: This does not check for dublicate entries.
6768 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006769 if ((flags == NULL) || (value == NULL))
6770 return (-1);
6771 if (value[0] == 0)
6772 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006773 if (xmlStrEqual(value, BAD_CAST "#all")) {
6774 if (flagAll != -1)
6775 *flags |= flagAll;
6776 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006777 if (flagExtension != -1)
6778 *flags |= flagExtension;
6779 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006780 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006781 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006782 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006783 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006784 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006785 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006786 *flags |= flagUnion;
6787 }
6788 } else {
6789 const xmlChar *end, *cur = value;
6790 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006791
Daniel Veillardc0826a72004-08-10 14:17:33 +00006792 do {
6793 while (IS_BLANK_CH(*cur))
6794 cur++;
6795 end = cur;
6796 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6797 end++;
6798 if (end == cur)
6799 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006800 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006801 if (xmlStrEqual(item, BAD_CAST "extension")) {
6802 if (flagExtension != -1) {
6803 if ((*flags & flagExtension) == 0)
6804 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006805 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006806 ret = 1;
6807 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
6808 if (flagRestriction != -1) {
6809 if ((*flags & flagRestriction) == 0)
6810 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006811 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006812 ret = 1;
6813 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
6814 if (flagSubstitution != -1) {
6815 if ((*flags & flagSubstitution) == 0)
6816 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006817 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006818 ret = 1;
6819 } else if (xmlStrEqual(item, BAD_CAST "list")) {
6820 if (flagList != -1) {
6821 if ((*flags & flagList) == 0)
6822 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006823 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006824 ret = 1;
6825 } else if (xmlStrEqual(item, BAD_CAST "union")) {
6826 if (flagUnion != -1) {
6827 if ((*flags & flagUnion) == 0)
6828 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006829 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006830 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006831 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006832 ret = 1;
6833 if (item != NULL)
6834 xmlFree(item);
6835 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006836 } while ((ret == 0) && (*cur != 0));
6837 }
6838
Daniel Veillardc0826a72004-08-10 14:17:33 +00006839 return (ret);
6840}
6841
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006842static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006843xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006844 xmlSchemaIDCPtr idc,
6845 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006846 xmlAttrPtr attr,
6847 int isField)
6848{
6849 xmlNodePtr node;
6850
6851 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006852 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006853 * Schema Component Constraint: Selector Value OK
6854 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006855 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006856 * in [XPath].
6857 */
6858 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006859 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006860 XML_SCHEMAP_INTERNAL,
6861 "Internal error: xmlSchemaCheckCSelectorXPath, "
6862 "the selector is not specified.\n", NULL, NULL);
6863 return (-1);
6864 }
6865 if (attr == NULL)
6866 node = idc->node;
6867 else
6868 node = (xmlNodePtr) attr;
6869 if (selector->xpath == NULL) {
6870 xmlSchemaPCustomErr(ctxt,
6871 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006872 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6873 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006874 "The XPath expression of the selector is not valid", NULL);
6875 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6876 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006877 const xmlChar **nsArray = NULL;
6878 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006879 /*
6880 * Compile the XPath expression.
6881 */
6882 /*
6883 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006884 * TODO: Call xmlPatterncompile with different options for selector/
6885 * field.
6886 */
6887 nsList = xmlGetNsList(attr->doc, attr->parent);
6888 /*
6889 * Build an array of prefixes and namespaces.
6890 */
6891 if (nsList != NULL) {
6892 int i, count = 0;
6893 xmlNsPtr ns;
6894
6895 for (i = 0; nsList[i] != NULL; i++)
6896 count++;
6897
6898 nsArray = (const xmlChar **) xmlMalloc(
6899 (count * 2 + 1) * sizeof(const xmlChar *));
6900 if (nsArray == NULL) {
6901 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
6902 NULL);
6903 return (-1);
6904 }
6905 for (i = 0; i < count; i++) {
6906 ns = nsList[i];
6907 nsArray[2 * i] = nsList[i]->href;
6908 nsArray[2 * i + 1] = nsList[i]->prefix;
6909 }
6910 nsArray[count * 2] = NULL;
6911 xmlFree(nsList);
6912 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006913 /*
6914 * TODO: Differentiate between "selector" and "field".
6915 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006916 if (isField)
6917 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00006918 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006919 else
6920 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00006921 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006922 if (nsArray != NULL)
6923 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006924
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006925 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006926 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006927 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006928 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6929 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006930 "The XPath expression '%s' could not be "
6931 "compiled", selector->xpath);
6932 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006933 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006934 }
6935 return (0);
6936}
6937
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006938#define ADD_ANNOTATION(annot) \
6939 xmlSchemaAnnotPtr cur = item->annot; \
6940 if (item->annot == NULL) { \
6941 item->annot = annot; \
6942 return (annot); \
6943 } \
6944 cur = item->annot; \
6945 if (cur->next != NULL) { \
6946 cur = cur->next; \
6947 } \
6948 cur->next = annot;
6949
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006950/**
6951 * xmlSchemaAssignAnnotation:
6952 * @item: the schema component
6953 * @annot: the annotation
6954 *
6955 * Adds the annotation to the given schema component.
6956 *
6957 * Returns the given annotaion.
6958 */
6959static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006960xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
6961 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006962{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006963 if ((annItem == NULL) || (annot == NULL))
6964 return (NULL);
6965 switch (annItem->type) {
6966 case XML_SCHEMA_TYPE_ELEMENT: {
6967 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
6968 ADD_ANNOTATION(annot)
6969 }
6970 break;
6971 case XML_SCHEMA_TYPE_ATTRIBUTE: {
6972 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
6973 ADD_ANNOTATION(annot)
6974 }
6975 break;
6976 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
6977 case XML_SCHEMA_TYPE_ANY: {
6978 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
6979 ADD_ANNOTATION(annot)
6980 }
6981 break;
6982 case XML_SCHEMA_TYPE_PARTICLE:
6983 case XML_SCHEMA_TYPE_IDC_KEY:
6984 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006985 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006986 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
6987 ADD_ANNOTATION(annot)
6988 }
6989 break;
6990 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
6991 xmlSchemaAttributeGroupPtr item =
6992 (xmlSchemaAttributeGroupPtr) annItem;
6993 ADD_ANNOTATION(annot)
6994 }
6995 break;
6996 case XML_SCHEMA_TYPE_NOTATION: {
6997 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
6998 ADD_ANNOTATION(annot)
6999 }
7000 break;
7001 case XML_SCHEMA_FACET_MININCLUSIVE:
7002 case XML_SCHEMA_FACET_MINEXCLUSIVE:
7003 case XML_SCHEMA_FACET_MAXINCLUSIVE:
7004 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
7005 case XML_SCHEMA_FACET_TOTALDIGITS:
7006 case XML_SCHEMA_FACET_FRACTIONDIGITS:
7007 case XML_SCHEMA_FACET_PATTERN:
7008 case XML_SCHEMA_FACET_ENUMERATION:
7009 case XML_SCHEMA_FACET_WHITESPACE:
7010 case XML_SCHEMA_FACET_LENGTH:
7011 case XML_SCHEMA_FACET_MAXLENGTH:
7012 case XML_SCHEMA_FACET_MINLENGTH: {
7013 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
7014 ADD_ANNOTATION(annot)
7015 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007016 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007017 case XML_SCHEMA_TYPE_SIMPLE:
7018 case XML_SCHEMA_TYPE_COMPLEX: {
7019 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
7020 ADD_ANNOTATION(annot)
7021 }
7022 break;
7023 case XML_SCHEMA_TYPE_GROUP: {
7024 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
7025 ADD_ANNOTATION(annot)
7026 }
7027 break;
7028 case XML_SCHEMA_TYPE_SEQUENCE:
7029 case XML_SCHEMA_TYPE_CHOICE:
7030 case XML_SCHEMA_TYPE_ALL: {
7031 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
7032 ADD_ANNOTATION(annot)
7033 }
7034 break;
7035 default:
7036 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007037 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007038 NULL, NULL, NULL,
7039 "Internal error: xmlSchemaAddAnnotation, "
7040 "The item is not a annotated schema component", NULL);
7041 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007042 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007043 return (annot);
7044}
7045
7046/**
7047 * xmlSchemaParseIDCSelectorAndField:
7048 * @ctxt: a schema validation context
7049 * @schema: the schema being built
7050 * @node: a subtree containing XML Schema informations
7051 *
7052 * Parses a XML Schema identity-contraint definition's
7053 * <selector> and <field> elements.
7054 *
7055 * Returns the parsed identity-constraint definition.
7056 */
7057static xmlSchemaIDCSelectPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007058xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007059 xmlSchemaPtr schema,
7060 xmlSchemaIDCPtr idc,
7061 xmlNodePtr node,
7062 int isField)
7063{
7064 xmlSchemaIDCSelectPtr item;
7065 xmlNodePtr child = NULL;
7066 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007067
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007068 /*
7069 * Check for illegal attributes.
7070 */
7071 attr = node->properties;
7072 while (attr != NULL) {
7073 if (attr->ns == NULL) {
7074 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7075 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007076 xmlSchemaPIllegalAttrErr(ctxt,
7077 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7078 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007079 }
7080 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007081 xmlSchemaPIllegalAttrErr(ctxt,
7082 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7083 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007084 }
7085 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007086 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007087 /*
7088 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007089 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007090 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
7091 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007092 xmlSchemaPErrMemory(ctxt,
7093 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007094 NULL);
7095 return (NULL);
7096 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007097 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007098 /*
7099 * Attribute "xpath" (mandatory).
7100 */
7101 attr = xmlSchemaGetPropNode(node, "xpath");
7102 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007103 xmlSchemaPMissingAttrErr(ctxt,
7104 XML_SCHEMAP_S4S_ATTR_MISSING,
7105 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007106 "name", NULL);
7107 } else {
7108 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7109 /*
7110 * URGENT TODO: "field"s have an other syntax than "selector"s.
7111 */
7112
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007113 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
7114 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007115 xmlSchemaPErr(ctxt,
7116 (xmlNodePtr) attr,
7117 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007118 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007119 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007120 NULL, NULL);
7121 }
7122
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007123 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007124 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007125 /*
7126 * And now for the children...
7127 */
7128 child = node->children;
7129 if (IS_SCHEMA(child, "annotation")) {
7130 /*
7131 * Add the annotation to the parent IDC.
7132 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007133 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007134 xmlSchemaParseAnnotation(ctxt, schema, child));
7135 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007136 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007137 if (child != NULL) {
7138 xmlSchemaPContentErr(ctxt,
7139 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007140 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007141 NULL, "(annotation?)");
7142 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007143
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007144 return (item);
7145}
7146
7147/**
7148 * xmlSchemaParseIDC:
7149 * @ctxt: a schema validation context
7150 * @schema: the schema being built
7151 * @node: a subtree containing XML Schema informations
7152 *
7153 * Parses a XML Schema identity-contraint definition.
7154 *
7155 * Returns the parsed identity-constraint definition.
7156 */
7157static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007158xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007159 xmlSchemaPtr schema,
7160 xmlNodePtr node,
7161 xmlSchemaTypeType idcCategory,
7162 const xmlChar *targetNamespace)
7163{
7164 xmlSchemaIDCPtr item = NULL;
7165 xmlNodePtr child = NULL;
7166 xmlAttrPtr attr;
7167 const xmlChar *name = NULL;
7168 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
7169 int resAdd;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007170
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007171 /*
7172 * Check for illegal attributes.
7173 */
7174 attr = node->properties;
7175 while (attr != NULL) {
7176 if (attr->ns == NULL) {
7177 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7178 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7179 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
7180 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007181 xmlSchemaPIllegalAttrErr(ctxt,
7182 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7183 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007184 }
7185 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007186 xmlSchemaPIllegalAttrErr(ctxt,
7187 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7188 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007189 }
7190 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007191 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007192 /*
7193 * Attribute "name" (mandatory).
7194 */
7195 attr = xmlSchemaGetPropNode(node, "name");
7196 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007197 xmlSchemaPMissingAttrErr(ctxt,
7198 XML_SCHEMAP_S4S_ATTR_MISSING,
7199 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007200 "name", NULL);
7201 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007202 } else if (xmlSchemaPValAttrNode(ctxt,
7203 NULL, NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007204 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7205 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007206 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007207 /*
7208 * Create the component.
7209 */
7210 if (schema->idcDef == NULL)
7211 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007212 if (schema->idcDef == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007213 return (NULL);
7214
7215 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
7216 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007217 xmlSchemaPErrMemory(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007218 "allocating an identity-constraint definition", NULL);
7219 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007220 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007221 /*
7222 * Add the IDC to the list of IDCs on the schema component.
7223 */
7224 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007225 if (resAdd != 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007226 xmlSchemaPCustomErrExt(ctxt,
7227 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007228 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007229 "An identity-constraint definition with the name '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007230 "and targetNamespace '%s' does already exist",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007231 name, targetNamespace, NULL);
7232 xmlFree(item);
7233 return (NULL);
7234 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007235 memset(item, 0, sizeof(xmlSchemaIDC));
7236 item->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007237 item->type = idcCategory;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007238 item->node = node;
7239 /*
7240 * The target namespace of the parent element declaration.
7241 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007242 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007243 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
7244 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007245 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
7246 /*
7247 * Attribute "refer" (mandatory).
7248 */
7249 attr = xmlSchemaGetPropNode(node, "refer");
7250 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007251 xmlSchemaPMissingAttrErr(ctxt,
7252 XML_SCHEMAP_S4S_ATTR_MISSING,
7253 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007254 "refer", NULL);
7255 } else {
7256 /*
7257 * Create a reference item.
7258 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007259 item->ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007260 NULL, NULL);
7261 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007262 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007263 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007264 NULL, NULL, attr,
7265 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007266 &(item->ref->name));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007267 xmlSchemaCheckReference(ctxt, schema, node,
7268 (xmlSchemaBasicItemPtr) item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007269 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007270 }
7271 }
7272 /*
7273 * And now for the children...
7274 */
7275 child = node->children;
7276 if (IS_SCHEMA(child, "annotation")) {
7277 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7278 child = child->next;
7279 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007280 if (child == NULL) {
7281 xmlSchemaPContentErr(ctxt,
7282 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007283 NULL, NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007284 "A child element is missing",
7285 "(annotation?, (selector, field+))");
7286 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007287 /*
7288 * Child element <selector>.
7289 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007290 if (IS_SCHEMA(child, "selector")) {
7291 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007292 item, child, 0);
7293 child = child->next;
7294 /*
7295 * Child elements <field>.
7296 */
7297 if (IS_SCHEMA(child, "field")) {
7298 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007299 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007300 item, child, 1);
7301 if (field != NULL) {
7302 field->index = item->nbFields;
7303 item->nbFields++;
7304 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007305 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007306 else
7307 item->fields = field;
7308 lastField = field;
7309 }
7310 child = child->next;
7311 } while (IS_SCHEMA(child, "field"));
7312 } else {
7313 xmlSchemaPContentErr(ctxt,
7314 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007315 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007316 NULL, "(annotation?, (selector, field+))");
7317 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007318 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007319 if (child != NULL) {
7320 xmlSchemaPContentErr(ctxt,
7321 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007322 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007323 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007324 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007325
7326 return (item);
7327}
7328
Daniel Veillardc0826a72004-08-10 14:17:33 +00007329/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007330 * xmlSchemaParseElement:
7331 * @ctxt: a schema validation context
7332 * @schema: the schema being built
7333 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007334 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00007335 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007336 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007337 * *WARNING* this interface is highly subject to change
7338 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007339 * Returns the element declaration or a particle; NULL in case
7340 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00007341 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007342static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00007343xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007344 xmlNodePtr node, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007345{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007346 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007347 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007348 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007349 xmlNodePtr child = NULL;
7350 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007351 int min, max, isRef = 0;
7352 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007353
7354 /* 3.3.3 Constraints on XML Representations of Element Declarations */
7355 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007356
Daniel Veillard4255d502002-04-16 15:50:10 +00007357 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007358 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007359 /*
7360 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007361 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007362 * robust.
7363 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007364 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007365 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007366 if ((topLevel) || (attr == NULL)) {
7367 if (nameAttr == NULL) {
7368 xmlSchemaPMissingAttrErr(ctxt,
7369 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007370 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007371 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007372 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007373 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007374 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007375
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007376 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007377 child = node->children;
7378 if (IS_SCHEMA(child, "annotation")) {
7379 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7380 child = child->next;
7381 }
7382 /*
7383 * Skip particle part if a global declaration.
7384 */
7385 if (topLevel)
7386 goto declaration_part;
7387 /*
7388 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007389 */
7390 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
7391 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
7392 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007393 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
7394 if (particle == NULL)
7395 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007396
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007397 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
7398
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007399 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007400 const xmlChar *refNs = NULL, *ref = NULL;
7401 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007402 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007403 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00007404 */
7405 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007406 NULL, NULL, attr, &refNs, &ref);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007407 xmlSchemaCheckReference(ctxt, schema, node, NULL, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007408 /*
7409 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00007410 */
7411 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007412 xmlSchemaPMutualExclAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007413 XML_SCHEMAP_SRC_ELEMENT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007414 NULL, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007415 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007416 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007417 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007418 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007419 attr = node->properties;
7420 while (attr != NULL) {
7421 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007422 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
7423 xmlStrEqual(attr->name, BAD_CAST "name") ||
7424 xmlStrEqual(attr->name, BAD_CAST "id") ||
7425 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
7426 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
7427 {
7428 attr = attr->next;
7429 continue;
7430 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007431 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007432 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007433 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007434 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007435 "Only the attributes 'minOccurs', 'maxOccurs' and "
7436 "'id' are allowed in addition to 'ref'");
7437 break;
7438 }
7439 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7440 xmlSchemaPIllegalAttrErr(ctxt,
7441 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007442 NULL, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007443 }
7444 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007445 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007446 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007447 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007448 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007449 if (child != NULL) {
7450 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7451 NULL, NULL, node, child, NULL, "(annotation?)");
7452 }
7453 if ((min == 0) && (max == 0))
7454 goto return_null;
7455 /*
7456 * Create the reference item.
7457 */
7458 refer = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_ELEMENT,
7459 ref, refNs);
7460 if (refer == NULL)
7461 goto return_null;
7462 particle->children = (xmlSchemaTreeItemPtr) refer;
7463 particle->annot = annot;
7464 /*
7465 * Add to assembled items; the reference need to be resolved.
7466 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007467 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007468 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) particle);
7469
7470 return ((xmlSchemaBasicItemPtr) particle);
7471 }
7472 /*
7473 * The declaration part ===============================================
7474 */
7475declaration_part:
7476 {
7477 const xmlChar *ns = NULL, *fixed, *name, *oldcontainer, *attrValue;
7478 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
7479
7480 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007481 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007482 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007483 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007484 * Evaluate the target namespace.
7485 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007486 if (topLevel) {
7487 ns = schema->targetNamespace;
7488 } else {
7489 attr = xmlSchemaGetPropNode(node, "form");
7490 if (attr != NULL) {
7491 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7492 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00007493 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007494 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007495 xmlSchemaPSimpleTypeErr(ctxt,
7496 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7497 NULL, (xmlNodePtr) attr,
7498 NULL, "(qualified | unqualified)",
7499 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007500 }
7501 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007502 ns = schema->targetNamespace;
7503 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007504 decl = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007505 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007506 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00007507 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007508 decl->type = XML_SCHEMA_TYPE_ELEMENT;
7509 decl->node = node;
7510 decl->targetNamespace = ns;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007511 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007512 * Check for illegal attributes.
7513 */
William M. Bracke7091952004-05-11 15:09:58 +00007514 attr = node->properties;
7515 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007516 if (attr->ns == NULL) {
7517 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7518 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007519 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007520 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007521 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007522 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007523 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
7524 {
7525 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007526 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007527 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007528 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007529 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007530 xmlSchemaPIllegalAttrErr(ctxt,
7531 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7532 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007533 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007534 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
7535 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007536 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
7537
7538 xmlSchemaPIllegalAttrErr(ctxt,
7539 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007540 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007541 }
7542 }
7543 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007544
Daniel Veillardc0826a72004-08-10 14:17:33 +00007545 xmlSchemaPIllegalAttrErr(ctxt,
7546 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007547 NULL, (xmlSchemaTypePtr) decl, attr);
William M. Bracke7091952004-05-11 15:09:58 +00007548 }
7549 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007550 }
William M. Bracke7091952004-05-11 15:09:58 +00007551 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007552 * Extract/validate attributes.
7553 */
7554 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007555 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007556 * Process top attributes of global element declarations here.
7557 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007558 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
7559 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007560 xmlSchemaPValAttrQName(ctxt, schema, NULL,
7561 (xmlSchemaTypePtr) decl, node, "substitutionGroup",
7562 &(decl->substGroupNs), &(decl->substGroup));
7563 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007564 node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007565 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007566 /*
7567 * Attribute "final".
7568 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007569 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007570 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007571 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7572 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
7573 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7574 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007575 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007576 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7577 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007578 -1,
7579 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
7580 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007581 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007582 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007583 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
7584 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007585 attrValue, NULL, NULL, NULL);
7586 }
7587 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007588 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007589 /*
7590 * Attribute "block".
7591 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007592 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007593 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007594 /*
7595 * Apply default "block" values.
7596 */
7597 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7598 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
7599 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7600 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
7601 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7602 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007603 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007604 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7605 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007606 -1,
7607 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007608 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007609 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
7610 xmlSchemaPSimpleTypeErr(ctxt,
7611 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007612 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007613 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007614 "restriction | substitution))", attrValue,
7615 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007616 }
7617 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007618 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007619 node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007620 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007621
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007622 attr = xmlSchemaGetPropNode(node, "type");
7623 if (attr != NULL) {
7624 xmlSchemaPValAttrNodeQName(ctxt, schema,
7625 NULL, (xmlSchemaTypePtr) decl, attr,
7626 &(decl->namedTypeNs), &(decl->namedType));
7627 xmlSchemaCheckReference(ctxt, schema, node,
7628 (xmlSchemaBasicItemPtr) decl, decl->namedTypeNs);
7629 }
7630 decl->value = xmlSchemaGetProp(ctxt, node, "default");
7631 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007632 if (attr != NULL) {
7633 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007634 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007635 /*
7636 * 3.3.3 : 1
7637 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007638 */
7639 xmlSchemaPMutualExclAttrErr(ctxt,
7640 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007641 NULL, (xmlSchemaTypePtr) decl, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007642 "default", "fixed");
7643 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007644 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
7645 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007646 }
William M. Bracke7091952004-05-11 15:09:58 +00007647 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007648 /*
7649 * And now for the children...
7650 */
7651 oldcontainer = ctxt->container;
7652 ctxt->container = decl->name;
William M. Bracke7091952004-05-11 15:09:58 +00007653 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007654 /*
7655 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007656 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007657 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007658 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007659 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007660 xmlSchemaPContentErr(ctxt,
7661 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007662 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007663 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007664 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007665 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007666 ELEM_TYPE(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007667 child = child->next;
7668 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007669 /*
7670 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007671 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007672 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007673 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007674 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007675 xmlSchemaPContentErr(ctxt,
7676 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007677 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007678 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007679 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007680 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007681 ELEM_TYPE(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007682 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007683 }
William M. Bracke7091952004-05-11 15:09:58 +00007684 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00007685 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007686 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007687 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007688 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007689 } else if (IS_SCHEMA(child, "key")) {
7690 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007691 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007692 } else if (IS_SCHEMA(child, "keyref")) {
7693 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007694 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007695 }
7696 if (lastIDC != NULL)
7697 lastIDC->next = curIDC;
7698 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007699 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007700 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007701 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00007702 }
7703 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007704 xmlSchemaPContentErr(ctxt,
7705 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007706 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007707 NULL, "(annotation?, ((simpleType | complexType)?, "
7708 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007709 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007710 ctxt->container = oldcontainer;
7711 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007712 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007713 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007714 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00007715 * different layer.
7716 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007717 FREE_AND_NULL(des)
7718 if (topLevel)
7719 return ((xmlSchemaBasicItemPtr) decl);
7720 else {
7721 particle->children = (xmlSchemaTreeItemPtr) decl;
7722 return ((xmlSchemaBasicItemPtr) particle);
7723 }
7724
7725return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007726 FREE_AND_NULL(des);
7727 if (annot != NULL) {
7728 if (particle != NULL)
7729 particle->annot = NULL;
7730 if (decl != NULL)
7731 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007732 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007733 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007734 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007735}
7736
7737/**
7738 * xmlSchemaParseUnion:
7739 * @ctxt: a schema validation context
7740 * @schema: the schema being built
7741 * @node: a subtree containing XML Schema informations
7742 *
7743 * parse a XML schema Union definition
7744 * *WARNING* this interface is highly subject to change
7745 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007746 * Returns -1 in case of internal error, 0 in case of success and a positive
7747 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00007748 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007749static int
Daniel Veillard4255d502002-04-16 15:50:10 +00007750xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007751 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007752{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007753 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007754 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007755 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007756 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007757
7758 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007759 return (-1);
7760 /* Not a component, don't create it. */
7761 type = ctxt->ctxtType;
7762 /*
7763 * Mark the simple type as being of variety "union".
7764 */
7765 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007766 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007767 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7768 * then the ·simple ur-type definition·."
7769 */
7770 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007771 /*
7772 * Check for illegal attributes.
7773 */
7774 attr = node->properties;
7775 while (attr != NULL) {
7776 if (attr->ns == NULL) {
7777 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7778 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007779 xmlSchemaPIllegalAttrErr(ctxt,
7780 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7781 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007782 }
7783 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007784 xmlSchemaPIllegalAttrErr(ctxt,
7785 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7786 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007787 }
7788 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007789 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007790 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007791 /*
7792 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007793 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00007794 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007795 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007796 if (attr != NULL) {
7797 const xmlChar *end;
7798 xmlChar *tmp;
7799 const xmlChar *localName, *nsName;
7800 xmlSchemaTypeLinkPtr link, lastLink = NULL;
7801 xmlSchemaQNameRefPtr ref;
7802
7803 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007804 type->ref = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007805 do {
7806 while (IS_BLANK_CH(*cur))
7807 cur++;
7808 end = cur;
7809 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7810 end++;
7811 if (end == cur)
7812 break;
7813 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007814 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, NULL,
7815 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007816 /*
7817 * Create the member type link.
7818 */
7819 link = (xmlSchemaTypeLinkPtr)
7820 xmlMalloc(sizeof(xmlSchemaTypeLink));
7821 if (link == NULL) {
7822 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
7823 "allocating a type link", NULL);
7824 return (-1);
7825 }
7826 link->type = NULL;
7827 link->next = NULL;
7828 if (lastLink == NULL)
7829 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007830 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007831 lastLink->next = link;
7832 lastLink = link;
7833 /*
7834 * Create a reference item.
7835 */
7836 ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_SIMPLE,
7837 localName, nsName);
7838 if (ref == NULL) {
7839 FREE_AND_NULL(tmp)
7840 return (-1);
7841 }
7842 /*
7843 * Assign the reference to the link, it will be resolved
7844 * later during fixup of the union simple type.
7845 */
7846 link->type = (xmlSchemaTypePtr) ref;
7847 }
7848 FREE_AND_NULL(tmp)
7849 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007850 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007851
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007852 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007853 /*
7854 * And now for the children...
7855 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007856 child = node->children;
7857 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007858 /*
7859 * Add the annotation to the simple type ancestor.
7860 */
7861 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7862 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007863 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007864 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007865 if (IS_SCHEMA(child, "simpleType")) {
7866 xmlSchemaTypePtr subtype, last = NULL;
7867
7868 /*
7869 * Anchor the member types in the "subtypes" field of the
7870 * simple type.
7871 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007872 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007873 subtype = (xmlSchemaTypePtr)
7874 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7875 if (subtype != NULL) {
7876 if (last == NULL) {
7877 type->subtypes = subtype;
7878 last = subtype;
7879 } else {
7880 last->next = subtype;
7881 last = subtype;
7882 }
7883 last->next = NULL;
7884 }
7885 child = child->next;
7886 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007887 }
7888 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007889 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007890 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007891 NULL, NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007892 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007893 if ((attr == NULL) && (type->subtypes == NULL)) {
7894 /*
7895 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007896 * Either the memberTypes [attribute] of the <union> element must
7897 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007898 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007899 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007900 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
7901 NULL, NULL, node,
7902 "Either the attribute 'memberTypes' or "
7903 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007904 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007905 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00007906}
7907
7908/**
7909 * xmlSchemaParseList:
7910 * @ctxt: a schema validation context
7911 * @schema: the schema being built
7912 * @node: a subtree containing XML Schema informations
7913 *
7914 * parse a XML schema List definition
7915 * *WARNING* this interface is highly subject to change
7916 *
William M. Bracke7091952004-05-11 15:09:58 +00007917 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007918 * 1 in case of success.
7919 */
7920static xmlSchemaTypePtr
7921xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007922 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007923{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007924 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007925 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007926 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007927
7928 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7929 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007930 /* Not a component, don't create it. */
7931 type = ctxt->ctxtType;
7932 /*
7933 * Mark the type as being of variety "list".
7934 */
7935 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007936 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007937 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7938 * then the ·simple ur-type definition·."
7939 */
7940 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007941 /*
7942 * Check for illegal attributes.
7943 */
7944 attr = node->properties;
7945 while (attr != NULL) {
7946 if (attr->ns == NULL) {
7947 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7948 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007949 xmlSchemaPIllegalAttrErr(ctxt,
7950 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7951 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007952 }
7953 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007954 xmlSchemaPIllegalAttrErr(ctxt,
7955 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7956 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007957 }
7958 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007959 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007960
7961 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
7962
William M. Brack2f2a6632004-08-20 23:09:47 +00007963 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007964 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
7965 * fields for holding the reference to the itemType.
William M. Brack2f2a6632004-08-20 23:09:47 +00007966 */
7967 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007968 node, "itemType", &(type->refNs), &(type->ref));
William M. Brack2f2a6632004-08-20 23:09:47 +00007969 /*
7970 * And now for the children...
7971 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007972 child = node->children;
7973 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007974 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7975 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007976 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007977 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007978 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007979 /*
7980 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007981 * Either the itemType [attribute] or the <simpleType> [child] of
7982 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007983 */
7984 if (type->ref != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007985 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00007986 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007987 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00007988 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007989 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007990 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007991 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00007992 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007993 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007994 } else if (type->ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007995 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007996 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007997 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007998 "Either the attribute 'itemType' or the <simpleType> child "
7999 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008000 }
8001 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008002 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008003 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008004 NULL, NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008005 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008006 if ((type->ref == NULL) &&
8007 (type->subtypes == NULL) &&
8008 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008009 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008010 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008011 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008012 "Either the attribute 'itemType' or the <simpleType> child "
8013 "must be present", NULL);
8014 }
8015 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008016}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008017
Daniel Veillard4255d502002-04-16 15:50:10 +00008018/**
8019 * xmlSchemaParseSimpleType:
8020 * @ctxt: a schema validation context
8021 * @schema: the schema being built
8022 * @node: a subtree containing XML Schema informations
8023 *
8024 * parse a XML schema Simple Type definition
8025 * *WARNING* this interface is highly subject to change
8026 *
William M. Bracke7091952004-05-11 15:09:58 +00008027 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00008028 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00008029 */
8030static xmlSchemaTypePtr
8031xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008032 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008033{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008034 xmlSchemaTypePtr type, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008035 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008036 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008037 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008038
8039 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8040 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008041
Daniel Veillardc0826a72004-08-10 14:17:33 +00008042 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008043 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008044 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008045 xmlSchemaPMissingAttrErr(ctxt,
8046 XML_SCHEMAP_S4S_ATTR_MISSING,
8047 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008048 "name", NULL);
8049 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008050 } else {
8051 if (xmlSchemaPValAttrNode(ctxt,
8052 NULL, NULL, attr,
8053 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
8054 return (NULL);
8055 /*
8056 * Skip built-in types.
8057 */
8058 if (ctxt->isS4S) {
8059 xmlSchemaTypePtr biType;
8060
8061 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
8062 if (biType != NULL)
8063 return (biType);
8064 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008065 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008066 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008067
Daniel Veillardc0826a72004-08-10 14:17:33 +00008068 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008069 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00008070
Daniel Veillard01fa6152004-06-29 17:04:39 +00008071 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008072 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008073 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008074 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008075 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008076 if (type == NULL)
8077 return (NULL);
8078 type->node = node;
8079 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008080 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008081 /*
8082 * Check for illegal attributes.
8083 */
8084 attr = node->properties;
8085 while (attr != NULL) {
8086 if (attr->ns == NULL) {
8087 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008088 xmlSchemaPIllegalAttrErr(ctxt,
8089 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8090 NULL, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008091 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008092 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008093 xmlSchemaPIllegalAttrErr(ctxt,
8094 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8095 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008096 }
8097 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008098 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008099 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008100 /*
8101 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008102 *
8103 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008104 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008105 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008106 if (type == NULL)
8107 return (NULL);
8108 type->node = node;
8109 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008110 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008111 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8112 /*
8113 * Check for illegal attributes.
8114 */
8115 attr = node->properties;
8116 while (attr != NULL) {
8117 if (attr->ns == NULL) {
8118 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8119 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008120 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008121 xmlSchemaPIllegalAttrErr(ctxt,
8122 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8123 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008124 }
8125 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008126 xmlSchemaPIllegalAttrErr(ctxt,
8127 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8128 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008129 }
8130 attr = attr->next;
8131 }
8132 /*
8133 * Attribute "final".
8134 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008135 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008136 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008137 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8138 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
8139 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8140 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
8141 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8142 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008143 } else {
8144 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008145 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8146 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008147 XML_SCHEMAS_TYPE_FINAL_LIST,
8148 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
8149
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008150 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008151 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008152 type, (xmlNodePtr) attr,
8153 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008154 attrValue, NULL, NULL, NULL);
8155 }
8156 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008157 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008158 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008159 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008160 /*
8161 * And now for the children...
8162 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008163 oldCtxtType = ctxt->ctxtType;
8164 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008165 ctxt->ctxtType = type;
8166 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008167 child = node->children;
8168 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008169 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8170 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008171 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008172 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008173 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
8174 NULL, type, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008175 "(annotation?, (restriction | list | union))");
8176 } else if (IS_SCHEMA(child, "restriction")) {
8177 xmlSchemaParseRestriction(ctxt, schema, child,
8178 XML_SCHEMA_TYPE_SIMPLE);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008179 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008180 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008181 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008182 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008183 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008184 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008185 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008186 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008187 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008188 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8189 NULL, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008190 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008191 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008192 ctxt->parentItem = oldParentItem;
8193 ctxt->ctxtType = oldCtxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008194
Daniel Veillard4255d502002-04-16 15:50:10 +00008195 return (type);
8196}
8197
Daniel Veillard4255d502002-04-16 15:50:10 +00008198/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008199 * xmlSchemaParseModelGroupDefRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00008200 * @ctxt: a schema validation context
8201 * @schema: the schema being built
8202 * @node: a subtree containing XML Schema informations
8203 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008204 * Parses a XML schema particle (reference to a model group definition).
Daniel Veillard4255d502002-04-16 15:50:10 +00008205 * *WARNING* this interface is highly subject to change
8206 *
William M. Bracke7091952004-05-11 15:09:58 +00008207 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008208 * 1 in case of success.
8209 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008210static xmlSchemaTreeItemPtr
8211xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
8212 xmlSchemaPtr schema,
8213 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008214{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008215 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008216 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008217 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008218 const xmlChar *ref = NULL, *refNs = NULL;
8219 int min, max;
8220
8221 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008222 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008223
8224 attr = xmlSchemaGetPropNode(node, "ref");
8225 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008226 xmlSchemaPMissingAttrErr(ctxt,
8227 XML_SCHEMAP_S4S_ATTR_MISSING,
8228 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008229 "ref", NULL);
8230 return (NULL);
8231 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008232 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008233 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008234 }
8235 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008236 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008237 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008238 /*
8239 * Check for illegal attributes.
8240 */
8241 attr = node->properties;
8242 while (attr != NULL) {
8243 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008244 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008245 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8246 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8247 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008248 xmlSchemaPIllegalAttrErr(ctxt,
8249 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8250 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008251 }
8252 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008253 xmlSchemaPIllegalAttrErr(ctxt,
8254 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8255 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008256 }
8257 attr = attr->next;
8258 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008259 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008260 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8261 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008262 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008263 /*
8264 * Create a reference item as the term; it will be substituted for
8265 * the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008266 */
8267 item->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008268 xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_GROUP, ref, refNs);
8269 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) item, refNs);
8270 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
8271 /*
8272 * And now for the children...
8273 */
8274 child = node->children;
8275 /* TODO: Is annotation even allowed for a model group reference? */
8276 if (IS_SCHEMA(child, "annotation")) {
8277 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008278 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008279 */
8280 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8281 child = child->next;
8282 }
8283 if (child != NULL) {
8284 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008285 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008286 NULL, NULL, node, child, NULL,
8287 "(annotation?)");
8288 }
8289 /*
8290 * Corresponds to no component at all if minOccurs==maxOccurs==0.
8291 */
8292 if ((min == 0) && (max == 0))
8293 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008294 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008295 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
8296 return ((xmlSchemaTreeItemPtr) item);
8297}
8298
8299/**
8300 * xmlSchemaParseModelGroupDefinition:
8301 * @ctxt: a schema validation context
8302 * @schema: the schema being built
8303 * @node: a subtree containing XML Schema informations
8304 *
8305 * Parses a XML schema model group definition.
8306 * *WARNING* this interface is highly subject to change
8307 *
8308 * Returns -1 in case of error, 0 if the declaration is improper and
8309 * 1 in case of success.
8310 */
8311static xmlSchemaModelGroupDefPtr
8312xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
8313 xmlSchemaPtr schema,
8314 xmlNodePtr node)
8315{
8316 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008317 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008318 xmlAttrPtr attr;
8319 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008320
8321 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008322 return (NULL);
8323
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008324 attr = xmlSchemaGetPropNode(node, "name");
8325 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008326 xmlSchemaPMissingAttrErr(ctxt,
8327 XML_SCHEMAP_S4S_ATTR_MISSING,
8328 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008329 "name", NULL);
8330 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008331 } else if (xmlSchemaPValAttrNode(ctxt,
8332 NULL, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008333 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8334 return (NULL);
8335 }
8336 item = xmlSchemaAddGroup(ctxt, schema, name, schema->targetNamespace, node);
8337 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008338 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008339 /*
8340 * Check for illegal attributes.
8341 */
8342 attr = node->properties;
8343 while (attr != NULL) {
8344 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008345 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008346 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008347 xmlSchemaPIllegalAttrErr(ctxt,
8348 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8349 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008350 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008351 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008352 xmlSchemaPIllegalAttrErr(ctxt,
8353 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8354 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008355 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008356 attr = attr->next;
8357 }
8358 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8359 /*
8360 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008361 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008362 child = node->children;
8363 if (IS_SCHEMA(child, "annotation")) {
8364 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8365 child = child->next;
8366 }
8367 if (IS_SCHEMA(child, "all")) {
8368 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8369 XML_SCHEMA_TYPE_ALL, 0);
8370 child = child->next;
8371 } else if (IS_SCHEMA(child, "choice")) {
8372 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8373 XML_SCHEMA_TYPE_CHOICE, 0);
8374 child = child->next;
8375 } else if (IS_SCHEMA(child, "sequence")) {
8376 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8377 XML_SCHEMA_TYPE_SEQUENCE, 0);
8378 child = child->next;
8379 }
8380 if (child != NULL) {
8381 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008382 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8383 NULL, NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008384 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008385 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008386
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008387 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00008388}
8389
8390/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008391 * xmlSchemaCleanupDoc:
8392 * @ctxt: a schema validation context
8393 * @node: the root of the document.
8394 *
8395 * removes unwanted nodes in a schemas document tree
8396 */
8397static void
8398xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
8399{
8400 xmlNodePtr delete, cur;
8401
8402 if ((ctxt == NULL) || (root == NULL)) return;
8403
8404 /*
8405 * Remove all the blank text nodes
8406 */
8407 delete = NULL;
8408 cur = root;
8409 while (cur != NULL) {
8410 if (delete != NULL) {
8411 xmlUnlinkNode(delete);
8412 xmlFreeNode(delete);
8413 delete = NULL;
8414 }
8415 if (cur->type == XML_TEXT_NODE) {
8416 if (IS_BLANK_NODE(cur)) {
8417 if (xmlNodeGetSpacePreserve(cur) != 1) {
8418 delete = cur;
8419 }
8420 }
8421 } else if ((cur->type != XML_ELEMENT_NODE) &&
8422 (cur->type != XML_CDATA_SECTION_NODE)) {
8423 delete = cur;
8424 goto skip_children;
8425 }
8426
8427 /*
8428 * Skip to next node
8429 */
8430 if (cur->children != NULL) {
8431 if ((cur->children->type != XML_ENTITY_DECL) &&
8432 (cur->children->type != XML_ENTITY_REF_NODE) &&
8433 (cur->children->type != XML_ENTITY_NODE)) {
8434 cur = cur->children;
8435 continue;
8436 }
8437 }
8438 skip_children:
8439 if (cur->next != NULL) {
8440 cur = cur->next;
8441 continue;
8442 }
8443
8444 do {
8445 cur = cur->parent;
8446 if (cur == NULL)
8447 break;
8448 if (cur == root) {
8449 cur = NULL;
8450 break;
8451 }
8452 if (cur->next != NULL) {
8453 cur = cur->next;
8454 break;
8455 }
8456 } while (cur != NULL);
8457 }
8458 if (delete != NULL) {
8459 xmlUnlinkNode(delete);
8460 xmlFreeNode(delete);
8461 delete = NULL;
8462 }
8463}
8464
William M. Brack2f2a6632004-08-20 23:09:47 +00008465
8466/**
8467 * xmlSchemaImportSchema
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008468 *
William M. Brack2f2a6632004-08-20 23:09:47 +00008469 * @ctxt: a schema validation context
8470 * @schemaLocation: an URI defining where to find the imported schema
8471 *
8472 * import a XML schema
8473 * *WARNING* this interface is highly subject to change
8474 *
8475 * Returns -1 in case of error and 1 in case of success.
8476 */
8477#if 0
8478static xmlSchemaImportPtr
8479xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
8480 const xmlChar *schemaLocation)
8481{
8482 xmlSchemaImportPtr import;
8483 xmlSchemaParserCtxtPtr newctxt;
8484
8485 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8486 if (newctxt == NULL) {
8487 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
8488 NULL);
8489 return (NULL);
8490 }
8491 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
8492 /* Keep the same dictionnary for parsing, really */
8493 xmlDictReference(ctxt->dict);
8494 newctxt->dict = ctxt->dict;
8495 newctxt->includes = 0;
8496 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
8497
8498 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
8499 ctxt->userData);
8500
8501 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8502 if (import == NULL) {
8503 xmlSchemaPErrMemory(NULL, "allocating imported schema",
8504 NULL);
8505 xmlSchemaFreeParserCtxt(newctxt);
8506 return (NULL);
8507 }
8508
8509 memset(import, 0, sizeof(xmlSchemaImport));
8510 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8511 import->schema = xmlSchemaParse(newctxt);
8512
8513 if (import->schema == NULL) {
8514 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008515 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008516 "Failed to import schema from location \"%s\".\n",
8517 schemaLocation, NULL);
8518
8519 xmlSchemaFreeParserCtxt(newctxt);
8520 /* The schemaLocation is held by the dictionary.
8521 if (import->schemaLocation != NULL)
8522 xmlFree((xmlChar *)import->schemaLocation);
8523 */
8524 xmlFree(import);
8525 return NULL;
8526 }
8527
8528 xmlSchemaFreeParserCtxt(newctxt);
8529 return import;
8530}
8531#endif
8532
8533static void
8534xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
8535{
8536 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8537 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
8538
8539 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
8540 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
8541
8542 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8543 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
8544 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8545 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
8546 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8547 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
8548 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8549 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
8550
8551 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8552 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
8553 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8554 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
8555 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8556 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
8557}
8558
8559static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008560xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008561 xmlSchemaPtr schema,
8562 xmlNodePtr node)
8563{
8564 xmlAttrPtr attr;
8565 const xmlChar *val;
8566
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008567 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8568 if (schema->version == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008569 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008570 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8571 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008572 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008573 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), NULL);
8574
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008575 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008576 if (attr != NULL) {
8577 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008578 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008579 XML_SCHEMAS_QUALIF_ELEM) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008580 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008581 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008582 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008583 "(qualified | unqualified)", val, NULL, NULL, NULL);
8584 }
8585 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008586
8587 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008588 if (attr != NULL) {
8589 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008590 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008591 XML_SCHEMAS_QUALIF_ATTR) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008592 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008593 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008594 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008595 "(qualified | unqualified)", val, NULL, NULL, NULL);
8596 }
8597 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008598
8599 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008600 if (attr != NULL) {
8601 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8602 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8603 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
8604 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
8605 -1,
8606 XML_SCHEMAS_FINAL_DEFAULT_LIST,
8607 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
8608 xmlSchemaPSimpleTypeErr(ctxt,
8609 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008610 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008611 "(#all | List of (extension | restriction | list | union))",
8612 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008613 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008614 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008615
8616 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008617 if (attr != NULL) {
8618 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8619 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8620 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
8621 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
8622 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
8623 xmlSchemaPSimpleTypeErr(ctxt,
8624 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008625 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008626 "(#all | List of (extension | restriction | substitution))",
8627 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008628 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008629 }
8630}
8631
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008632/**
8633 * xmlSchemaParseSchemaTopLevel:
8634 * @ctxt: a schema validation context
8635 * @schema: the schemas
8636 * @nodes: the list of top level nodes
8637 *
8638 * Returns the internal XML Schema structure built from the resource or
8639 * NULL in case of error
8640 */
8641static void
8642xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
8643 xmlSchemaPtr schema, xmlNodePtr nodes)
8644{
8645 xmlNodePtr child;
8646 xmlSchemaAnnotPtr annot;
8647
8648 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
8649 return;
8650
8651 child = nodes;
8652 while ((IS_SCHEMA(child, "include")) ||
8653 (IS_SCHEMA(child, "import")) ||
8654 (IS_SCHEMA(child, "redefine")) ||
8655 (IS_SCHEMA(child, "annotation"))) {
8656 if (IS_SCHEMA(child, "annotation")) {
8657 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8658 if (schema->annot == NULL)
8659 schema->annot = annot;
8660 else
8661 xmlSchemaFreeAnnot(annot);
8662 } else if (IS_SCHEMA(child, "import")) {
8663 xmlSchemaParseImport(ctxt, schema, child);
8664 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008665 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008666 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008667 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008668 } else if (IS_SCHEMA(child, "redefine")) {
8669 TODO
8670 }
8671 child = child->next;
8672 }
8673 while (child != NULL) {
8674 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008675 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008676 child = child->next;
8677 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008678 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008679 child = child->next;
8680 } else if (IS_SCHEMA(child, "element")) {
8681 xmlSchemaParseElement(ctxt, schema, child, 1);
8682 child = child->next;
8683 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00008684 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008685 child = child->next;
8686 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008687 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008688 child = child->next;
8689 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008690 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008691 child = child->next;
8692 } else if (IS_SCHEMA(child, "notation")) {
8693 xmlSchemaParseNotation(ctxt, schema, child);
8694 child = child->next;
8695 } else {
8696 xmlSchemaPErr2(ctxt, NULL, child,
8697 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008698 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008699 child->name, NULL);
8700 child = child->next;
8701 }
8702 while (IS_SCHEMA(child, "annotation")) {
8703 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8704 if (schema->annot == NULL)
8705 schema->annot = annot;
8706 else
8707 xmlSchemaFreeAnnot(annot);
8708 child = child->next;
8709 }
8710 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008711 ctxt->parentItem = NULL;
8712 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008713}
8714
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008715static xmlSchemaImportPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008716xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008717 xmlHashTablePtr *imports,
8718 const xmlChar *nsName)
8719{
8720 xmlSchemaImportPtr ret;
8721
8722 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00008723 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008724 if (*imports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008725 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008726 XML_SCHEMAP_FAILED_BUILD_IMPORT,
8727 NULL, NULL, (xmlNodePtr) ctxt->doc,
8728 "Internal error: failed to build the import table",
8729 NULL);
8730 return (NULL);
8731 }
8732 }
8733 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8734 if (ret == NULL) {
8735 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
8736 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008737 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008738 memset(ret, 0, sizeof(xmlSchemaImport));
8739 if (nsName == NULL)
8740 nsName = XML_SCHEMAS_NO_NAMESPACE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008741 xmlHashAddEntry(*imports, nsName, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008742
8743 return (ret);
8744}
8745
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008746/**
8747 * xmlSchemaNewParserCtxtUseDict:
8748 * @URL: the location of the schema
8749 * @dict: the dictionary to be used
8750 *
8751 * Create an XML Schemas parse context for that file/resource expected
8752 * to contain an XML Schemas file.
8753 *
8754 * Returns the parser context or NULL in case of error
8755 */
8756static xmlSchemaParserCtxtPtr
8757xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
8758{
8759 xmlSchemaParserCtxtPtr ret;
8760 /*
8761 if (URL == NULL)
8762 return (NULL);
8763 */
8764
8765 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8766 if (ret == NULL) {
8767 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8768 NULL);
8769 return (NULL);
8770 }
8771 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8772 ret->dict = dict;
8773 xmlDictReference(dict);
8774 if (URL != NULL)
8775 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
8776 ret->includes = 0;
8777 return (ret);
8778}
8779
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008780static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008781xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
8782{
8783 if (vctxt->pctxt == NULL) {
8784 if (vctxt->schema != NULL)
8785 vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
8786 else
8787 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
8788 if (vctxt->pctxt == NULL) {
8789 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
8790 "failed to create a temp. parser context");
8791 return (-1);
8792 }
8793 /* TODO: Pass user data. */
8794 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
8795 }
8796 return (0);
8797}
8798
8799static int
8800xmlSchemaAcquireSchemaDoc(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008801 xmlSchemaPtr schema,
8802 xmlNodePtr node,
8803 const xmlChar *nsName,
8804 const xmlChar *location,
8805 xmlDocPtr *doc,
8806 const xmlChar **targetNamespace,
8807 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008808{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008809 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008810 xmlParserCtxtPtr parserCtxt;
8811 xmlSchemaImportPtr import;
8812 const xmlChar *ns;
8813 xmlNodePtr root;
8814
8815 /*
8816 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
8817 * <xsi:noNamespaceSchemaLocation>.
8818 */
8819 *doc = NULL;
8820 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008821 * Given that the schemaLocation [attribute] is only a hint, it is open
8822 * to applications to ignore all but the first <import> for a given
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008823 * namespace, regardless of the ·actual value· of schemaLocation, but
8824 * such a strategy risks missing useful information when new
8825 * schemaLocations are offered.
8826 *
8827 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
8828 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
8829 * valid or not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008830 * We will follow XSV here.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008831 */
8832 if (location == NULL) {
8833 /*
8834 * Schema Document Location Strategy:
8835 *
8836 * 3 Based on the namespace name, identify an existing schema document,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008837 * either as a resource which is an XML document or a <schema> element
8838 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008839 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008840 * 5 Attempt to resolve the namespace name to locate such a resource.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008841 *
8842 * NOTE: Those stategies are not supported, so we will skip.
8843 */
8844 return (0);
8845 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008846 if (nsName == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008847 ns = XML_SCHEMAS_NO_NAMESPACE;
8848 else
8849 ns = nsName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008850
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008851 import = xmlHashLookup(schema->schemasImports, ns);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008852 if (import != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008853 /*
8854 * There was a valid resource for the specified namespace already
8855 * defined, so skip.
8856 * TODO: This might be changed someday to allow import of
8857 * components from multiple documents for a single target namespace.
8858 */
8859 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008860 }
8861 if (actxt->type == XML_SCHEMA_CTXT_PARSER)
8862 pctxt = (xmlSchemaParserCtxtPtr) actxt;
8863 else {
8864 xmlSchemaCreatePCtxtOnVCtxt((xmlSchemaValidCtxtPtr) actxt);
8865 pctxt = ((xmlSchemaValidCtxtPtr) actxt)->pctxt;
8866 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008867 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008868 * Schema Document Location Strategy:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008869 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008870 * 2 Based on the location URI, identify an existing schema document,
8871 * either as a resource which is an XML document or a <schema> element
8872 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008873 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008874 * 4 Attempt to resolve the location URI, to locate a resource on the
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008875 * web which is or contains or references a <schema> element;
8876 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
8877 *
8878 */
8879 if ((absolute == 0) && (node != NULL)) {
8880 xmlChar *base, *URI;
8881
8882 base = xmlNodeGetBase(node->doc, node);
8883 if (base == NULL) {
8884 URI = xmlBuildURI(location, node->doc->URL);
8885 } else {
8886 URI = xmlBuildURI(location, base);
8887 xmlFree(base);
8888 }
8889 if (URI != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008890 location = xmlDictLookup(pctxt->dict, URI, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008891 xmlFree(URI);
8892 }
8893 }
8894 parserCtxt = xmlNewParserCtxt();
8895 if (parserCtxt == NULL) {
8896 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
8897 "allocating a parser context", NULL);
8898 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008899 }
8900 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008901 xmlDictFree(parserCtxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008902 parserCtxt->dict = pctxt->dict;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008903 xmlDictReference(parserCtxt->dict);
8904 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008905 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008906 NULL, SCHEMAS_PARSE_OPTIONS);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008907 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008908 * 2.1 The referent is (a fragment of) a resource which is an
8909 * XML document (see clause 1.1), which in turn corresponds to
8910 * a <schema> element information item in a well-formed information
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008911 * set, which in turn corresponds to a valid schema.
8912 * TODO: What to do with the "fragment" stuff?
8913 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008914 * 2.2 The referent is a <schema> element information item in
8915 * a well-formed information set, which in turn corresponds
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008916 * to a valid schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008917 * NOTE: 2.2 won't apply, since only XML documents will be processed
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008918 * here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008919 */
8920 if (*doc == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008921 xmlErrorPtr lerr;
8922 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008923 * It is *not* an error for the application schema reference
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008924 * strategy to fail.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008925 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008926 * If the doc is NULL and the parser error is an IO error we
8927 * will assume that the resource could not be located or accessed.
8928 *
8929 * TODO: Try to find specific error codes to react only on
8930 * localisation failures.
8931 *
8932 * TODO, FIXME: Check the spec: is a namespace added to the imported
8933 * namespaces, even if the schemaLocation did not provide
8934 * a resource? I guess so, since omitting the "schemaLocation"
8935 * attribute, imports a namespace as well.
8936 */
8937 lerr = xmlGetLastError();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008938 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008939 xmlFreeParserCtxt(parserCtxt);
8940 return(0);
8941 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008942 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008943 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008944 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008945 "Failed to parse the resource '%s' for import",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008946 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008947 xmlFreeParserCtxt(parserCtxt);
8948 return(XML_SCHEMAP_SRC_IMPORT_2_1);
8949 }
8950 xmlFreeParserCtxt(parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008951
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008952 root = xmlDocGetRootElement(*doc);
8953 if (root == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008954 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008955 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008956 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008957 "The XML document '%s' to be imported has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008958 "element", location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008959 xmlFreeDoc(*doc);
8960 *doc = NULL;
8961 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008962 }
8963
8964 xmlSchemaCleanupDoc(pctxt, root);
8965
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008966 if (!IS_SCHEMA(root, "schema")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008967 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008968 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008969 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008970 "The XML document '%s' to be imported is not a XML schema document",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008971 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008972 xmlFreeDoc(*doc);
8973 *doc = NULL;
8974 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008975 }
8976 *targetNamespace = xmlSchemaGetProp(pctxt, root, "targetNamespace");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008977 /*
8978 * Schema Representation Constraint: Import Constraints and Semantics
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008979 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008980 if (nsName == NULL) {
8981 if (*targetNamespace != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008982 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008983 XML_SCHEMAP_SRC_IMPORT_3_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008984 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008985 "The XML schema to be imported is not expected "
8986 "to have a target namespace; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008987 "its target namespace of '%s'", *targetNamespace, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008988 xmlFreeDoc(*doc);
8989 *doc = NULL;
8990 return (XML_SCHEMAP_SRC_IMPORT_3_2);
8991 }
8992 } else {
8993 if (*targetNamespace == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008994 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008995 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008996 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008997 "The XML schema to be imported is expected to have a target "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008998 "namespace of '%s'", nsName, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008999 xmlFreeDoc(*doc);
9000 *doc = NULL;
9001 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9002 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009003 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009004 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009005 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009006 "The XML schema to be imported is expected to have a "
9007 "target namespace of '%s'; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009008 "its target namespace of '%s'",
9009 nsName, *targetNamespace);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009010 xmlFreeDoc(*doc);
9011 *doc = NULL;
9012 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9013 }
9014 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009015 import = xmlSchemaAddImport(pctxt, &(schema->schemasImports), nsName);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009016 if (import == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009017 AERROR_INT("xmlSchemaAcquireSchemaDoc",
9018 "failed to build import table");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009019 xmlFreeDoc(*doc);
9020 *doc = NULL;
9021 return (-1);
9022 }
9023 import->schemaLocation = location;
9024 import->doc = *doc;
9025 return (0);
9026}
William M. Brack2f2a6632004-08-20 23:09:47 +00009027
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009028static void
9029xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
9030 xmlSchemaPtr schema,
9031 const xmlChar *targetNamespace,
9032 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009033{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009034 const xmlChar *oldURL, **oldLocImps, *oldTNS;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009035 int oldFlags, oldNumLocImps, oldSizeLocImps, oldIsS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009036
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009037 /*
9038 * Save and reset the context & schema.
9039 */
9040 oldURL = pctxt->URL;
9041 /* TODO: Is using the doc->URL here correct? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009042 pctxt->URL = node->doc->URL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009043 oldLocImps = pctxt->localImports;
9044 pctxt->localImports = NULL;
9045 oldNumLocImps = pctxt->nbLocalImports;
9046 pctxt->nbLocalImports = 0;
9047 oldSizeLocImps = pctxt->sizeLocalImports;
9048 pctxt->sizeLocalImports = 0;
9049 oldFlags = schema->flags;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009050 oldIsS4S = pctxt->isS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009051 xmlSchemaClearSchemaDefaults(schema);
9052 oldTNS = schema->targetNamespace;
9053 schema->targetNamespace = targetNamespace;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009054 if ((targetNamespace != NULL) &&
9055 xmlStrEqual(targetNamespace, xmlSchemaNs)) {
9056 /*
9057 * We are parsing the schema for schema!
9058 */
9059 pctxt->isS4S = 1;
9060 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009061 /*
9062 * Parse the schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009063 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009064 xmlSchemaParseSchemaDefaults(pctxt, schema, node);
9065 xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
9066 /*
9067 * Restore the context & schema.
9068 */
9069 schema->flags = oldFlags;
9070 schema->targetNamespace = oldTNS;
9071 if (pctxt->localImports != NULL)
9072 xmlFree((xmlChar *) pctxt->localImports);
9073 pctxt->localImports = oldLocImps;
9074 pctxt->nbLocalImports = oldNumLocImps;
9075 pctxt->sizeLocalImports = oldSizeLocImps;
9076 pctxt->URL = oldURL;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009077 pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009078}
9079
William M. Brack2f2a6632004-08-20 23:09:47 +00009080/**
9081 * xmlSchemaParseImport:
9082 * @ctxt: a schema validation context
9083 * @schema: the schema being built
9084 * @node: a subtree containing XML Schema informations
9085 *
9086 * parse a XML schema Import definition
9087 * *WARNING* this interface is highly subject to change
9088 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009089 * Returns 0 in case of success, a positive error code if
9090 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +00009091 */
9092static int
9093xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9094 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009095{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009096 xmlNodePtr child;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009097 const xmlChar *namespaceName = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009098 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009099 const xmlChar *targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00009100 xmlAttrPtr attr;
9101 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009102 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009103
9104 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9105 return (-1);
9106
9107 /*
9108 * Check for illegal attributes.
9109 */
9110 attr = node->properties;
9111 while (attr != NULL) {
9112 if (attr->ns == NULL) {
9113 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9114 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
9115 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009116 xmlSchemaPIllegalAttrErr(ctxt,
9117 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9118 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009119 }
9120 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009121 xmlSchemaPIllegalAttrErr(ctxt,
9122 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9123 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009124 }
9125 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009126 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009127 /*
9128 * Extract and validate attributes.
9129 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009130 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9131 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009132 &namespaceName) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009133 xmlSchemaPSimpleTypeErr(ctxt,
9134 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
9135 NULL, node,
9136 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009137 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009138 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
9139 }
9140
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009141 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9142 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +00009143 &schemaLocation) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009144 xmlSchemaPSimpleTypeErr(ctxt,
9145 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
9146 NULL, node,
9147 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009148 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009149 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009150 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009151 /*
9152 * And now for the children...
9153 */
9154 child = node->children;
9155 if (IS_SCHEMA(child, "annotation")) {
9156 /*
9157 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009158 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +00009159 */
9160 child = child->next;
9161 }
9162 if (child != NULL) {
9163 xmlSchemaPContentErr(ctxt,
9164 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
9165 NULL, NULL, node, child, NULL,
9166 "(annotation?)");
9167 }
9168 /*
9169 * Apply additional constraints.
9170 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009171 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009172 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009173 * 1.1 If the namespace [attribute] is present, then its ·actual value·
9174 * must not match the ·actual value· of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +00009175 * targetNamespace [attribute].
9176 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009177 if (xmlStrEqual(schema->targetNamespace, namespaceName)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009178 xmlSchemaPCustomErr(ctxt,
9179 XML_SCHEMAP_SRC_IMPORT_1_1,
9180 NULL, NULL, node,
9181 "The value of the attribute 'namespace' must not match "
9182 "the target namespace '%s' of the importing schema",
9183 schema->targetNamespace);
9184 return (XML_SCHEMAP_SRC_IMPORT_1_1);
9185 }
9186 } else {
9187 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009188 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +00009189 * <schema> must have a targetNamespace [attribute].
9190 */
9191 if (schema->targetNamespace == NULL) {
9192 xmlSchemaPCustomErr(ctxt,
9193 XML_SCHEMAP_SRC_IMPORT_1_2,
9194 NULL, NULL, node,
9195 "The attribute 'namespace' must be existent if "
9196 "the importing schema has no target namespace",
9197 NULL);
9198 return (XML_SCHEMAP_SRC_IMPORT_1_2);
9199 }
9200 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009201 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009202 * Add the namespace to the list of locally imported namespace.
9203 */
9204 if (ctxt->localImports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009205 ctxt->localImports = (const xmlChar **) xmlMalloc(10 *
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009206 sizeof(const xmlChar*));
9207 ctxt->sizeLocalImports = 10;
9208 ctxt->nbLocalImports = 0;
9209 } else if (ctxt->sizeLocalImports <= ctxt->nbLocalImports) {
9210 ctxt->sizeLocalImports *= 2;
9211 ctxt->localImports = (const xmlChar **) xmlRealloc(
9212 (xmlChar **) ctxt->localImports,
9213 ctxt->sizeLocalImports * sizeof(const xmlChar*));
9214 }
9215 ctxt->localImports[ctxt->nbLocalImports++] = namespaceName;
9216 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009217 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00009218 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009219 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) ctxt,
9220 schema, node, namespaceName,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009221 schemaLocation, &doc, &targetNamespace, 0);
9222 if (ret != 0) {
9223 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00009224 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009225 return (ret);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009226 } else if (doc != NULL) {
9227 xmlSchemaParseForImpInc(ctxt, schema, targetNamespace,
9228 xmlDocGetRootElement(doc));
William M. Brack2f2a6632004-08-20 23:09:47 +00009229 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009230
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009231 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009232}
9233
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009234/**
9235 * xmlSchemaParseInclude:
9236 * @ctxt: a schema validation context
9237 * @schema: the schema being built
9238 * @node: a subtree containing XML Schema informations
9239 *
9240 * parse a XML schema Include definition
9241 *
William M. Bracke7091952004-05-11 15:09:58 +00009242 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009243 * 1 in case of success.
9244 */
9245static int
9246xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9247 xmlNodePtr node)
9248{
9249 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009250 const xmlChar *schemaLocation, *targetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009251 xmlDocPtr doc = NULL;
9252 xmlNodePtr root = NULL;
Daniel Veillardcffc1c72005-03-12 18:54:55 +00009253 xmlSchemaIncludePtr include = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009254 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009255 xmlAttrPtr attr;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009256 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009257
9258
9259 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9260 return (-1);
9261
9262 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009263 * Check for illegal attributes.
9264 */
9265 attr = node->properties;
9266 while (attr != NULL) {
9267 if (attr->ns == NULL) {
9268 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9269 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009270 xmlSchemaPIllegalAttrErr(ctxt,
9271 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9272 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009273 }
9274 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009275 xmlSchemaPIllegalAttrErr(ctxt,
9276 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9277 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009278 }
9279 attr = attr->next;
9280 }
9281 /*
9282 * Extract and validate attributes.
9283 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009284 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009285 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009286 * Preliminary step, extract the URI-Reference for the include and
9287 * make an URI from the base.
9288 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009289 attr = xmlSchemaGetPropNode(node, "schemaLocation");
9290 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009291 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009292 xmlChar *uri = NULL;
9293
9294 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9295 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009296 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009297 base = xmlNodeGetBase(node->doc, node);
9298 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009299 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009300 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00009301 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009302 xmlFree(base);
9303 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009304 if (uri == NULL) {
9305 xmlSchemaPErr(ctxt,
9306 node,
9307 XML_SCHEMAP_INTERNAL,
9308 "Internal error: xmlSchemaParseInclude, "
9309 "could not build an URI from the schemaLocation.\n",
9310 NULL, NULL);
9311 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009312 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009313 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
9314 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009315 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009316 xmlSchemaPMissingAttrErr(ctxt,
9317 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
9318 NULL, node, "schemaLocation", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009319 goto exit_invalid;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009320 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009321 /*
9322 * And now for the children...
9323 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009324 child = node->children;
9325 while (IS_SCHEMA(child, "annotation")) {
9326 /*
9327 * the annotations here are simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009328 * TODO: really?
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009329 */
9330 child = child->next;
9331 }
9332 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009333 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009334 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
9335 NULL, NULL, node, child, NULL,
9336 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009337 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009338 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009339 * Report self-inclusion.
9340 */
9341 if (xmlStrEqual(schemaLocation, ctxt->URL)) {
9342 xmlSchemaPCustomErr(ctxt,
9343 XML_SCHEMAP_SRC_INCLUDE,
9344 NULL, NULL, node,
9345 "The schema document '%s' cannot include itself.",
9346 schemaLocation);
9347 return (XML_SCHEMAP_SRC_INCLUDE);
9348 }
9349 /*
9350 * Check if this one was already processed to avoid incorrect
9351 * duplicate component errors and infinite circular inclusion.
9352 */
9353 include = schema->includes;
9354 while (include != NULL) {
9355 if (xmlStrEqual(include->schemaLocation, schemaLocation)) {
9356 targetNamespace = include->origTargetNamespace;
9357 if (targetNamespace == NULL) {
9358 /*
9359 * Chameleon include: skip only if it was build for
9360 * the targetNamespace of the including schema.
9361 */
9362 if (xmlStrEqual(schema->targetNamespace,
9363 include->targetNamespace)) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009364 goto check_targetNamespace;
9365 }
9366 } else {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009367 goto check_targetNamespace;
9368 }
9369 }
9370 include = include->next;
9371 }
9372 /*
9373 * First step is to parse the input document into an DOM/Infoset
9374 * TODO: Use xmlCtxtReadFile to share the dictionary?
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009375 */
9376 parserCtxt = xmlNewParserCtxt();
9377 if (parserCtxt == NULL) {
9378 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
9379 "allocating a parser context", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009380 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009381 }
9382
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009383 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
9384 xmlDictFree(parserCtxt->dict);
9385 parserCtxt->dict = ctxt->dict;
9386 xmlDictReference(parserCtxt->dict);
9387 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009388
9389 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009390 NULL, SCHEMAS_PARSE_OPTIONS);
9391 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009392 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009393 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009394 * TODO: It is not an error for the ·actual value· of the
9395 * schemaLocation [attribute] to fail to resolve it all, in which
9396 * case no corresponding inclusion is performed.
William M. Brack2f2a6632004-08-20 23:09:47 +00009397 * So do we need a warning report here?
9398 */
9399 xmlSchemaPCustomErr(ctxt,
9400 XML_SCHEMAP_FAILED_LOAD,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009401 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00009402 "Failed to load the document '%s' for inclusion", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009403 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009404 }
9405
9406 /*
9407 * Then extract the root of the schema
9408 */
9409 root = xmlDocGetRootElement(doc);
9410 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009411 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009412 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00009413 NULL, NULL, node,
9414 "The included document '%s' has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009415 "element", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009416 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009417 }
9418
9419 /*
9420 * Remove all the blank text nodes
9421 */
9422 xmlSchemaCleanupDoc(ctxt, root);
9423
9424 /*
9425 * Check the schemas top level element
9426 */
9427 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009428 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009429 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00009430 NULL, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009431 "The document '%s' to be included is not a schema document",
William M. Brack2f2a6632004-08-20 23:09:47 +00009432 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009433 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009434 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009435
William M. Brack2f2a6632004-08-20 23:09:47 +00009436 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009437 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009438 * 2.1 SII has a targetNamespace [attribute], and its ·actual
9439 * value· is identical to the ·actual value· of the targetNamespace
Daniel Veillardc0826a72004-08-10 14:17:33 +00009440 * [attribute] of SIIÂ’ (which must have such an [attribute]).
9441 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009442check_targetNamespace:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009443 if (targetNamespace != NULL) {
9444 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009445 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009446 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009447 NULL, NULL, node,
9448 "The target namespace of the included schema "
9449 "'%s' has to be absent, since the including schema "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009450 "has no target namespace",
9451 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009452 goto exit_invalid;
William M. Brack2f2a6632004-08-20 23:09:47 +00009453 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
9454 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009455 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009456 NULL, NULL, node,
9457 "The target namespace '%s' of the included schema '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009458 "differs from '%s' of the including schema",
William M. Brack2f2a6632004-08-20 23:09:47 +00009459 targetNamespace, schemaLocation, schema->targetNamespace);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009460 goto exit_invalid;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009461 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009462 } else if (schema->targetNamespace != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009463 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009464 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009465 } else
9466 wasConvertingNs = 1;
9467 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009468
9469 if (include != NULL)
9470 goto exit;
9471
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009472 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009473 * URGENT TODO: If the schema is a chameleon-include then copy the
9474 * components into the including schema and modify the targetNamespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009475 * of those components, do nothing otherwise.
9476 * NOTE: This is currently worked-around by compiling the chameleon
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009477 * for every destinct including targetNamespace; thus not performant at
9478 * the moment.
9479 * TODO: Check when the namespace in wildcards for chameleons needs
9480 * to be converted: before we built wildcard intersections or after.
9481 */
9482 /*
9483 * Register the include.
9484 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009485 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
9486 if (include == NULL) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009487 xmlSchemaPErrMemory(ctxt, "allocating include entry", NULL);
9488 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009489 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009490 memset(include, 0, sizeof(xmlSchemaInclude));
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009491 include->next = schema->includes;
9492 schema->includes = include;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009493 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009494 * TODO: Use the resolved URI for the this location, since it might
9495 * differ if using filenames/URIs simultaneosly.
Daniel Veillardc0826a72004-08-10 14:17:33 +00009496 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009497 include->schemaLocation = schemaLocation;
9498 include->doc = doc;
9499 /*
9500 * In case of chameleons, the original target namespace will differ
9501 * from the resulting namespace.
9502 */
9503 include->origTargetNamespace = targetNamespace;
9504 include->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009505#ifdef DEBUG_INCLUDES
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009506 if (targetNamespace != schema->targetNamespace)
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009507 xmlGenericError(xmlGenericErrorContext,
9508 "INCLUDING CHAMELEON '%s'\n orig TNS '%s'\n"
9509 " into TNS '%s'\n", schemaLocation,
9510 targetNamespace, schema->targetNamespace);
9511 else
9512 xmlGenericError(xmlGenericErrorContext,
9513 "INCLUDING '%s'\n orig-TNS '%s'\n", schemaLocation,
9514 targetNamespace);
9515#endif
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009516 /*
9517 * Compile the included schema.
9518 */
9519 xmlSchemaParseForImpInc(ctxt, schema, schema->targetNamespace, root);
9520
9521exit:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009522 /*
9523 * Remove the converting flag.
9524 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009525 if ((wasConvertingNs == 0) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00009526 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00009527 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009528 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009529
9530exit_invalid:
9531 if (doc != NULL) {
9532 if (include != NULL)
9533 include->doc = NULL;
9534 xmlFreeDoc(doc);
9535 }
9536 return (ctxt->err);
9537
9538exit_failure:
9539 if (doc != NULL) {
9540 if (include != NULL)
9541 include->doc = NULL;
9542 xmlFreeDoc(doc);
9543 }
9544 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009545}
9546
9547/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009548 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +00009549 * @ctxt: a schema validation context
9550 * @schema: the schema being built
9551 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009552 * @type: the "compositor" type
9553 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +00009554 *
9555 * parse a XML schema Sequence definition
9556 * *WARNING* this interface is highly subject to change
9557 *
William M. Bracke7091952004-05-11 15:09:58 +00009558 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00009559 * 1 in case of success.
9560 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009561static xmlSchemaTreeItemPtr
9562xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9563 xmlNodePtr node, xmlSchemaTypeType type,
9564 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +00009565{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009566 xmlSchemaModelGroupPtr item;
9567 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009568 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009569 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009570 const xmlChar *oldcontainer, *container;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009571 int min = 0, max = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009572
9573 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009574 return (NULL);
9575 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009576 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +00009577 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009578 item = xmlSchemaAddModelGroup(ctxt, schema, type, &container, node);
9579 if (item == NULL)
9580 return (NULL);
9581
9582 if (withParticle) {
9583 if (type == XML_SCHEMA_TYPE_ALL) {
9584 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009585 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009586 } else {
9587 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009588 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9589 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9590 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009591 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009592 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
9593 /*
9594 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009595 */
9596 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
9597 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009598 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009599 particle->children = (xmlSchemaTreeItemPtr) item;
9600 /*
9601 * Check for illegal attributes.
9602 */
9603 attr = node->properties;
9604 while (attr != NULL) {
9605 if (attr->ns == NULL) {
9606 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9607 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
9608 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009609 xmlSchemaPIllegalAttrErr(ctxt,
9610 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9611 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009612 }
9613 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009614 xmlSchemaPIllegalAttrErr(ctxt,
9615 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9616 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009617 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009618 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00009619 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009620 } else {
9621 /*
9622 * Check for illegal attributes.
9623 */
9624 attr = node->properties;
9625 while (attr != NULL) {
9626 if (attr->ns == NULL) {
9627 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009628 xmlSchemaPIllegalAttrErr(ctxt,
9629 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9630 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009631 }
9632 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009633 xmlSchemaPIllegalAttrErr(ctxt,
9634 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9635 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009636 }
9637 attr = attr->next;
9638 }
9639
William M. Brack2f2a6632004-08-20 23:09:47 +00009640 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009641
William M. Brack2f2a6632004-08-20 23:09:47 +00009642 /*
9643 * Extract and validate attributes.
9644 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009645 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009646 /*
9647 * And now for the children...
9648 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009649 child = node->children;
9650 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009651 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009652 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009653 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009654 oldcontainer = ctxt->container;
9655 ctxt->container = container;
9656 if (type == XML_SCHEMA_TYPE_ALL) {
9657 xmlSchemaParticlePtr part, last = NULL;
9658
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009659 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009660 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
9661 schema, child, 0);
9662 if (part != NULL) {
9663 if (part->minOccurs > 1)
9664 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MINOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009665 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009666 "Invalid value for minOccurs (must be 0 or 1)", NULL);
9667 if (part->maxOccurs > 1)
9668 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MAXOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009669 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009670 "Invalid value for maxOccurs (must be 0 or 1)",
9671 NULL);
9672 if (last == NULL)
9673 item->children = (xmlSchemaTreeItemPtr) part;
9674 else
9675 last->next = (xmlSchemaTreeItemPtr) part;
9676 last = part;
9677 }
9678 child = child->next;
9679 }
9680 if (child != NULL) {
9681 xmlSchemaPContentErr(ctxt,
9682 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9683 NULL, NULL, node, child, NULL,
9684 "(annotation?, (annotation?, element*)");
9685 }
9686 } else {
9687 /* choice + sequence */
9688 xmlSchemaTreeItemPtr part = NULL, last = NULL;
9689
9690 while ((IS_SCHEMA(child, "element")) ||
9691 (IS_SCHEMA(child, "group")) ||
9692 (IS_SCHEMA(child, "any")) ||
9693 (IS_SCHEMA(child, "choice")) ||
9694 (IS_SCHEMA(child, "sequence"))) {
9695
9696 if (IS_SCHEMA(child, "element")) {
9697 part = (xmlSchemaTreeItemPtr)
9698 xmlSchemaParseElement(ctxt, schema, child, 0);
9699 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009700 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009701 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9702 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009703 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009704 xmlSchemaParseAny(ctxt, schema, child);
9705 } else if (IS_SCHEMA(child, "choice")) {
9706 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9707 XML_SCHEMA_TYPE_CHOICE, 1);
9708 } else if (IS_SCHEMA(child, "sequence")) {
9709 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9710 XML_SCHEMA_TYPE_SEQUENCE, 1);
9711 }
9712 if (part != NULL) {
9713 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009714 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009715 else
9716 last->next = part;
9717 last = part;
9718 }
9719 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009720 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009721 if (child != NULL) {
9722 xmlSchemaPContentErr(ctxt,
9723 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9724 NULL, NULL, node, child, NULL,
9725 "(annotation?, (element | group | choice | sequence | any)*)");
9726 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009727 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009728 ctxt->container = oldcontainer;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009729 if (withParticle) {
9730 if ((min == 0) && (max == 0))
9731 return (NULL);
9732 else
9733 return ((xmlSchemaTreeItemPtr) particle);
9734 } else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009735 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009736}
9737
9738/**
9739 * xmlSchemaParseRestriction:
9740 * @ctxt: a schema validation context
9741 * @schema: the schema being built
9742 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00009743 *
9744 * parse a XML schema Restriction definition
9745 * *WARNING* this interface is highly subject to change
9746 *
9747 * Returns the type definition or NULL in case of error
9748 */
9749static xmlSchemaTypePtr
9750xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009751 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00009752{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009753 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009754 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009755 char buf[30];
9756 const xmlChar *oldcontainer, *container;
William M. Brack2f2a6632004-08-20 23:09:47 +00009757 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009758
9759 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9760 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009761 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009762 type = ctxt->ctxtType;
9763 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009764
9765 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009766 * TODO: Is the container needed at all? the anonymous
9767 * items inside should generate unique names already.
9768 */
9769 snprintf(buf, 29, "#restr%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009770 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009771 /*
9772 * Check for illegal attributes.
9773 */
9774 attr = node->properties;
9775 while (attr != NULL) {
9776 if (attr->ns == NULL) {
9777 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9778 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009779 xmlSchemaPIllegalAttrErr(ctxt,
9780 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9781 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009782 }
9783 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009784 xmlSchemaPIllegalAttrErr(ctxt,
9785 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9786 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009787 }
9788 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009789 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009790 /*
9791 * Extract and validate attributes.
9792 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009793 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009794 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009795 * Attribute "base" - mandatory if inside a complex type.
William M. Brack2f2a6632004-08-20 23:09:47 +00009796 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009797 /*
9798 * SPEC (1.2) "otherwise (<restriction> has no <simpleType> "
9799 * among its [children]), the simple type definition which is
9800 * the {content type} of the type definition ·resolved· to by
9801 * the ·actual value· of the base [attribute]"
9802 */
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009803 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009804 NULL, NULL, node, "base",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009805 &(type->baseNs), &(type->base)) == 0) &&
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009806 (type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009807 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009808 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009809 XML_SCHEMAP_S4S_ATTR_MISSING,
9810 type, node, "base", NULL);
9811 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009812 /*
9813 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009814 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009815 child = node->children;
9816 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009817 /*
9818 * Add the annotation to the simple type ancestor.
9819 */
9820 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9821 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009822 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009823 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009824 oldcontainer = ctxt->container;
9825 ctxt->container = container;
9826 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
9827 /*
9828 * Corresponds to <simpleType><restriction><simpleType>.
9829 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009830 if (IS_SCHEMA(child, "simpleType")) {
9831 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009832 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009833 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009834 * Either the base [attribute] or the simpleType [child] of the
9835 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +00009836 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009837 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009838 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009839 NULL, NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +00009840 "The attribute 'base' and the <simpleType> child are "
9841 "mutually exclusive", NULL);
9842 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009843 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +00009844 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009845 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009846 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009847 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009848 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009849 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
9850 NULL, NULL, node, child,
9851 "Either the attribute 'base' or a <simpleType> child "
9852 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009853 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009854 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9855 /*
9856 * Corresponds to <complexType><complexContent><restriction>...
9857 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009858 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009859 * Model groups <all>, <choice> and <sequence>.
9860 */
9861 if (IS_SCHEMA(child, "all")) {
9862 type->subtypes = (xmlSchemaTypePtr)
9863 xmlSchemaParseModelGroup(ctxt, schema, child,
9864 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009865 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009866 } else if (IS_SCHEMA(child, "choice")) {
9867 type->subtypes = (xmlSchemaTypePtr)
9868 xmlSchemaParseModelGroup(ctxt,
9869 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
9870 child = child->next;
9871 } else if (IS_SCHEMA(child, "sequence")) {
9872 type->subtypes = (xmlSchemaTypePtr)
9873 xmlSchemaParseModelGroup(ctxt, schema, child,
9874 XML_SCHEMA_TYPE_SEQUENCE, 1);
9875 child = child->next;
9876 /*
9877 * Model group reference <group>.
9878 */
9879 } else if (IS_SCHEMA(child, "group")) {
9880 type->subtypes = (xmlSchemaTypePtr)
9881 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9882 child = child->next;
9883 }
9884 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009885 /*
9886 * Corresponds to <complexType><simpleContent><restriction>...
9887 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009888 * "1.1 the simple type definition corresponding to the <simpleType>
9889 * among the [children] of <restriction> if there is one;"
9890 */
9891 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009892 /*
9893 * We will store the to-be-restricted simple type in
9894 * type->contentTypeDef *temporarily*.
9895 */
9896 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009897 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009898 if ( type->contentTypeDef == NULL)
9899 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009900 child = child->next;
9901 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009902 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009903
9904 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009905 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009906 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009907 /*
9908 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009909 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009910 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009911
Daniel Veillard01fa6152004-06-29 17:04:39 +00009912 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009913 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009914 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009915 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009916 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
9917 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009918 * *Single Facet Value*
9919 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009920 while ((IS_SCHEMA(child, "minInclusive")) ||
9921 (IS_SCHEMA(child, "minExclusive")) ||
9922 (IS_SCHEMA(child, "maxInclusive")) ||
9923 (IS_SCHEMA(child, "maxExclusive")) ||
9924 (IS_SCHEMA(child, "totalDigits")) ||
9925 (IS_SCHEMA(child, "fractionDigits")) ||
9926 (IS_SCHEMA(child, "pattern")) ||
9927 (IS_SCHEMA(child, "enumeration")) ||
9928 (IS_SCHEMA(child, "whiteSpace")) ||
9929 (IS_SCHEMA(child, "length")) ||
9930 (IS_SCHEMA(child, "maxLength")) ||
9931 (IS_SCHEMA(child, "minLength"))) {
9932 facet = xmlSchemaParseFacet(ctxt, schema, child);
9933 if (facet != NULL) {
9934 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009935 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009936 else
9937 lastfacet->next = facet;
9938 lastfacet = facet;
9939 lastfacet->next = NULL;
9940 }
9941 child = child->next;
9942 }
9943 /*
9944 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009945 */
9946 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009947 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
9948
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009949 facet = type->facets;
9950 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009951 facetLink = (xmlSchemaFacetLinkPtr)
9952 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +00009953 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009954 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009955 xmlFree(facetLink);
9956 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009957 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009958 facetLink->facet = facet;
9959 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009960 if (lastFacetLink == NULL)
9961 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009962 else
9963 lastFacetLink->next = facetLink;
9964 lastFacetLink = facetLink;
9965 facet = facet->next;
9966 } while (facet != NULL);
9967 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009968 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009969 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
9970 /*
9971 * Attribute uses/declarations.
9972 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009973 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009974 /*
9975 * Attribute wildcard.
9976 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009977 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009978 type->attributeWildcard =
9979 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009980 child = child->next;
9981 }
9982 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009983 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009984 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9985 xmlSchemaPContentErr(ctxt,
9986 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009987 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009988 "annotation?, (group | all | choice | sequence)?, "
9989 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009990 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009991 xmlSchemaPContentErr(ctxt,
9992 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009993 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009994 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
9995 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
9996 "length | minLength | maxLength | enumeration | whiteSpace | "
9997 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
9998 } else {
9999 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010000 xmlSchemaPContentErr(ctxt,
10001 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010002 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010003 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10004 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10005 "length | minLength | maxLength | enumeration | whiteSpace | "
10006 "pattern)*))");
10007 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010008 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010009 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010010 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010011}
10012
10013/**
10014 * xmlSchemaParseExtension:
10015 * @ctxt: a schema validation context
10016 * @schema: the schema being built
10017 * @node: a subtree containing XML Schema informations
10018 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010019 * Parses an <extension>, which is found inside a
10020 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010021 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000010022 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010023 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000010024 */
10025static xmlSchemaTypePtr
10026xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010027 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000010028{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010029 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010030 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010031 char buf[30];
10032 const xmlChar *oldcontainer, *container;
10033 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010034
10035 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10036 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010037 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010038 type = ctxt->ctxtType;
10039 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000010040
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010041 snprintf(buf, 29, "#ext%d", ctxt->counter++ + 1);
10042 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
10043 /*
10044 * Check for illegal attributes.
10045 */
10046 attr = node->properties;
10047 while (attr != NULL) {
10048 if (attr->ns == NULL) {
10049 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10050 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010051 xmlSchemaPIllegalAttrErr(ctxt,
10052 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10053 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010054 }
10055 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010056 xmlSchemaPIllegalAttrErr(ctxt,
10057 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10058 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010059 }
10060 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010061 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010062
10063 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010064
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010065 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010066 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010067 */
10068 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010069 NULL, NULL, node, "base", &(type->baseNs), &(type->base)) == 0) &&
10070 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010071 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010072 XML_SCHEMAP_S4S_ATTR_MISSING,
10073 NULL, node, "base", NULL);
10074 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010075 /*
10076 * And now for the children...
10077 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010078 child = node->children;
10079 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010080 /*
10081 * Add the annotation to the type ancestor.
10082 */
10083 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10084 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010085 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010086 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010087 oldcontainer = ctxt->container;
10088 ctxt->container = container;
10089 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10090 /*
10091 * Corresponds to <complexType><complexContent><extension>... and:
10092 *
10093 * Model groups <all>, <choice>, <sequence> and <group>.
10094 */
10095 if (IS_SCHEMA(child, "all")) {
10096 type->subtypes = (xmlSchemaTypePtr)
10097 xmlSchemaParseModelGroup(ctxt, schema,
10098 child, XML_SCHEMA_TYPE_ALL, 1);
10099 child = child->next;
10100 } else if (IS_SCHEMA(child, "choice")) {
10101 type->subtypes = (xmlSchemaTypePtr)
10102 xmlSchemaParseModelGroup(ctxt, schema,
10103 child, XML_SCHEMA_TYPE_CHOICE, 1);
10104 child = child->next;
10105 } else if (IS_SCHEMA(child, "sequence")) {
10106 type->subtypes = (xmlSchemaTypePtr)
10107 xmlSchemaParseModelGroup(ctxt, schema,
10108 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
10109 child = child->next;
10110 } else if (IS_SCHEMA(child, "group")) {
10111 type->subtypes = (xmlSchemaTypePtr)
10112 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
10113 child = child->next;
10114 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010115 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010116 if (child != NULL) {
10117 /*
10118 * Attribute uses/declarations.
10119 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010120 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010121 /*
10122 * Attribute wildcard.
10123 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010124 if (IS_SCHEMA(child, "anyAttribute")) {
10125 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010126 xmlSchemaParseAnyAttribute(ctxt, schema, child);
10127 child = child->next;
10128 }
10129 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010130 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010131 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10132 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010133 xmlSchemaPContentErr(ctxt,
10134 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010135 NULL, NULL, node, child, NULL,
10136 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010137 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010138 } else {
10139 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010140 xmlSchemaPContentErr(ctxt,
10141 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010142 NULL, NULL, node, child, NULL,
10143 "(annotation?, ((attribute | attributeGroup)*, "
10144 "anyAttribute?))");
10145 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010146 }
10147 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010148 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010149}
10150
10151/**
10152 * xmlSchemaParseSimpleContent:
10153 * @ctxt: a schema validation context
10154 * @schema: the schema being built
10155 * @node: a subtree containing XML Schema informations
10156 *
10157 * parse a XML schema SimpleContent definition
10158 * *WARNING* this interface is highly subject to change
10159 *
10160 * Returns the type definition or NULL in case of error
10161 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010162static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010163xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
10164 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010165{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010166 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010167 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010168 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010169
10170 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010171 return (-1);
10172 /* Not a component, don't create it. */
10173 type = ctxt->ctxtType;
10174 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
10175 /*
10176 * Check for illegal attributes.
10177 */
10178 attr = node->properties;
10179 while (attr != NULL) {
10180 if (attr->ns == NULL) {
10181 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010182 xmlSchemaPIllegalAttrErr(ctxt,
10183 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10184 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010185 }
10186 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010187 xmlSchemaPIllegalAttrErr(ctxt,
10188 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10189 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010190 }
10191 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010192 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010193
10194 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000010195
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010196 /*
10197 * And now for the children...
10198 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010199 child = node->children;
10200 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010201 /*
10202 * Add the annotation to the complex type ancestor.
10203 */
10204 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10205 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010206 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010207 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010208 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010209 xmlSchemaParseRestriction(ctxt, schema, child,
10210 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010211 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010212 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010213 xmlSchemaParseExtension(ctxt, schema, child,
10214 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010215 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010216 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010217 if (child != NULL) {
10218 xmlSchemaPContentErr(ctxt,
10219 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010220 NULL, NULL, node, child, NULL,
10221 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010222 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010223 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010224}
10225
10226/**
10227 * xmlSchemaParseComplexContent:
10228 * @ctxt: a schema validation context
10229 * @schema: the schema being built
10230 * @node: a subtree containing XML Schema informations
10231 *
10232 * parse a XML schema ComplexContent definition
10233 * *WARNING* this interface is highly subject to change
10234 *
10235 * Returns the type definition or NULL in case of error
10236 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010237static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010238xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
10239 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010240{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010241 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010242 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010243 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010244
10245 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010246 return (-1);
10247 /* Not a component, don't create it. */
10248 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010249 /*
10250 * Check for illegal attributes.
10251 */
10252 attr = node->properties;
10253 while (attr != NULL) {
10254 if (attr->ns == NULL) {
10255 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010256 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010257 {
10258 xmlSchemaPIllegalAttrErr(ctxt,
10259 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10260 NULL, NULL, attr);
10261 }
10262 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10263 xmlSchemaPIllegalAttrErr(ctxt,
10264 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10265 NULL, NULL, attr);
10266 }
10267 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010268 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010269
10270 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
10271
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010272 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010273 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010274 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010275 if (xmlGetBooleanProp(ctxt, NULL, NULL, node, "mixed", 0)) {
10276 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
10277 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010278 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010279 child = node->children;
10280 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010281 /*
10282 * Add the annotation to the complex type ancestor.
10283 */
10284 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10285 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010286 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010287 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010288 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010289 xmlSchemaParseRestriction(ctxt, schema, child,
10290 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010291 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010292 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010293 xmlSchemaParseExtension(ctxt, schema, child,
10294 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010295 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010296 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010297 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010298 xmlSchemaPContentErr(ctxt,
10299 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10300 NULL, NULL, node, child,
10301 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010302 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010303 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010304}
10305
10306/**
10307 * xmlSchemaParseComplexType:
10308 * @ctxt: a schema validation context
10309 * @schema: the schema being built
10310 * @node: a subtree containing XML Schema informations
10311 *
10312 * parse a XML schema Complex Type definition
10313 * *WARNING* this interface is highly subject to change
10314 *
10315 * Returns the type definition or NULL in case of error
10316 */
10317static xmlSchemaTypePtr
10318xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000010319 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000010320{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010321 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010322 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010323 const xmlChar *oldcontainer, *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010324 xmlAttrPtr attr;
10325 const xmlChar *attrValue;
10326 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +000010327 char buf[40];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010328 int final = 0, block = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000010329
Daniel Veillard4255d502002-04-16 15:50:10 +000010330
10331 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10332 return (NULL);
10333
Daniel Veillard01fa6152004-06-29 17:04:39 +000010334 ctxtType = ctxt->ctxtType;
10335
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010336 if (topLevel) {
10337 attr = xmlSchemaGetPropNode(node, "name");
10338 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010339 xmlSchemaPMissingAttrErr(ctxt,
10340 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010341 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010342 } else if (xmlSchemaPValAttrNode(ctxt,
10343 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010344 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
10345 return (NULL);
10346 }
10347 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010348
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010349 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010350 /*
10351 * Parse as local complex type definition.
10352 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000010353 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010354 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
10355 if (type == NULL)
10356 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010357 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010358 type->node = node;
10359 type->type = XML_SCHEMA_TYPE_COMPLEX;
10360 /*
10361 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010362 */
10363 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010364 /*
10365 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010366 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010367 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010368 if (type == NULL)
10369 return (NULL);
10370 type->node = node;
10371 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010372 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000010373 }
10374 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010375 /*
10376 * Handle attributes.
10377 */
10378 attr = node->properties;
10379 while (attr != NULL) {
10380 if (attr->ns == NULL) {
10381 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
10382 /*
10383 * Attribute "id".
10384 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010385 xmlSchemaPValAttrID(ctxt, NULL, type, node,
10386 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010387 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
10388 /*
10389 * Attribute "mixed".
10390 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010391 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010392 (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010393 type->flags |= XML_SCHEMAS_TYPE_MIXED;
10394 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010395 /*
10396 * Attributes of global complex type definitions.
10397 */
10398 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
10399 /* Pass. */
10400 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
10401 /*
10402 * Attribute "abstract".
10403 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010404 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
10405 (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010406 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
10407 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
10408 /*
10409 * Attribute "final".
10410 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010411 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010412 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010413 if (xmlSchemaPValAttrBlockFinal(attrValue,
10414 &(type->flags),
10415 -1,
10416 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
10417 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
10418 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010419 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010420 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010421 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010422 type, (xmlNodePtr) attr, NULL,
10423 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010424 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010425 } else
10426 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010427 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
10428 /*
10429 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010430 */
10431 attrValue = xmlSchemaGetNodeContent(ctxt,
10432 (xmlNodePtr) attr);
10433 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010434 -1,
10435 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010436 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010437 -1, -1, -1) != 0) {
10438 xmlSchemaPSimpleTypeErr(ctxt,
10439 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010440 type, (xmlNodePtr) attr, NULL,
10441 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010442 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010443 } else
10444 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010445 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010446 xmlSchemaPIllegalAttrErr(ctxt,
10447 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010448 &des, type, attr);
10449 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010450 } else {
10451 xmlSchemaPIllegalAttrErr(ctxt,
10452 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010453 &des, type, attr);
10454 }
10455 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010456 xmlSchemaPIllegalAttrErr(ctxt,
10457 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10458 &des, type, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010459 }
10460 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010461 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010462 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000010463 /*
10464 * Apply default "block" values.
10465 */
10466 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
10467 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
10468 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
10469 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
10470 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010471 if (! final) {
10472 /*
10473 * Apply default "block" values.
10474 */
10475 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
10476 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
10477 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
10478 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
10479 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010480 /*
10481 * And now for the children...
10482 */
10483 oldcontainer = ctxt->container;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010484 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +000010485 child = node->children;
10486 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010487 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
10488 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010489 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010490 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010491 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010492 /*
10493 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010494 * Specifying mixed='true' when the <simpleContent>
10495 * alternative is chosen has no effect
10496 */
William M. Bracke7091952004-05-11 15:09:58 +000010497 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
10498 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010499 xmlSchemaParseSimpleContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010500 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010501 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010502 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
10503 xmlSchemaParseComplexContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010504 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010505 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010506 /*
10507 * SPEC
10508 * "...the third alternative (neither <simpleContent> nor
10509 * <complexContent>) is chosen. This case is understood as shorthand
10510 * for complex content restricting the ·ur-type definition·, and the
10511 * details of the mappings should be modified as necessary.
10512 */
10513 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10514 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010515 /*
10516 * Parse model groups.
10517 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010518 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010519 type->subtypes = (xmlSchemaTypePtr)
10520 xmlSchemaParseModelGroup(ctxt, schema, child,
10521 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010522 child = child->next;
10523 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010524 type->subtypes = (xmlSchemaTypePtr)
10525 xmlSchemaParseModelGroup(ctxt, schema, child,
10526 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010527 child = child->next;
10528 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010529 type->subtypes = (xmlSchemaTypePtr)
10530 xmlSchemaParseModelGroup(ctxt, schema, child,
10531 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010532 child = child->next;
10533 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010534 type->subtypes = (xmlSchemaTypePtr)
10535 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010536 child = child->next;
10537 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010538 /*
10539 * Parse attribute decls/refs.
10540 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010541 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010542 /*
10543 * Parse attribute wildcard.
10544 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010545 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010546 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
10547 child = child->next;
10548 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010549 }
10550 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010551 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010552 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010553 &des, type, node, child,
10554 NULL, "(annotation?, (simpleContent | complexContent | "
10555 "((group | all | choice | sequence)?, ((attribute | "
10556 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010557 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010558 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +000010559 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010560 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010561 return (type);
10562}
10563
Daniel Veillard4255d502002-04-16 15:50:10 +000010564/**
10565 * xmlSchemaParseSchema:
10566 * @ctxt: a schema validation context
10567 * @node: a subtree containing XML Schema informations
10568 *
10569 * parse a XML schema definition from a node set
10570 * *WARNING* this interface is highly subject to change
10571 *
10572 * Returns the internal XML Schema structure built from the resource or
10573 * NULL in case of error
10574 */
10575static xmlSchemaPtr
10576xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
10577{
10578 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010579 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010580 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010581 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010582
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010583 /*
10584 * This one is called by xmlSchemaParse only and is used if
10585 * the schema to be parsed was specified via the API; i.e. not
10586 * automatically by the validated instance document.
10587 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010588 if ((ctxt == NULL) || (node == NULL))
10589 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010590 nberrors = ctxt->nberrors;
10591 ctxt->nberrors = 0;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010592 ctxt->isS4S = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010593 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010594 xmlSchemaImportPtr import;
10595
Daniel Veillard4255d502002-04-16 15:50:10 +000010596 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010597 if (schema == NULL)
10598 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010599 attr = xmlSchemaGetPropNode(node, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +000010600 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010601 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010602 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
10603 /*
10604 * TODO: Should we proceed with an invalid target namespace?
10605 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010606 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010607 if (xmlStrEqual(schema->targetNamespace, xmlSchemaNs)) {
10608 /*
10609 * We are parsing the schema for schema!
10610 */
10611 ctxt->isS4S = 1;
10612 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010613 } else {
10614 schema->targetNamespace = NULL;
10615 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010616 /*
10617 * Add the current ns name and location to the import table;
10618 * this is needed to have a consistent mechanism, regardless
10619 * if all schemata are constructed dynamically fired by the
10620 * instance or if the schema to be used was specified via
10621 * the API.
10622 */
10623 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
10624 schema->targetNamespace);
10625 if (import == NULL) {
10626 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
10627 NULL, NULL, (xmlNodePtr) ctxt->doc,
10628 "Internal error: xmlSchemaParseSchema, "
10629 "failed to add an import entry", NULL);
10630 xmlSchemaFree(schema);
10631 schema = NULL;
10632 return (NULL);
10633 }
10634 import->schemaLocation = ctxt->URL;
10635 /*
10636 * NOTE: We won't set the doc here, otherwise it will be freed
10637 * if the import struct is freed.
10638 * import->doc = ctxt->doc;
10639 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010640 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010641 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
10642 } else {
10643 xmlDocPtr doc;
10644
10645 doc = node->doc;
10646
10647 if ((doc != NULL) && (doc->URL != NULL)) {
10648 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10649 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010650 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010651 } else {
10652 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10653 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010654 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010655 }
10656 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010657 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010658 if (ctxt->nberrors != 0) {
10659 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010660 xmlSchemaFree(schema);
10661 schema = NULL;
10662 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010663 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010664 if (schema != NULL)
10665 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010666 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +000010667#ifdef DEBUG
10668 if (schema == NULL)
10669 xmlGenericError(xmlGenericErrorContext,
10670 "xmlSchemaParse() failed\n");
10671#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000010672 return (schema);
10673}
10674
10675/************************************************************************
10676 * *
10677 * Validating using Schemas *
10678 * *
10679 ************************************************************************/
10680
10681/************************************************************************
10682 * *
10683 * Reading/Writing Schemas *
10684 * *
10685 ************************************************************************/
10686
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010687#if 0 /* Will be enabled if it is clear what options are needed. */
10688/**
10689 * xmlSchemaParserCtxtSetOptions:
10690 * @ctxt: a schema parser context
10691 * @options: a combination of xmlSchemaParserOption
10692 *
10693 * Sets the options to be used during the parse.
10694 *
10695 * Returns 0 in case of success, -1 in case of an
10696 * API error.
10697 */
10698static int
10699xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
10700 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010701
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010702{
10703 int i;
10704
10705 if (ctxt == NULL)
10706 return (-1);
10707 /*
10708 * WARNING: Change the start value if adding to the
10709 * xmlSchemaParseOption.
10710 */
10711 for (i = 1; i < (int) sizeof(int) * 8; i++) {
10712 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010713 return (-1);
10714 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010715 }
10716 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010717 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010718}
10719
10720/**
10721 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010722 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010723 *
10724 * Returns the option combination of the parser context.
10725 */
10726static int
10727xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010728
10729{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010730 if (ctxt == NULL)
10731 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010732 else
10733 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010734}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010735#endif
10736
Daniel Veillard4255d502002-04-16 15:50:10 +000010737/**
10738 * xmlSchemaNewParserCtxt:
10739 * @URL: the location of the schema
10740 *
10741 * Create an XML Schemas parse context for that file/resource expected
10742 * to contain an XML Schemas file.
10743 *
10744 * Returns the parser context or NULL in case of error
10745 */
10746xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010747xmlSchemaNewParserCtxt(const char *URL)
10748{
Daniel Veillard4255d502002-04-16 15:50:10 +000010749 xmlSchemaParserCtxtPtr ret;
10750
10751 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010752 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010753
10754 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10755 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010756 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010757 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010758 return (NULL);
10759 }
10760 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010761 ret->type = XML_SCHEMA_CTXT_PARSER;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010762 ret->dict = xmlDictCreate();
10763 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010764 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010765 return (ret);
10766}
10767
10768/**
Daniel Veillard6045c902002-10-09 21:13:59 +000010769 * xmlSchemaNewMemParserCtxt:
10770 * @buffer: a pointer to a char array containing the schemas
10771 * @size: the size of the array
10772 *
10773 * Create an XML Schemas parse context for that memory buffer expected
10774 * to contain an XML Schemas file.
10775 *
10776 * Returns the parser context or NULL in case of error
10777 */
10778xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010779xmlSchemaNewMemParserCtxt(const char *buffer, int size)
10780{
Daniel Veillard6045c902002-10-09 21:13:59 +000010781 xmlSchemaParserCtxtPtr ret;
10782
10783 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010784 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010785
10786 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10787 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010788 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010789 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010790 return (NULL);
10791 }
10792 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10793 ret->buffer = buffer;
10794 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010795 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000010796 return (ret);
10797}
10798
10799/**
Daniel Veillard9d751502003-10-29 13:21:47 +000010800 * xmlSchemaNewDocParserCtxt:
10801 * @doc: a preparsed document tree
10802 *
10803 * Create an XML Schemas parse context for that document.
10804 * NB. The document may be modified during the parsing process.
10805 *
10806 * Returns the parser context or NULL in case of error
10807 */
10808xmlSchemaParserCtxtPtr
10809xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
10810{
10811 xmlSchemaParserCtxtPtr ret;
10812
10813 if (doc == NULL)
10814 return (NULL);
10815
10816 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10817 if (ret == NULL) {
10818 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10819 NULL);
10820 return (NULL);
10821 }
10822 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10823 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010824 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000010825 /* The application has responsibility for the document */
10826 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000010827
10828 return (ret);
10829}
10830
10831/**
Daniel Veillard4255d502002-04-16 15:50:10 +000010832 * xmlSchemaFreeParserCtxt:
10833 * @ctxt: the schema parser context
10834 *
10835 * Free the resources associated to the schema parser context
10836 */
10837void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010838xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
10839{
Daniel Veillard4255d502002-04-16 15:50:10 +000010840 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010841 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000010842 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010843 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010844 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010845 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010846 xmlFree(ctxt->assemble);
10847 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010848 if (ctxt->vctxt != NULL) {
10849 xmlSchemaFreeValidCtxt(ctxt->vctxt);
10850 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010851 if (ctxt->localImports != NULL)
10852 xmlFree((xmlChar *) ctxt->localImports);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010853 if (ctxt->substGroups != NULL)
10854 xmlHashFree(ctxt->substGroups,
10855 (xmlHashDeallocator) xmlSchemaFreeSubstGroup);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010856 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000010857 xmlFree(ctxt);
10858}
10859
10860/************************************************************************
10861 * *
10862 * Building the content models *
10863 * *
10864 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010865
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010866static void
10867xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010868 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010869{
10870 xmlAutomataStatePtr start;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010871 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010872 xmlAutomataStatePtr end;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010873 xmlSchemaSubstGroupPtr substGroup;
10874 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010875
10876 elemDecl = (xmlSchemaElementPtr) particle->children;
10877 /*
10878 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010879 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010880 start = pctxt->state;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010881 end = xmlAutomataNewState(pctxt->am);
10882 substGroup = xmlSchemaGetElementSubstitutionGroup(pctxt, elemDecl);
10883 if (substGroup == NULL) {
10884 xmlSchemaPErr(pctxt, GET_NODE(particle),
10885 XML_SCHEMAP_INTERNAL,
10886 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
10887 "declaration is marked having a subst. group but none "
10888 "available.\n", elemDecl->name, NULL);
10889 return;
10890 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010891 if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010892 /*
10893 * NOTE that we put the declaration in, even if it's abstract,
10894 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010895 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010896 xmlAutomataNewTransition2(pctxt->am,
10897 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010898 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
10899 /*
10900 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010901 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010902 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010903 member = (xmlSchemaElementPtr) substGroup->members->items[i];
10904 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010905 xmlAutomataNewTransition2(pctxt->am,
10906 start, NULL,
10907 member->name, member->targetNamespace, member),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010908 end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010909 }
10910 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010911 int counter;
10912 xmlAutomataStatePtr hop;
10913 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
10914 UNBOUNDED : particle->maxOccurs - 1;
10915 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
10916
10917 counter =
10918 xmlAutomataNewCounter(pctxt->am, minOccurs,
10919 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010920 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010921
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010922 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010923 xmlAutomataNewTransition2(pctxt->am,
10924 start, NULL,
10925 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010926 hop);
10927 /*
10928 * Add subst. group members.
10929 */
10930 for (i = 0; i < substGroup->members->nbItems; i++) {
10931 member = (xmlSchemaElementPtr) substGroup->members->items[i];
10932 xmlAutomataNewEpsilon(pctxt->am,
10933 xmlAutomataNewTransition2(pctxt->am,
10934 start, NULL,
10935 member->name, member->targetNamespace, member),
10936 hop);
10937 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010938 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
10939 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
10940 }
10941 if (particle->minOccurs == 0)
10942 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010943 pctxt->state = end;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010944}
10945
10946static void
10947xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
10948 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010949{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010950 if (((xmlSchemaElementPtr) particle->children)->flags &
10951 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010952 /*
10953 * Substitution groups.
10954 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010955 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010956 } else {
10957 xmlSchemaElementPtr elemDecl;
10958 xmlAutomataStatePtr start;
10959
10960 elemDecl = (xmlSchemaElementPtr) particle->children;
10961
10962 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010963 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010964 if (particle->maxOccurs == 1) {
10965 start = ctxt->state;
10966 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
10967 elemDecl->name, elemDecl->targetNamespace, elemDecl);
10968 } else if ((particle->maxOccurs >= UNBOUNDED) && (particle->minOccurs < 2)) {
10969 /* Special case. */
10970 start = ctxt->state;
10971 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
10972 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010973 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, start);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010974 } else {
10975 int counter;
10976 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
10977 UNBOUNDED : particle->maxOccurs - 1;
10978 int minOccurs = particle->minOccurs < 1 ?
10979 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010980
10981 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010982 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
10983 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
10984 elemDecl->name, elemDecl->targetNamespace, elemDecl);
10985 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
10986 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
10987 NULL, counter);
10988 }
10989 if (particle->minOccurs == 0)
10990 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
10991 }
10992}
10993
Daniel Veillard4255d502002-04-16 15:50:10 +000010994/**
10995 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000010996 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010997 * @particle: the particle component
10998 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000010999 *
11000 * Generate the automata sequence needed for that type
11001 */
11002static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011003xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011004 xmlSchemaParticlePtr particle,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011005 const xmlChar * name)
11006{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011007 if (particle == NULL) {
11008 xmlSchemaPErr(ctxt, NULL,
11009 XML_SCHEMAP_INTERNAL,
11010 "Internal error: xmlSchemaBuildAContentModel, "
11011 "particle is NULL.\n", NULL, NULL);
11012 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011013 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011014 if (particle->children == NULL) {
11015 xmlSchemaPErr(ctxt, GET_NODE(particle),
11016 XML_SCHEMAP_INTERNAL,
11017 "Internal error: xmlSchemaBuildAContentModel, "
11018 "no term on particle.\n", NULL, NULL);
11019 return;
11020 }
11021
11022 switch (particle->children->type) {
11023 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011024 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011025 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011026 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000011027
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011028 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011029
Daniel Veillardc0826a72004-08-10 14:17:33 +000011030 start = ctxt->state;
11031 end = xmlAutomataNewState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011032
11033 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011034 if (wild->any == 1) {
11035 /*
11036 * We need to add both transitions:
11037 *
11038 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011039 */
11040 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011041 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011042 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011043 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11044 /*
11045 * 2. the {"*"} for elements in no namespace.
11046 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011047 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011048 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011049 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011050 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11051
11052 } else if (wild->nsSet != NULL) {
11053 ns = wild->nsSet;
11054 do {
11055 ctxt->state = start;
11056 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011057 ctxt->state, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011058 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11059 ns = ns->next;
11060 } while (ns != NULL);
11061
11062 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011063
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011064 /*
11065 * Lead nodes with the negated namespace to the sink-state
11066 * {"*", "##other"}.
11067 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011068 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011069 BAD_CAST "*", wild->negNsSet->value, wild);
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011070 /*
11071 * Open a door for nodes with any other namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011072 * {"*", "*"}
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011073 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011074 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011075 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011076 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011077 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011078 } else {
11079 int counter;
11080 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011081 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011082 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011083 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011084 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011085
Daniel Veillardc0826a72004-08-10 14:17:33 +000011086 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011087 hop = xmlAutomataNewState(ctxt->am);
11088 if (wild->any == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011089 ctxt->state =
11090 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011091 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011092 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011093 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011094 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011095 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011096 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011097 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011098 ns = wild->nsSet;
11099 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011100 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011101 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011102 start, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011103 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
11104 ns = ns->next;
11105 } while (ns != NULL);
11106
11107 } else if (wild->negNsSet != NULL) {
11108 xmlAutomataStatePtr deadEnd;
11109
11110 deadEnd = xmlAutomataNewState(ctxt->am);
11111 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011112 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011113 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011114 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011115 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011116 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011117 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
11118 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
11119 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011120 if (particle->minOccurs == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011121 xmlAutomataNewEpsilon(ctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011122 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011123 ctxt->state = end;
11124 break;
11125 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011126 case XML_SCHEMA_TYPE_ELEMENT:
11127 xmlSchemaBuildContentModelForElement(ctxt, particle);
11128 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011129 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011130 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011131
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011132 /*
11133 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011134 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011135 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011136 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
11137 sub = particle->children->children;
11138 while (sub != NULL) {
11139 xmlSchemaBuildAContentModel(ctxt,
11140 (xmlSchemaParticlePtr) sub, name);
11141 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011142 }
11143 } else {
11144 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011145
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011146 if (particle->maxOccurs >= UNBOUNDED) {
11147 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011148 xmlAutomataStatePtr tmp;
11149 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011150
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011151 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011152 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011153 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011154
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011155 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011156 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011157
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011158 sub = particle->children->children;
11159 while (sub != NULL) {
11160 xmlSchemaBuildAContentModel(ctxt,
11161 (xmlSchemaParticlePtr) sub, name);
11162 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011163 }
11164 tmp = ctxt->state;
11165 xmlAutomataNewCountedTrans(ctxt->am, tmp,
11166 oldstate, counter);
11167 ctxt->state =
11168 xmlAutomataNewCounterTrans(ctxt->am, tmp,
11169 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011170
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011171 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011172 sub = particle->children->children;
11173 while (sub != NULL) {
11174 xmlSchemaBuildAContentModel(ctxt,
11175 (xmlSchemaParticlePtr) sub, name);
11176 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011177 }
11178 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
11179 oldstate);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011180 if (particle->minOccurs == 0) {
11181 xmlAutomataNewEpsilon(ctxt->am,
11182 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011183 }
11184 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011185 } else if ((particle->maxOccurs > 1)
11186 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011187 xmlAutomataStatePtr tmp;
11188 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011189
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011190 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011191 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011192 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000011193
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011194 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011195 particle->minOccurs - 1,
11196 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011197
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011198 sub = particle->children->children;
11199 while (sub != NULL) {
11200 xmlSchemaBuildAContentModel(ctxt,
11201 (xmlSchemaParticlePtr) sub, name);
11202 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011203 }
11204 tmp = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011205 xmlAutomataNewCountedTrans(ctxt->am,
11206 tmp, oldstate, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011207 ctxt->state =
11208 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
11209 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011210 if (particle->minOccurs == 0) {
11211 xmlAutomataNewEpsilon(ctxt->am,
11212 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011213 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011214 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011215 sub = particle->children->children;
11216 while (sub != NULL) {
11217 xmlSchemaBuildAContentModel(ctxt,
11218 (xmlSchemaParticlePtr) sub, name);
11219 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011220 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011221 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011222 xmlAutomataNewEpsilon(ctxt->am, oldstate,
11223 ctxt->state);
11224 }
11225 }
11226 }
11227 break;
11228 }
11229 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011230 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011231 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000011232
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011233 start = ctxt->state;
11234 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000011235
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011236 /*
11237 * iterate over the subtypes and remerge the end with an
11238 * epsilon transition
11239 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011240 if (particle->maxOccurs == 1) {
11241 sub = particle->children->children;
11242 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011243 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011244 xmlSchemaBuildAContentModel(ctxt,
11245 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011246 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011247 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011248 }
11249 } else {
11250 int counter;
11251 xmlAutomataStatePtr hop;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011252 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11253 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011254 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011255 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000011256
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011257 /*
11258 * use a counter to keep track of the number of transtions
11259 * which went through the choice.
11260 */
11261 counter =
11262 xmlAutomataNewCounter(ctxt->am, minOccurs,
11263 maxOccurs);
11264 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000011265
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011266 sub = particle->children->children;
11267 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011268 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011269 xmlSchemaBuildAContentModel(ctxt,
11270 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011271 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011272 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011273 }
11274 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
11275 counter);
11276 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
11277 counter);
11278 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011279 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011280 xmlAutomataNewEpsilon(ctxt->am, start, end);
11281 }
11282 ctxt->state = end;
11283 break;
11284 }
11285 case XML_SCHEMA_TYPE_ALL:{
11286 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011287 xmlSchemaParticlePtr sub;
11288 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011289 int lax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011290
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011291 sub = (xmlSchemaParticlePtr) particle->children->children;
11292 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011293 break;
11294 start = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011295 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011296 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011297
11298 elemDecl = (xmlSchemaElementPtr) sub->children;
11299 if (elemDecl == NULL) {
11300 xmlSchemaPErr(ctxt, NULL,
11301 XML_SCHEMAP_INTERNAL,
11302 "Internal error: xmlSchemaBuildAContentModel, "
11303 "<element> particle a NULL term.\n", NULL, NULL);
11304 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011305 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011306 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011307 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011308 * {particles} of the group must be 0 or 1; this is
11309 * already ensured during the parse of the content of
11310 * <all>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011311 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011312 if ((sub->minOccurs == 1) &&
11313 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011314 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011315 ctxt->state,
11316 elemDecl->name,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011317 elemDecl->targetNamespace,
11318 1, 1, elemDecl);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011319 } else if ((sub->minOccurs == 0) &&
11320 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011321
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011322 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011323 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011324 elemDecl->name,
11325 elemDecl->targetNamespace,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011326 0,
11327 1,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011328 elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011329 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011330 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011331 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011332 lax = particle->minOccurs == 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011333 ctxt->state =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011334 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011335 break;
11336 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011337 default:
11338 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011339 "Internal error: xmlSchemaBuildAContentModel, found "
11340 "unexpected term of type %d in content model of complex "
11341 "type '%s'.\n",
11342 particle->children->type, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011343 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011344 }
11345}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011346
Daniel Veillard4255d502002-04-16 15:50:10 +000011347/**
11348 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011349 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011350 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011351 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000011352 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011353 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000011354 */
11355static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011356xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011357 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011358 const xmlChar * name)
11359{
Daniel Veillard4255d502002-04-16 15:50:10 +000011360 xmlAutomataStatePtr start;
11361
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011362 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
11363 (type->contModel != NULL) ||
11364 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
11365 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011366 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011367
11368#ifdef DEBUG_CONTENT
11369 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011370 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011371#endif
11372
Daniel Veillard4255d502002-04-16 15:50:10 +000011373 ctxt->am = xmlNewAutomata();
11374 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011375 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011376 "Cannot create automata for complex type %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011377 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011378 }
11379 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011380 xmlSchemaBuildAContentModel(ctxt, (xmlSchemaParticlePtr) type->subtypes, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011381 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011382 type->contModel = xmlAutomataCompile(ctxt->am);
11383 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011384 xmlSchemaPCustomErr(ctxt,
11385 XML_SCHEMAP_INTERNAL,
11386 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011387 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011388 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011389 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011390 XML_SCHEMAP_NOT_DETERMINISTIC,
11391 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011392 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011393 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000011394 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000011395#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011396 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011397 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011398 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000011399#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000011400 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011401 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011402 xmlFreeAutomata(ctxt->am);
11403 ctxt->am = NULL;
11404}
11405
11406/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011407 * xmlSchemaElementFixup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011408 * @elem: the schema element context
11409 * @ctxt: the schema parser context
11410 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000011411 * Resolves the references of an element declaration
11412 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011413 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000011414 */
11415static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011416xmlSchemaElementFixup(xmlSchemaElementPtr elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011417 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011418 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011419 const xmlChar * context ATTRIBUTE_UNUSED,
11420 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000011421{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011422 if ((ctxt == NULL) || (elemDecl == NULL) ||
11423 ((elemDecl != NULL) &&
11424 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011425 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011426 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011427
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011428 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011429 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011430
11431 /* (type definition) ... otherwise the type definition ·resolved·
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011432 * to by the ·actual value· of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011433 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011434 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011435 elemDecl->namedTypeNs);
11436 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011437 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011438 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011439 (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011440 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011441 XML_SCHEMA_TYPE_BASIC, "type definition");
11442 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011443 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011444 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011445 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011446 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011447
Daniel Veillardc0826a72004-08-10 14:17:33 +000011448 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011449 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011450 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000011451 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011452 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
11453 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011454 if (substHead == NULL) {
11455 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011456 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011457 (xmlSchemaTypePtr) elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011458 "substitutionGroup", elemDecl->substGroup,
11459 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011460 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011461 xmlSchemaElementFixup(substHead, ctxt, NULL, NULL, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011462 /*
11463 * Set the "substitution group affiliation".
11464 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011465 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011466 elemDecl->refDecl = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011467 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011468 * (type definition)...otherwise the {type definition} of the
11469 * element declaration ·resolved· to by the ·actual value· of
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011470 * the substitutionGroup [attribute], if present
11471 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011472 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011473 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011474 }
11475 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011476 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType == NULL) &&
11477 (elemDecl->substGroup == NULL))
11478 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000011479}
11480
11481/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011482 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000011483 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011484 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000011485 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011486 * Checks and builds the "member type definitions" property of the union
11487 * simple type. This handles part (1), part (2) is done in
11488 * xmlSchemaFinishMemberTypeDefinitionsProperty()
11489 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000011490 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000011491 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011492static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011493xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
11494 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000011495{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011496
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011497 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011498 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000011499
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011500 /*
11501 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
11502 * define the explicit members as the type definitions ·resolved·
11503 * to by the items in the ·actual value· of the memberTypes [attribute],
11504 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011505 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000011506 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011507 /*
11508 * Resolve references.
11509 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011510 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011511 lastLink = NULL;
11512 while (link != NULL) {
11513 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011514
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011515 name = ((xmlSchemaQNameRefPtr) link->type)->name;
11516 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
11517
11518 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
11519 if ((memberType == NULL) || (! IS_SIMPLE_TYPE(memberType))) {
11520 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011521 type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011522 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
11523 /*
11524 * Remove the member type link.
11525 */
11526 if (lastLink == NULL)
11527 type->memberTypes = link->next;
11528 else
11529 lastLink->next = link->next;
11530 newLink = link;
11531 link = link->next;
11532 xmlFree(newLink);
11533 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011534 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011535 lastLink = link;
11536 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011537 }
11538 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011539 /*
11540 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011541 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011542 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011543 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011544 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
11545 if (link == NULL) {
11546 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
11547 return (-1);
11548 }
11549 link->type = memberType;
11550 link->next = NULL;
11551 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011552 type->memberTypes = link;
11553 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000011554 lastLink->next = link;
11555 lastLink = link;
11556 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011557 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011558 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000011559}
11560
Daniel Veillard4255d502002-04-16 15:50:10 +000011561/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011562 * xmlSchemaIsDerivedFromBuiltInType:
11563 * @ctxt: the schema parser context
11564 * @type: the type definition
11565 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011566 *
Daniel Veillard3646d642004-06-02 19:19:14 +000011567 *
11568 * Returns 1 if the type has the given value type, or
11569 * is derived from such a type.
11570 */
William M. Brack803812b2004-06-03 02:11:24 +000011571static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011572xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000011573{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011574 if (type == NULL)
11575 return (0);
11576 if (IS_COMPLEX_TYPE(type))
11577 return (0);
11578 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11579 if (type->builtInType == valType)
11580 return(1);
11581 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11582 (type->builtInType == XML_SCHEMAS_ANYTYPE))
11583 return (0);
11584 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11585 } else
11586 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000011587
11588 return (0);
11589}
11590
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011591#if 0
11592/**
11593 * xmlSchemaIsDerivedFromBuiltInType:
11594 * @ctxt: the schema parser context
11595 * @type: the type definition
11596 * @valType: the value type
11597 *
11598 *
11599 * Returns 1 if the type has the given value type, or
11600 * is derived from such a type.
11601 */
11602static int
11603xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
11604{
11605 if (type == NULL)
11606 return (0);
11607 if (IS_COMPLEX_TYPE(type))
11608 return (0);
11609 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11610 if (type->builtInType == valType)
11611 return(1);
11612 return (0);
11613 } else
11614 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11615
11616 return (0);
11617}
11618#endif
11619
11620static xmlSchemaTypePtr
11621xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
11622{
11623 if (type == NULL)
11624 return (NULL);
11625 if (IS_COMPLEX_TYPE(type))
11626 return (NULL);
11627 if (type->type == XML_SCHEMA_TYPE_BASIC)
11628 return(type);
11629 else
11630 return(xmlSchemaQueryBuiltInType(type->subtypes));
11631
11632 return (NULL);
11633}
11634
Daniel Veillard3646d642004-06-02 19:19:14 +000011635/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011636 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000011637 * @type: the simpleType definition
11638 *
11639 * Returns the primitive type of the given type or
11640 * NULL in case of error.
11641 */
11642static xmlSchemaTypePtr
11643xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
11644{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011645
Daniel Veillard01fa6152004-06-29 17:04:39 +000011646 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011647 /*
11648 * Note that anySimpleType is actually not a primitive type
11649 * but we need that here.
11650 */
11651 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11652 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000011653 return (type);
11654 type = type->baseType;
11655 }
11656
11657 return (NULL);
11658}
11659
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011660#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011661/**
11662 * xmlSchemaGetBuiltInTypeAncestor:
11663 * @type: the simpleType definition
11664 *
11665 * Returns the primitive type of the given type or
11666 * NULL in case of error.
11667 */
11668static xmlSchemaTypePtr
11669xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
11670{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011671 if (VARIETY_LIST(type) || VARIETY_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000011672 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011673 while (type != NULL) {
11674 if (type->type == XML_SCHEMA_TYPE_BASIC)
11675 return (type);
11676 type = type->baseType;
11677 }
11678
11679 return (NULL);
11680}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011681#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011682
Daniel Veillard01fa6152004-06-29 17:04:39 +000011683/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011684 * xmlSchemaBuildAttributeUsesOwned:
11685 * @ctxt: the schema parser context
11686 * @type: the complex type definition
11687 * @cur: the attribute declaration list
11688 * @lastUse: the top of the attribute use list
11689 *
11690 * Builds the attribute uses list on the given complex type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011691 * This one is supposed to be called by
Daniel Veillard3646d642004-06-02 19:19:14 +000011692 * xmlSchemaBuildAttributeValidation only.
11693 */
11694static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011695xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011696 xmlSchemaAttributePtr cur,
11697 xmlSchemaAttributeLinkPtr *uses,
11698 xmlSchemaAttributeLinkPtr *lastUse)
11699{
11700 xmlSchemaAttributeLinkPtr tmp;
11701 while (cur != NULL) {
11702 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011703 /*
11704 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
11705 * to by the ·actual value·s of the ref [attribute] of the
Daniel Veillard3646d642004-06-02 19:19:14 +000011706 * <attributeGroup> [children], if any."
11707 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011708 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
11709 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
Daniel Veillard3646d642004-06-02 19:19:14 +000011710 lastUse) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011711 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011712 }
11713 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011714 /* W3C: "1 The set of attribute uses corresponding to the
Daniel Veillard3646d642004-06-02 19:19:14 +000011715 * <attribute> [children], if any."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011716 */
11717 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +000011718 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11719 if (tmp == NULL) {
11720 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
11721 return (-1);
11722 }
11723 tmp->attr = cur;
11724 tmp->next = NULL;
11725 if (*uses == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011726 *uses = tmp;
11727 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011728 (*lastUse)->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011729 *lastUse = tmp;
11730 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011731 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011732 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011733 return (0);
11734}
11735
Daniel Veillard50355f02004-06-08 17:52:16 +000011736/**
11737 * xmlSchemaCloneWildcardNsConstraints:
11738 * @ctxt: the schema parser context
11739 * @dest: the destination wildcard
11740 * @source: the source wildcard
11741 *
11742 * Clones the namespace constraints of source
11743 * and assignes them to dest.
11744 * Returns -1 on internal error, 0 otherwise.
11745 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011746static int
11747xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
11748 xmlSchemaWildcardPtr *dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011749 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000011750{
11751 xmlSchemaWildcardNsPtr cur, tmp, last;
11752
11753 if ((source == NULL) || (*dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011754 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011755 (*dest)->any = source->any;
11756 cur = source->nsSet;
11757 last = NULL;
11758 while (cur != NULL) {
11759 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11760 if (tmp == NULL)
11761 return(-1);
11762 tmp->value = cur->value;
11763 if (last == NULL)
11764 (*dest)->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011765 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011766 last->next = tmp;
11767 last = tmp;
11768 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011769 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011770 if ((*dest)->negNsSet != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011771 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000011772 if (source->negNsSet != NULL) {
11773 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11774 if ((*dest)->negNsSet == NULL)
11775 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011776 (*dest)->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000011777 } else
11778 (*dest)->negNsSet = NULL;
11779 return(0);
11780}
11781
Daniel Veillard50355f02004-06-08 17:52:16 +000011782/**
11783 * xmlSchemaUnionWildcards:
11784 * @ctxt: the schema parser context
11785 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011786 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000011787 *
11788 * Unions the namespace constraints of the given wildcards.
11789 * @completeWild will hold the resulting union.
11790 * Returns a positive error code on failure, -1 in case of an
11791 * internal error, 0 otherwise.
11792 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011793static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011794xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011795 xmlSchemaWildcardPtr completeWild,
11796 xmlSchemaWildcardPtr curWild)
11797{
11798 xmlSchemaWildcardNsPtr cur, curB, tmp;
11799
11800 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011801 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000011802 * value.
11803 */
11804 if ((completeWild->any == curWild->any) &&
11805 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
11806 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011807
Daniel Veillard3646d642004-06-02 19:19:14 +000011808 if ((completeWild->negNsSet == NULL) ||
11809 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011810
Daniel Veillard3646d642004-06-02 19:19:14 +000011811 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000011812 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011813
11814 /*
11815 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000011816 */
11817 cur = completeWild->nsSet;
11818 while (cur != NULL) {
11819 found = 0;
11820 curB = curWild->nsSet;
11821 while (curB != NULL) {
11822 if (cur->value == curB->value) {
11823 found = 1;
11824 break;
11825 }
11826 curB = curB->next;
11827 }
11828 if (!found)
11829 break;
11830 cur = cur->next;
11831 }
11832 if (found)
11833 return(0);
11834 } else
11835 return(0);
11836 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011837 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011838 /*
11839 * 2 If either O1 or O2 is any, then any must be the value
11840 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011841 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011842 if (completeWild->any == 0) {
11843 completeWild->any = 1;
11844 if (completeWild->nsSet != NULL) {
11845 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11846 completeWild->nsSet = NULL;
11847 }
11848 if (completeWild->negNsSet != NULL) {
11849 xmlFree(completeWild->negNsSet);
11850 completeWild->negNsSet = NULL;
11851 }
11852 }
Daniel Veillard50355f02004-06-08 17:52:16 +000011853 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011854 }
11855 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011856 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000011857 * then the union of those sets must be the value.
11858 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011859 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011860 int found;
11861 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011862
Daniel Veillard3646d642004-06-02 19:19:14 +000011863 cur = curWild->nsSet;
11864 start = completeWild->nsSet;
11865 while (cur != NULL) {
11866 found = 0;
11867 curB = start;
11868 while (curB != NULL) {
11869 if (cur->value == curB->value) {
11870 found = 1;
11871 break;
11872 }
11873 curB = curB->next;
11874 }
11875 if (!found) {
11876 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011877 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011878 return (-1);
11879 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011880 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000011881 completeWild->nsSet = tmp;
11882 }
11883 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011884 }
11885
Daniel Veillard3646d642004-06-02 19:19:14 +000011886 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011887 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011888 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011889 * 4 If the two are negations of different values (namespace names
Daniel Veillard3646d642004-06-02 19:19:14 +000011890 * or ·absent·), then a pair of not and ·absent· must be the value.
11891 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011892 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011893 (curWild->negNsSet != NULL) &&
11894 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
11895 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000011896
11897 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011898 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011899 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011900 * 5.
11901 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011902 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011903 (completeWild->negNsSet->value != NULL) &&
11904 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011905 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011906 (curWild->negNsSet->value != NULL) &&
11907 (completeWild->nsSet != NULL))) {
11908
11909 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011910
Daniel Veillard3646d642004-06-02 19:19:14 +000011911 if (completeWild->nsSet != NULL) {
11912 cur = completeWild->nsSet;
11913 curB = curWild->negNsSet;
11914 } else {
11915 cur = curWild->nsSet;
11916 curB = completeWild->negNsSet;
11917 }
11918 nsFound = 0;
11919 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011920 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011921 absentFound = 1;
11922 else if (cur->value == curB->value)
11923 nsFound = 1;
11924 if (nsFound && absentFound)
11925 break;
11926 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011927 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011928
11929 if (nsFound && absentFound) {
11930 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011931 * 5.1 If the set S includes both the negated namespace
Daniel Veillard3646d642004-06-02 19:19:14 +000011932 * name and ·absent·, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011933 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011934 completeWild->any = 1;
11935 if (completeWild->nsSet != NULL) {
11936 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11937 completeWild->nsSet = NULL;
11938 }
11939 if (completeWild->negNsSet != NULL) {
11940 xmlFree(completeWild->negNsSet);
11941 completeWild->negNsSet = NULL;
11942 }
11943 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011944 /*
11945 * 5.2 If the set S includes the negated namespace name
11946 * but not ·absent·, then a pair of not and ·absent· must
Daniel Veillard3646d642004-06-02 19:19:14 +000011947 * be the value.
11948 */
11949 if (completeWild->nsSet != NULL) {
11950 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11951 completeWild->nsSet = NULL;
11952 }
11953 if (completeWild->negNsSet == NULL) {
11954 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11955 if (completeWild->negNsSet == NULL)
11956 return (-1);
11957 }
11958 completeWild->negNsSet->value = NULL;
11959 } else if ((!nsFound) && absentFound) {
11960 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011961 * 5.3 If the set S includes ·absent· but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000011962 * namespace name, then the union is not expressible.
11963 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011964 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000011965 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011966 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011967 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011968 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011969 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011970 /*
11971 * 5.4 If the set S does not include either the negated namespace
11972 * name or ·absent·, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000011973 * and a namespace name must be the value.
11974 */
11975 if (completeWild->negNsSet == NULL) {
11976 if (completeWild->nsSet != NULL) {
11977 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11978 completeWild->nsSet = NULL;
11979 }
11980 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11981 if (completeWild->negNsSet == NULL)
11982 return (-1);
11983 completeWild->negNsSet->value = curWild->negNsSet->value;
11984 }
11985 }
11986 return (0);
11987 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011988 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011989 * 6.
11990 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011991 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011992 (completeWild->negNsSet->value == NULL) &&
11993 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011994 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011995 (curWild->negNsSet->value == NULL) &&
11996 (completeWild->nsSet != NULL))) {
11997
11998 if (completeWild->nsSet != NULL) {
11999 cur = completeWild->nsSet;
12000 } else {
12001 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012002 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012003 while (cur != NULL) {
12004 if (cur->value == NULL) {
12005 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012006 * 6.1 If the set S includes ·absent·, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012007 * value.
12008 */
12009 completeWild->any = 1;
12010 if (completeWild->nsSet != NULL) {
12011 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12012 completeWild->nsSet = NULL;
12013 }
12014 if (completeWild->negNsSet != NULL) {
12015 xmlFree(completeWild->negNsSet);
12016 completeWild->negNsSet = NULL;
12017 }
12018 return (0);
12019 }
12020 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012021 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012022 if (completeWild->negNsSet == NULL) {
12023 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012024 * 6.2 If the set S does not include ·absent·, then a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012025 * and ·absent· must be the value.
12026 */
12027 if (completeWild->nsSet != NULL) {
12028 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12029 completeWild->nsSet = NULL;
12030 }
12031 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12032 if (completeWild->negNsSet == NULL)
12033 return (-1);
12034 completeWild->negNsSet->value = NULL;
12035 }
12036 return (0);
12037 }
12038 return (0);
12039
12040}
12041
Daniel Veillard50355f02004-06-08 17:52:16 +000012042/**
12043 * xmlSchemaIntersectWildcards:
12044 * @ctxt: the schema parser context
12045 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012046 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012047 *
12048 * Intersects the namespace constraints of the given wildcards.
12049 * @completeWild will hold the resulting intersection.
12050 * Returns a positive error code on failure, -1 in case of an
12051 * internal error, 0 otherwise.
12052 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012053static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012054xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012055 xmlSchemaWildcardPtr completeWild,
12056 xmlSchemaWildcardPtr curWild)
12057{
William M. Brack803812b2004-06-03 02:11:24 +000012058 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012059
12060 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012061 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012062 * value.
12063 */
12064 if ((completeWild->any == curWild->any) &&
12065 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
12066 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012067
Daniel Veillard3646d642004-06-02 19:19:14 +000012068 if ((completeWild->negNsSet == NULL) ||
12069 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012070
Daniel Veillard3646d642004-06-02 19:19:14 +000012071 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000012072 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012073
12074 /*
12075 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000012076 */
12077 cur = completeWild->nsSet;
12078 while (cur != NULL) {
12079 found = 0;
12080 curB = curWild->nsSet;
12081 while (curB != NULL) {
12082 if (cur->value == curB->value) {
12083 found = 1;
12084 break;
12085 }
12086 curB = curB->next;
12087 }
12088 if (!found)
12089 break;
12090 cur = cur->next;
12091 }
12092 if (found)
12093 return(0);
12094 } else
12095 return(0);
12096 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012097 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012098 /*
12099 * 2 If either O1 or O2 is any, then the other must be the value.
12100 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012101 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012102 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012103 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012104 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012105 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012106 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012107 * 3 If either O1 or O2 is a pair of not and a value (a namespace
12108 * name or ·absent·) and the other is a set of (namespace names or
12109 * ·absent·), then that set, minus the negated value if it was in
Daniel Veillard3646d642004-06-02 19:19:14 +000012110 * the set, minus ·absent· if it was in the set, must be the value.
12111 */
12112 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
12113 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
12114 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012115
Daniel Veillard3646d642004-06-02 19:19:14 +000012116 if (completeWild->nsSet == NULL) {
12117 neg = completeWild->negNsSet->value;
12118 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
12119 return(-1);
12120 } else
12121 neg = curWild->negNsSet->value;
12122 /*
12123 * Remove absent and negated.
12124 */
12125 prev = NULL;
12126 cur = completeWild->nsSet;
12127 while (cur != NULL) {
12128 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012129 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012130 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012131 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012132 prev->next = cur->next;
12133 xmlFree(cur);
12134 break;
12135 }
12136 prev = cur;
12137 cur = cur->next;
12138 }
12139 if (neg != NULL) {
12140 prev = NULL;
12141 cur = completeWild->nsSet;
12142 while (cur != NULL) {
12143 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012144 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012145 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012146 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012147 prev->next = cur->next;
12148 xmlFree(cur);
12149 break;
12150 }
12151 prev = cur;
12152 cur = cur->next;
12153 }
12154 }
12155
12156 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012157 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012158 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012159 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000012160 * then the intersection of those sets must be the value.
12161 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012162 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012163 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012164
Daniel Veillard3646d642004-06-02 19:19:14 +000012165 cur = completeWild->nsSet;
12166 prev = NULL;
12167 while (cur != NULL) {
12168 found = 0;
12169 curB = curWild->nsSet;
12170 while (curB != NULL) {
12171 if (cur->value == curB->value) {
12172 found = 1;
12173 break;
12174 }
12175 curB = curB->next;
12176 }
12177 if (!found) {
12178 if (prev == NULL)
12179 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012180 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012181 prev->next = cur->next;
12182 tmp = cur->next;
12183 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012184 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012185 continue;
12186 }
12187 prev = cur;
12188 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012189 }
12190
Daniel Veillard3646d642004-06-02 19:19:14 +000012191 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012192 }
12193 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000012194 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012195 */
12196 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012197 (curWild->negNsSet != NULL) &&
12198 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012199 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012200 (curWild->negNsSet->value != NULL)) {
12201
12202 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012203 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012204 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012205 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012206 }
12207 /*
12208 * 6 If the one is a negation of a namespace name and the other
12209 * is a negation of ·absent·, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000012210 * of a namespace name must be the value.
12211 */
12212 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
12213 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012214 (completeWild->negNsSet->value == NULL)) {
12215 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000012216 }
12217 return(0);
12218}
12219
Daniel Veillard50355f02004-06-08 17:52:16 +000012220/**
12221 * xmlSchemaIsWildcardNsConstraintSubset:
12222 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012223 * @sub: the first wildcard
12224 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012225 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012226 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
12227 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012228 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012229 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000012230 */
12231static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012232xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
12233 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012234{
Daniel Veillard50355f02004-06-08 17:52:16 +000012235 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012236 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000012237 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012238 if (super->any)
12239 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012240 /*
12241 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
12242 * 2.2 super must be a pair of not and the same value.
12243 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012244 if ((sub->negNsSet != NULL) &&
12245 (super->negNsSet != NULL) &&
12246 (sub->negNsSet->value == sub->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012247 return (0);
12248 /*
12249 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
Daniel Veillard50355f02004-06-08 17:52:16 +000012250 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012251 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012252 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012253 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000012254 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012255 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012256 xmlSchemaWildcardNsPtr cur, curB;
12257 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012258
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012259 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012260 while (cur != NULL) {
12261 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012262 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012263 while (curB != NULL) {
12264 if (cur->value == curB->value) {
12265 found = 1;
12266 break;
12267 }
12268 curB = curB->next;
12269 }
12270 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012271 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012272 cur = cur->next;
12273 }
12274 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012275 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012276 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012277 xmlSchemaWildcardNsPtr cur;
12278 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012279 * 3.2.2 super must be a pair of not and a namespace name or
12280 * ·absent· and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000012281 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012282 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012283 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012284 if (cur->value == super->negNsSet->value)
12285 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012286 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012287 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012288 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012289 }
12290 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012291 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012292}
12293
12294/**
12295 * xmlSchemaBuildCompleteAttributeWildcard:
12296 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012297 * @attrs: the attribute list
Daniel Veillard50355f02004-06-08 17:52:16 +000012298 * @completeWild: the resulting complete wildcard
12299 *
12300 * Returns -1 in case of an internal error, 0 otherwise.
12301 */
12302static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012303xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012304 xmlSchemaAttributePtr attrs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012305 xmlSchemaWildcardPtr *completeWild)
12306{
Daniel Veillard3646d642004-06-02 19:19:14 +000012307 while (attrs != NULL) {
12308 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12309 xmlSchemaAttributeGroupPtr group;
12310
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012311 group = (xmlSchemaAttributeGroupPtr) attrs;
12312 /*
12313 * Handle attribute group references.
12314 */
12315 if (group->ref != NULL) {
12316 if (group->refItem == NULL) {
12317 /*
12318 * TODO: Should we raise a warning here?
12319 */
12320 /*
12321 * The referenced attribute group definition could not
12322 * be resolved beforehand, so skip.
12323 */
12324 attrs = attrs->next;
12325 continue;
12326 } else
12327 group = group->refItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012328 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012329 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012330 * For every attribute group definition, an intersected wildcard
12331 * will be created (assumed that a wildcard exists on the
12332 * particular attr. gr. def. or on any contained attr. gr. def
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012333 * at all).
12334 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
12335 * that the intersection will be performed only once.
12336 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012337 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
12338 if (group->attributes != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012339 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012340 group->attributes, &group->attributeWildcard) == -1)
12341 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012342 }
12343 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012344 }
12345 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012346 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012347 /*
12348 * Copy the first encountered wildcard as context, except for the annotation.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012349 *
12350 * Although the complete wildcard might not correspond to any
12351 * node in the schema, we will save this context node.
Daniel Veillard3646d642004-06-02 19:19:14 +000012352 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012353 *completeWild = xmlSchemaAddWildcard(ctxt, ctxt->schema,
12354 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
12355 group->attributeWildcard->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012356 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012357 completeWild, group->attributeWildcard) == -1)
12358 return (-1);
12359 (*completeWild)->processContents = group->attributeWildcard->processContents;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012360 (*completeWild)->node = group->attributeWildcard->node;
12361 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1)
Daniel Veillard50355f02004-06-08 17:52:16 +000012362 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012363 }
12364 }
12365 attrs = attrs->next;
12366 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012367
12368 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012369}
12370
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012371static int
12372xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
12373 int *fixed,
12374 const xmlChar **value,
12375 xmlSchemaValPtr *val)
12376{
12377 *fixed = 0;
12378 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012379 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012380 *val = NULL;
12381
12382 if (item->defValue == NULL)
12383 item = item->refDecl;
12384
12385 if (item == NULL)
12386 return (0);
12387
12388 if (item->defValue != NULL) {
12389 *value = item->defValue;
12390 if (val != 0)
12391 *val = item->defVal;
12392 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
12393 *fixed = 1;
12394 return (1);
12395 }
12396 return (0);
12397}
Daniel Veillard3646d642004-06-02 19:19:14 +000012398/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012399 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000012400 * @wild: the wildcard
12401 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012402 *
12403 * Validation Rule: Wildcard allows Namespace Name
12404 * (cvc-wildcard-namespace)
12405 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012406 *
12407 * Returns 1 if the given namespace matches the wildcard,
12408 * 0 otherwise.
12409 */
12410static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012411xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
12412 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000012413{
12414 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012415 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012416
12417 if (wild->any)
12418 return(1);
12419 else if (wild->nsSet != NULL) {
12420 xmlSchemaWildcardNsPtr cur;
12421
12422 cur = wild->nsSet;
12423 while (cur != NULL) {
12424 if (xmlStrEqual(cur->value, ns))
12425 return(1);
12426 cur = cur->next;
12427 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012428 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012429 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012430 return(1);
12431
Daniel Veillard3646d642004-06-02 19:19:14 +000012432 return(0);
12433}
12434
12435/**
12436 * xmlSchemaBuildAttributeValidation:
12437 * @ctxt: the schema parser context
12438 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012439 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012440 *
12441 * Builds the wildcard and the attribute uses on the given complex type.
12442 * Returns -1 if an internal error occurs, 0 otherwise.
12443 */
12444static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012445xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr pctxt,
12446 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000012447{
12448 xmlSchemaTypePtr baseType = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012449 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL,
12450 prev = NULL, uses = NULL, lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000012451 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012452 xmlSchemaTypePtr anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012453 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012454 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000012455
Daniel Veillard01fa6152004-06-29 17:04:39 +000012456 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012457 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012458 * Complex Type Definition with complex content Schema Component.
12459 *
12460 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012461 * TODO: Add checks for absent referenced attribute declarations and
12462 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000012463 */
12464 if (type->attributeUses != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012465 PERROR_INT("xmlSchemaBuildAttributeValidation",
12466 "attribute uses already builded");
Daniel Veillard3646d642004-06-02 19:19:14 +000012467 return (-1);
12468 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012469 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012470 PERROR_INT("xmlSchemaBuildAttributeValidation",
12471 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012472 return (-1);
12473 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012474 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012475 /*
12476 * Inherit the attribute uses of the base type.
12477 */
12478 /*
12479 * NOTE: It is allowed to "extend" the anyType complex type.
12480 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012481 if (! IS_ANYTYPE(baseType)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012482 if (baseType != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012483 for (cur = baseType->attributeUses; cur != NULL;
12484 cur = cur->next) {
12485 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012486 xmlMalloc(sizeof(xmlSchemaAttributeLink));
12487 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012488 xmlSchemaPErrMemory(pctxt,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012489 "building attribute uses of complexType", NULL);
12490 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012491 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012492 tmp->attr = cur->attr;
12493 tmp->next = NULL;
12494 if (type->attributeUses == NULL) {
12495 type->attributeUses = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012496 } else
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012497 lastBaseUse->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012498 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012499 }
12500 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012501 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012502 attrs = type->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012503 /*
12504 * Handle attribute wildcards.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012505 */
12506 err = xmlSchemaBuildCompleteAttributeWildcard(pctxt,
12507 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012508 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012509 * NOTE: During the parse time, the wildcard is created on the complexType
12510 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012511 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012512 if (err == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012513 PERROR_INT("xmlSchemaBuildAttributeValidation",
12514 "failed to build an intersected attribute wildcard");
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012515 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012516 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012517
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012518 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
12519 ((IS_ANYTYPE(baseType)) ||
12520 ((baseType != NULL) &&
12521 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
12522 (baseType->attributeWildcard != NULL)))) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012523 if (type->attributeWildcard != NULL) {
12524 /*
12525 * Union the complete wildcard with the base wildcard.
12526 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012527 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012528 baseType->attributeWildcard) == -1)
12529 return (-1);
12530 } else {
12531 /*
12532 * Just inherit the wildcard.
12533 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012534 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012535 * NOTE: This is the only case where an attribute
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012536 * wildcard is shared.
12537 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012538 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000012539 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012540 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012541
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012542 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12543 if (type->attributeWildcard != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012544 /*
12545 * Derivation Valid (Restriction, Complex)
12546 * 4.1 The {base type definition} must also have one.
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012547 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012548 if (baseType->attributeWildcard == NULL) {
12549 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012550 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012551 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012552 "The type has an attribute wildcard, "
12553 "but the base type %s does not have one",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012554 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012555 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012556 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012557 } else if (xmlSchemaCheckCOSNSSubset(
12558 type->attributeWildcard, baseType->attributeWildcard)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012559 /* 4.2 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012560 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012561 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012562 NULL, type, NULL,
12563 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012564 "subset of the wildcard in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012565 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12566 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012567 return (1);
12568 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012569 /* 4.3 Unless the {base type definition} is the ·ur-type
12570 * definition·, the complex type definition's {attribute
12571 * wildcard}'s {process contents} must be identical to or
12572 * stronger than the {base type definition}'s {attribute
12573 * wildcard}'s {process contents}, where strict is stronger
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012574 * than lax is stronger than skip.
12575 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012576 if ((! IS_ANYTYPE(baseType)) &&
12577 (type->attributeWildcard->processContents <
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012578 baseType->attributeWildcard->processContents)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012579 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012580 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012581 NULL, type, NULL,
12582 "The 'process contents' of the attribute wildcard is "
12583 "weaker than the one in the base type %s",
12584 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012585 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012586 return (1);
12587 }
12588 }
12589 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12590 /*
12591 * Derivation Valid (Extension)
12592 * At this point the type and the base have both, either
12593 * no wildcard or a wildcard.
12594 */
12595 if ((baseType->attributeWildcard != NULL) &&
12596 (baseType->attributeWildcard != type->attributeWildcard)) {
12597 /* 1.3 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012598 if (xmlSchemaCheckCOSNSSubset(
12599 baseType->attributeWildcard, type->attributeWildcard)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012600 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012601 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012602 NULL, type, NULL,
12603 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012604 "superset of the one in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012605 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12606 FREE_AND_NULL(str)
12607 return (1);
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012608 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012609 }
12610 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012611
Daniel Veillard3646d642004-06-02 19:19:14 +000012612 /*
12613 * Gather attribute uses defined by this type.
12614 */
12615 if (attrs != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012616 if (xmlSchemaBuildAttributeUsesOwned(pctxt, attrs,
Daniel Veillard3646d642004-06-02 19:19:14 +000012617 &uses, &lastUse) == -1) {
12618 return (-1);
12619 }
12620 }
12621 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012622 * "Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012623 * not have identical {name}s and {target namespace}s."
12624 *
12625 * For "extension" this is done further down.
12626 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012627 if ((uses != NULL) && ((type->flags &
12628 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012629 cur = uses;
12630 while (cur != NULL) {
12631 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012632 while (tmp != NULL) {
12633 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012634 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012635 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012636 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
12637
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012638 xmlSchemaPAttrUseErr(pctxt,
12639 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12640 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012641 "Duplicate attribute use %s specified",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012642 xmlSchemaFormatQName(&str,
12643 xmlSchemaGetAttrTargetNsURI(tmp->attr),
12644 xmlSchemaGetAttrName(tmp->attr)));
12645 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000012646 break;
12647 }
12648 tmp = tmp->next;
12649 }
12650 cur = cur->next;
12651 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012652 }
12653 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012654 /*
12655 * Derive by restriction.
12656 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012657 if (IS_ANYTYPE(baseType)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012658 type->attributeUses = uses;
12659 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012660 int found, valid;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012661 const xmlChar *bEffValue;
12662 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000012663
12664 cur = uses;
12665 while (cur != NULL) {
12666 found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012667 valid = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012668 base = type->attributeUses;
12669 while (base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012670 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012671 xmlSchemaGetAttrName(base->attr)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012672 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012673 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012674
12675 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012676
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012677 if ((cur->attr->occurs ==
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012678 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12679 (base->attr->occurs ==
12680 XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
12681 /*
12682 * NOOP.
12683 */
12684 } else if ((cur->attr->occurs ==
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012685 XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
12686 (base->attr->occurs ==
12687 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012688 /*
12689 * derivation-ok-restriction 2.1.1
Daniel Veillard3646d642004-06-02 19:19:14 +000012690 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012691 xmlSchemaPAttrUseErr(pctxt,
12692 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
12693 type, cur->attr,
12694 "The 'optional' use is inconsistent with a "
12695 "matching 'required' use of the base type",
12696 NULL);
12697 } else if ((cur->attr->occurs ==
12698 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12699 (base->attr->occurs ==
12700 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
12701 /*
12702 * derivation-ok-restriction 3
12703 */
12704 xmlSchemaPCustomErr(pctxt,
12705 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
12706 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012707 "A matching attribute use for the 'required' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012708 "attribute use '%s' of the base type is "
12709 "missing",
12710 xmlSchemaFormatQName(&str,
12711 xmlSchemaGetAttrTargetNsURI(base->attr),
12712 xmlSchemaGetAttrName(base->attr)));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012713 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012714 } else if (xmlSchemaCheckCOSSTDerivedOK(
12715 cur->attr->subtypes, base->attr->subtypes, 0) != 0) {
12716
12717 /*
12718 * SPEC (2.1.2) "R's {attribute declaration}'s
12719 * {type definition} must be validly derived from
12720 * B's {type definition} given the empty set as
12721 * defined in Type Derivation OK (Simple) (§3.14.6)."
12722 */
12723 xmlSchemaPAttrUseErr(pctxt,
12724 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
12725 type, cur->attr,
12726 "The attribute declaration's type "
12727 "definition is not validly derived from "
12728 "the corresponding definition in the "
12729 "base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012730 } else {
12731 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012732 * 2.1.3 [Definition:] Let the effective value
12733 * constraint of an attribute use be its {value
12734 * constraint}, if present, otherwise its {attribute
12735 * declaration}'s {value constraint} .
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012736 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012737 xmlSchemaGetEffectiveValueConstraint(base->attr,
12738 &effFixed, &bEffValue, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012739 /*
12740 * 2.1.3 ... one of the following must be true
12741 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012742 * 2.1.3.1 B's ·effective value constraint· is
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012743 * ·absent· or default.
12744 */
12745 if ((bEffValue != NULL) &&
12746 (effFixed == 1)) {
12747 const xmlChar *rEffValue = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012748
12749 xmlSchemaGetEffectiveValueConstraint(base->attr,
12750 &effFixed, &rEffValue, 0);
12751 /*
12752 * 2.1.3.2 R's ·effective value constraint· is
12753 * fixed with the same string as B's.
12754 * TODO: Compare the computed values.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012755 */
12756 if ((effFixed == 0) ||
12757 (! xmlStrEqual(rEffValue, bEffValue))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012758 xmlSchemaPAttrUseErr(pctxt,
12759 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
12760 type, cur->attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012761 "The effective value constraint of the "
12762 "attribute use is inconsistent with "
12763 "its correspondent of the base type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012764 NULL);
12765 } else {
12766 /*
12767 * Override the attribute use.
12768 */
12769 base->attr = cur->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012770 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012771 } else
12772 base->attr = cur->attr;
Daniel Veillard3646d642004-06-02 19:19:14 +000012773 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012774
Daniel Veillard3646d642004-06-02 19:19:14 +000012775 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012776 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012777 base = base->next;
12778 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012779
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012780 if ((!found) && (cur->attr->occurs !=
12781 XML_SCHEMAS_ATTR_USE_PROHIBITED)) {
12782 /*
12783 * derivation-ok-restriction 2.2
12784 */
12785 if ((baseType->attributeWildcard == NULL) ||
12786 (xmlSchemaCheckCVCWildcardNamespace(
12787 baseType->attributeWildcard,
12788 cur->attr->targetNamespace) != 1)) {
12789 xmlSchemaPAttrUseErr(pctxt,
12790 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
12791 type, cur->attr,
12792 "Neither a matching attribute use, "
12793 "nor a matching wildcard in the base type does exist",
12794 NULL);
12795 } else {
12796 /*
12797 * Add the attribute use.
12798 *
12799 * Note that this may lead to funny derivation error reports, if
12800 * multiple equal attribute uses exist; but this is not
12801 * allowed anyway, and it will be reported beforehand.
12802 */
12803 tmp = cur;
12804 if (prev != NULL)
12805 prev->next = cur->next;
12806 else
12807 uses = cur->next;
12808 cur = cur->next;
12809 tmp->next = NULL;
12810 if (type->attributeUses == NULL) {
12811 type->attributeUses = tmp;
12812 } else
12813 lastBaseUse->next = tmp;
12814 lastBaseUse = tmp;
12815
12816 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000012817 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012818 }
12819 prev = cur;
Daniel Veillard3646d642004-06-02 19:19:14 +000012820 cur = cur->next;
12821 }
12822 if (uses != NULL)
12823 xmlSchemaFreeAttributeUseList(uses);
12824 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012825 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012826 /*
12827 * The spec allows only appending, and not other kinds of extensions.
12828 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012829 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
Daniel Veillard3646d642004-06-02 19:19:14 +000012830 */
12831 if (uses != NULL) {
12832 if (type->attributeUses == NULL) {
12833 type->attributeUses = uses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012834 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000012835 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012836 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012837 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012838 PERROR_INT("xmlSchemaBuildAttributeValidation",
12839 "no derivation method");
12840 return (-1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012841 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012842 /*
12843 * 3.4.6 -> Complex Type Definition Properties Correct
12844 */
12845 if (type->attributeUses != NULL) {
12846 cur = type->attributeUses;
12847 prev = NULL;
12848 while (cur != NULL) {
12849 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012850 * 4. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012851 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000012852 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012853 * Note that this was already done for "restriction" and types derived from
12854 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000012855 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012856 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12857 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012858 while (tmp != NULL) {
12859 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012860 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012861 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012862 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012863
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012864 xmlSchemaPAttrUseErr(pctxt,
12865 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12866 type, tmp->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012867 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012868 break;
12869 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012870 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012871 }
12872 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012873 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012874 * 5. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012875 * not have {type definition}s which are or are derived from ID.
12876 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012877 if ((cur->attr->subtypes != NULL) &&
12878 (xmlSchemaIsDerivedFromBuiltInType(cur->attr->subtypes,
12879 XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012880 if (id != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012881 xmlSchemaPAttrUseErr(pctxt,
12882 XML_SCHEMAP_CT_PROPS_CORRECT_5,
12883 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012884 "There must not exist more than one attribute use, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012885 "declared of type 'ID' or derived from it",
Daniel Veillardc0826a72004-08-10 14:17:33 +000012886 NULL);
12887 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012888 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012889 id = cur;
12890 }
12891 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012892 * Remove "prohibited" attribute uses. The reason this is done at this late
Daniel Veillard3646d642004-06-02 19:19:14 +000012893 * stage is to be able to catch dublicate attribute uses. So we had to keep
12894 * prohibited uses in the list as well.
12895 */
12896 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
12897 tmp = cur;
12898 if (prev == NULL)
12899 type->attributeUses = cur->next;
12900 else
12901 prev->next = cur->next;
12902 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012903 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000012904 } else {
12905 prev = cur;
12906 cur = cur->next;
12907 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012908 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012909 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012910 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012911 * TODO: This check should be removed if we are 100% sure of
12912 * the base type attribute uses already being built.
12913 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012914 if ((baseType != NULL) && (! IS_ANYTYPE(baseType)) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012915 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012916 (IS_NOT_TYPEFIXED(baseType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012917 PERROR_INT("xmlSchemaBuildAttributeValidation",
12918 "attribute uses not builded on base type");
12919 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012920 return (0);
12921}
12922
12923/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000012924 * xmlSchemaTypeFinalContains:
12925 * @schema: the schema
12926 * @type: the type definition
12927 * @final: the final
12928 *
12929 * Evaluates if a type definition contains the given "final".
12930 * This does take "finalDefault" into account as well.
12931 *
12932 * Returns 1 if the type does containt the given "final",
12933 * 0 otherwise.
12934 */
12935static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012936xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012937{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012938 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012939 return (0);
12940 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012941 return (1);
12942 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012943 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012944}
12945
12946/**
12947 * xmlSchemaGetUnionSimpleTypeMemberTypes:
12948 * @type: the Union Simple Type
12949 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012950 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012951 * returns NULL otherwise.
12952 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012953static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000012954xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
12955{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012956 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012957 if (type->memberTypes != NULL)
12958 return (type->memberTypes);
12959 else
12960 type = type->baseType;
12961 }
12962 return (NULL);
12963}
12964
12965/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012966 * xmlSchemaGetParticleTotalRangeMin:
12967 * @particle: the particle
12968 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012969 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012970 * (all and sequence) + (choice)
12971 *
12972 * Returns the minimun Effective Total Range.
12973 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012974static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012975xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012976{
12977 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012978 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012979 return (0);
12980 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012981 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012982 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012983 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012984
12985 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012986 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012987 while (part != NULL) {
12988 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
12989 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012990 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012991 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012992 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012993 if (cur == 0)
12994 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012995 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012996 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012997 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012998 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012999 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013000 } else {
13001 /* <all> and <sequence> */
13002 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013003 xmlSchemaParticlePtr part =
13004 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013005
13006 if (part == NULL)
13007 return (0);
13008 do {
13009 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13010 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013011 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013012 else
13013 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013014 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013015 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013016 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013017 }
13018}
13019
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013020/**
13021 * xmlSchemaGetParticleTotalRangeMax:
13022 * @particle: the particle
13023 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013024 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013025 * (all and sequence) + (choice)
13026 *
13027 * Returns the maximum Effective Total Range.
13028 */
13029static int
13030xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
13031{
13032 if ((particle->children == NULL) ||
13033 (particle->children->children == NULL))
13034 return (0);
13035 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
13036 int max = -1, cur;
13037 xmlSchemaParticlePtr part =
13038 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013039
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013040 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13041 if (part->children == NULL)
13042 continue;
13043 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13044 (part->children->type == XML_SCHEMA_TYPE_ANY))
13045 cur = part->maxOccurs;
13046 else
13047 cur = xmlSchemaGetParticleTotalRangeMax(part);
13048 if (cur == UNBOUNDED)
13049 return (UNBOUNDED);
13050 if ((max < cur) || (max == -1))
13051 max = cur;
13052 }
13053 /* TODO: Handle overflows? */
13054 return (particle->maxOccurs * max);
13055 } else {
13056 /* <all> and <sequence> */
13057 int sum = 0, cur;
13058 xmlSchemaParticlePtr part =
13059 (xmlSchemaParticlePtr) particle->children->children;
13060
13061 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13062 if (part->children == NULL)
13063 continue;
13064 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13065 (part->children->type == XML_SCHEMA_TYPE_ANY))
13066 cur = part->maxOccurs;
13067 else
13068 cur = xmlSchemaGetParticleTotalRangeMax(part);
13069 if (cur == UNBOUNDED)
13070 return (UNBOUNDED);
13071 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
13072 return (UNBOUNDED);
13073 sum += cur;
13074 }
13075 /* TODO: Handle overflows? */
13076 return (particle->maxOccurs * sum);
13077 }
13078}
13079
13080/**
13081 * xmlSchemaIsParticleEmptiable:
13082 * @particle: the particle
13083 *
13084 * Schema Component Constraint: Particle Emptiable
13085 * Checks whether the given particle is emptiable.
13086 *
13087 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013088 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013089static int
13090xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
13091{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013092 /*
13093 * SPEC (1) "Its {min occurs} is 0."
13094 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013095 if ((particle == NULL) || (particle->minOccurs == 0) ||
13096 (particle->children == NULL))
13097 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013098 /*
13099 * SPEC (2) "Its {term} is a group and the minimum part of the
13100 * effective total range of that group, [...] is 0."
13101 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013102 if (IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013103 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013104 return (1);
13105 }
13106 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013107}
13108
13109/**
13110 * xmlSchemaCheckCOSSTDerivedOK:
13111 * @type: the derived simple type definition
13112 * @baseType: the base type definition
13113 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013114 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013115 * Type Derivation OK (Simple) (cos-st-derived-OK)
13116 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013117 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000013118 * derived from @baseType.
13119 *
13120 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013121 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013122static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013123xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
13124 xmlSchemaTypePtr baseType,
13125 int subset)
13126{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013127 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013128 * 1 They are the same type definition.
13129 * TODO: The identy check might have to be more complex than this.
13130 */
13131 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013132 return (0);
13133 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013134 * 2.1 restriction is not in the subset, or in the {final}
13135 * of its own {base type definition};
13136 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013137 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013138 (xmlSchemaTypeFinalContains(type->baseType,
13139 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
13140 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013141 }
13142 /* 2.2 */
13143 if (type->baseType == baseType) {
13144 /*
13145 * 2.2.1 D's ·base type definition· is B.
13146 */
13147 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013148 }
13149 /*
13150 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
13151 * and is validly derived from B given the subset, as defined by this
13152 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013153 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013154 if ((! IS_ANYTYPE(type->baseType)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013155 (xmlSchemaCheckCOSSTDerivedOK(type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013156 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013157 return (0);
13158 }
13159 /*
13160 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
Daniel Veillard01fa6152004-06-29 17:04:39 +000013161 * definition·.
13162 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013163 if (IS_ANY_SIMPLE_TYPE(baseType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013164 (VARIETY_LIST(type) || VARIETY_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013165 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013166 }
13167 /*
13168 * 2.2.4 B's {variety} is union and D is validly derived from a type
13169 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000013170 * defined by this constraint.
13171 *
13172 * NOTE: This seems not to involve built-in types, since there is no
13173 * built-in Union Simple Type.
13174 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013175 if (VARIETY_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013176 xmlSchemaTypeLinkPtr cur;
13177
13178 cur = baseType->memberTypes;
13179 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013180 if (xmlSchemaCheckCOSSTDerivedOK(type, cur->type, subset) == 0)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013181 return (0);
13182 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013183 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013184 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013185
Daniel Veillard01fa6152004-06-29 17:04:39 +000013186 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
13187}
13188
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013189/**
13190 * xmlSchemaCheckTypeDefCircularInternal:
13191 * @pctxt: the schema parser context
13192 * @ctxtType: the type definition
13193 * @ancestor: an ancestor of @ctxtType
13194 *
13195 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013196 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013197 *
13198 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
13199 * circular, 0 otherwise.
13200 */
13201static int
13202xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
13203 xmlSchemaTypePtr ctxtType,
13204 xmlSchemaTypePtr ancestor)
13205{
13206 int ret;
13207
13208 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
13209 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013210
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013211 if (ctxtType == ancestor) {
13212 xmlSchemaPCustomErr(pctxt,
13213 XML_SCHEMAP_ST_PROPS_CORRECT_2,
13214 NULL, ctxtType, GET_NODE(ctxtType),
13215 "The definition is circular", NULL);
13216 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
13217 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013218 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
13219 /*
13220 * Avoid inifinite recursion on circular types not yet checked.
13221 */
13222 return (0);
13223 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013224 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
13225 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
13226 ancestor->baseType);
13227 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
13228 return (ret);
13229}
13230
13231/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013232 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013233 * @item: the complex/simple type definition
13234 * @ctxt: the parser context
13235 * @name: the name
13236 *
13237 * Checks for circular type definitions.
13238 */
13239static void
13240xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013241 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013242 const xmlChar * name ATTRIBUTE_UNUSED)
13243{
13244 if ((item == NULL) ||
13245 ((item->type != XML_SCHEMA_TYPE_COMPLEX) &&
13246 (item->type != XML_SCHEMA_TYPE_SIMPLE)))
13247 return;
13248 xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType);
13249
13250}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013251
13252/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013253 * xmlSchemaResolveTypeDefs:
13254 * @item: the complex/simple type definition
13255 * @ctxt: the parser context
13256 * @name: the name
13257 *
13258 * Checks for circular type definitions.
13259 */
13260static void
13261xmlSchemaResolveTypeDefs(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013262 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013263 const xmlChar * name ATTRIBUTE_UNUSED)
13264{
13265 if (typeDef == NULL)
13266 return;
13267
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013268 /*
13269 * Resolve the base type.
13270 */
13271 if (typeDef->baseType == NULL) {
13272 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
13273 typeDef->base, typeDef->baseNs);
13274 if (typeDef->baseType == NULL) {
13275 xmlSchemaPResCompAttrErr(ctxt,
13276 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013277 typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013278 "base", typeDef->base, typeDef->baseNs,
13279 XML_SCHEMA_TYPE_SIMPLE, NULL);
13280 return;
13281 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013282 }
13283 if (IS_SIMPLE_TYPE(typeDef)) {
13284 if (VARIETY_UNION(typeDef)) {
13285 /*
13286 * Resolve the memberTypes.
13287 */
13288 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
13289 return;
13290 } else if (VARIETY_LIST(typeDef)) {
13291 /*
13292 * Resolve the itemType.
13293 */
13294 if ((typeDef->subtypes == NULL) && (typeDef->ref != NULL)) {
13295 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
13296 typeDef->ref, typeDef->refNs);
13297 if ((typeDef->subtypes == NULL) ||
13298 (! IS_SIMPLE_TYPE(typeDef->subtypes))) {
13299 typeDef->subtypes = NULL;
13300 xmlSchemaPResCompAttrErr(ctxt,
13301 XML_SCHEMAP_SRC_RESOLVE,
13302 typeDef, typeDef->node,
13303 "itemType", typeDef->ref, typeDef->refNs,
13304 XML_SCHEMA_TYPE_SIMPLE, NULL);
13305 }
13306 }
13307 return;
13308 }
13309 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013310}
13311
13312
13313
13314/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013315 * xmlSchemaCheckSTPropsCorrect:
13316 * @ctxt: the schema parser context
13317 * @type: the simple type definition
13318 *
13319 * Checks st-props-correct.
13320 *
13321 * Returns 0 if the properties are correct,
13322 * if not, a positive error code and -1 on internal
13323 * errors.
13324 */
13325static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013326xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013327 xmlSchemaTypePtr type)
13328{
13329 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
13330 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013331 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013332
Daniel Veillardc0826a72004-08-10 14:17:33 +000013333 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013334 /*
13335 * Schema Component Constraint: Simple Type Definition Properties Correct
13336 *
13337 * NOTE: This is somehow redundant, since we actually built a simple type
13338 * to have all the needed information; this acts as an self test.
13339 */
13340 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13341 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013342 /* Base type: If the datatype has been ·derived· by ·restriction·
13343 * then the Simple Type Definition component from which it is ·derived·,
13344 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013345 */
13346 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013347 /*
13348 * TODO: Think about: "modulo the impact of Missing
13349 * Sub-components (§5.3)."
13350 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013351 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013352 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013353 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013354 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013355 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013356
Daniel Veillard01fa6152004-06-29 17:04:39 +000013357 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013358 if (! IS_SIMPLE_TYPE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013359 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013360 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013361 NULL, type, NULL,
13362 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013363 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013364 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013365 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13366 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013367 if ( (VARIETY_LIST(type) || VARIETY_UNION(type)) &&
13368 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) &&
13369 (! IS_ANY_SIMPLE_TYPE(baseType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013370 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013371 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013372 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013373 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013374 "the simple ur-type definition as base type, not '%s'",
13375 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013376 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013377 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13378 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013379 /*
13380 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013381 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013382 if ((! VARIETY_ATOMIC(type)) && (! VARIETY_UNION(type)) &&
13383 (! VARIETY_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013384 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013385 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013386 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013387 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013388 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13389 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013390 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013391
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013392 /*
13393 * 3 The {final} of the {base type definition} must not contain restriction.
13394 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013395 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013396 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
13397 xmlSchemaPCustomErr(ctxt,
13398 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013399 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013400 "The 'final' of its base type '%s' must not contain "
13401 "'restriction'",
13402 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013403 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013404 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013405 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013406
13407 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013408 * 2 All simple type definitions must be derived ultimately from the ·simple
13409 * ur-type definition (so· circular definitions are disallowed). That is, it
13410 * must be possible to reach a built-in primitive datatype or the ·simple
13411 * ur-type definition· by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013412 *
13413 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000013414 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013415 return (0);
13416}
13417
13418/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013419 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013420 * @ctxt: the schema parser context
13421 * @type: the simple type definition
13422 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013423 * Schema Component Constraint:
13424 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
13425
13426 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013427 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013428 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013429 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013430 * a positive error code otherwise.
13431 */
13432static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013433xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013434 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013435{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013436 xmlChar *str = NULL;
13437
Daniel Veillard01fa6152004-06-29 17:04:39 +000013438 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013439 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13440 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013441 return (-1);
13442 }
13443
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013444 if (VARIETY_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013445 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013446 /*
13447 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000013448 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013449 */
13450 if (! VARIETY_ATOMIC(type->baseType)) {
13451 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013452 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013453 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013454 "The base type '%s' is not an atomic simple type",
13455 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013456 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013457 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
13458 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013459 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000013460 * restriction.
13461 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013462 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013463 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013464 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013465 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013466 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013467 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013468 "The final of its base type '%s' must not contain 'restriction'",
13469 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013470 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013471 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
13472 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013473
13474 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013475 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013476 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013477 * Primitive datatypes.
13478 */
13479 if (type->facets != NULL) {
13480 xmlSchemaFacetPtr facet;
13481 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013482
Daniel Veillard01fa6152004-06-29 17:04:39 +000013483 primitive = xmlSchemaGetPrimitiveType(type);
13484 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013485 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13486 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013487 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013488 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013489 facet = type->facets;
13490 do {
13491 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013492 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013493 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013494 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013495 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013496 }
13497 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013498 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013499 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013500 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013501 }
13502 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013503 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
13504 * of the {base type definition} (call this BF),then the DF's {value}
13505 * must be a valid restriction of BF's {value} as defined in
13506 * [XML Schemas: Datatypes]."
13507 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013508 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013509 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013510 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013511 } else if (VARIETY_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013512 xmlSchemaTypePtr itemType = NULL;
13513
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013514 itemType = type->subtypes;
13515 if ((itemType == NULL) || (! IS_SIMPLE_TYPE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013516 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13517 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013518 return (-1);
13519 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013520 if (IS_NOT_TYPEFIXED(itemType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013521 xmlSchemaTypeFixup(itemType, pctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013522 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013523 * 2.1 The {item type definition} must have a {variety} of atomic or
13524 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013525 * must be atomic).
13526 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013527 if ((! VARIETY_ATOMIC(itemType)) &&
13528 (! VARIETY_UNION(itemType))) {
13529 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013530 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013531 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013532 "The item type '%s' does not have a variety of atomic or union",
13533 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013534 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013535 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013536 } else if (VARIETY_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013537 xmlSchemaTypeLinkPtr member;
13538
13539 member = itemType->memberTypes;
13540 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013541 if (! VARIETY_ATOMIC(member->type)) {
13542 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013543 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013544 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013545 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013546 "member type '%s' of this item type is not atomic",
13547 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013548 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013549 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
13550 }
13551 member = member->next;
13552 }
13553 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013554
13555 if (IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013556 xmlSchemaFacetPtr facet;
13557 /*
13558 * This is the case if we have: <simpleType><list ..
13559 */
13560 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013561 * 2.3.1
13562 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000013563 * contain list.
13564 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013565 if (xmlSchemaTypeFinalContains(itemType,
13566 XML_SCHEMAS_TYPE_FINAL_LIST)) {
13567 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013568 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013569 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013570 "The final of its item type '%s' must not contain 'list'",
13571 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013572 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013573 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
13574 }
13575 /*
13576 * 2.3.1.2 The {facets} must only contain the whiteSpace
13577 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013578 * OPTIMIZE TODO: the S4S already disallows any facet
13579 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013580 */
13581 if (type->facets != NULL) {
13582 facet = type->facets;
13583 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013584 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013585 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013586 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013587 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013588 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
13589 }
13590 facet = facet->next;
13591 } while (facet != NULL);
13592 }
13593 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013594 * MAYBE TODO: (Hmm, not really) Datatypes states:
13595 * A ·list· datatype can be ·derived· from an ·atomic· datatype
13596 * whose ·lexical space· allows space (such as string or anyURI)or
13597 * a ·union· datatype any of whose {member type definitions}'s
Daniel Veillard01fa6152004-06-29 17:04:39 +000013598 * ·lexical space· allows space.
13599 */
13600 } else {
13601 /*
13602 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013603 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013604 */
13605 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013606 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013607 * 2.3.2.1 The {base type definition} must have a {variety} of list.
13608 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013609 if (! VARIETY_LIST(type->baseType)) {
13610 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013611 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013612 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013613 "The base type '%s' must be a list type",
13614 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013615 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013616 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
13617 }
13618 /*
13619 * 2.3.2.2 The {final} of the {base type definition} must not
13620 * contain restriction.
13621 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013622 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013623 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013624 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013625 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013626 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013627 "The 'final' of the base type '%s' must not contain 'restriction'",
13628 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013629 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013630 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
13631 }
13632 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013633 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000013634 * from the {base type definition}'s {item type definition} given
13635 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
13636 */
13637 {
13638 xmlSchemaTypePtr baseItemType;
13639
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013640 baseItemType = type->baseType->subtypes;
13641 if ((baseItemType == NULL) || (! IS_SIMPLE_TYPE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013642 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13643 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013644 return (-1);
13645 }
13646 if ((itemType != baseItemType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013647 (xmlSchemaCheckCOSSTDerivedOK(itemType,
13648 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013649 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013650 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013651 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013652 NULL, type, NULL,
13653 "The item type '%s' is not validly derived from "
13654 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013655 xmlSchemaGetComponentQName(&str, itemType),
13656 xmlSchemaGetComponentQName(&strBIT, baseItemType),
13657 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013658
13659 FREE_AND_NULL(str)
13660 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013661 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013662 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
13663 }
13664 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013665
Daniel Veillard01fa6152004-06-29 17:04:39 +000013666 if (type->facets != NULL) {
13667 xmlSchemaFacetPtr facet;
13668 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013669 /*
13670 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000013671 * and enumeration facet components are allowed among the {facets}.
13672 */
13673 facet = type->facets;
13674 do {
13675 switch (facet->type) {
13676 case XML_SCHEMA_FACET_LENGTH:
13677 case XML_SCHEMA_FACET_MINLENGTH:
13678 case XML_SCHEMA_FACET_MAXLENGTH:
13679 case XML_SCHEMA_FACET_WHITESPACE:
13680 /*
13681 * TODO: 2.5.1.2 List datatypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013682 * The value of ·whiteSpace· is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013683 */
13684 case XML_SCHEMA_FACET_PATTERN:
13685 case XML_SCHEMA_FACET_ENUMERATION:
13686 break;
13687 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013688 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013689 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013690 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013691 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013692 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000013693 * invalid facets.
13694 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013695 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013696 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013697 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013698 facet = facet->next;
13699 } while (facet != NULL);
13700 if (ok == 0)
13701 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
13702 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013703 * SPEC (2.3.2.5) (same as 1.3.2)
13704 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013705 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013706 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013707 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013708 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013709 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013710 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013711 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013712 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000013713 * atomic or list.
13714 */
13715 xmlSchemaTypeLinkPtr member;
13716
13717 member = type->memberTypes;
13718 while (member != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013719 if (IS_NOT_TYPEFIXED(member->type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013720 xmlSchemaTypeFixup(member->type, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013721
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013722 if ((! VARIETY_ATOMIC(member->type)) &&
13723 (! VARIETY_LIST(member->type))) {
13724 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013725 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013726 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013727 "The member type '%s' is neither an atomic, nor a list type",
13728 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013729 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013730 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
13731 }
13732 member = member->next;
13733 }
13734 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013735 * 3.3.1 If the {base type definition} is the ·simple ur-type
13736 * definition·
Daniel Veillard01fa6152004-06-29 17:04:39 +000013737 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013738 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013739 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013740 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000013741 * {final} which does not contain union.
13742 */
13743 member = type->memberTypes;
13744 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013745 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013746 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013747 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013748 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013749 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013750 "The 'final' of member type '%s' contains 'union'",
13751 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013752 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013753 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
13754 }
13755 member = member->next;
13756 }
13757 /*
13758 * 3.3.1.2 The {facets} must be empty.
13759 */
13760 if (type->facetSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013761 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013762 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013763 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013764 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013765 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
13766 }
13767 } else {
13768 /*
13769 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013770 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013771 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013772 if (! VARIETY_UNION(type->baseType)) {
13773 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013774 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013775 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013776 "The base type '%s' is not a union type",
13777 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013778 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013779 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
13780 }
13781 /*
13782 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
13783 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013784 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013785 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013786 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013787 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013788 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013789 "The 'final' of its base type '%s' must not contain 'restriction'",
13790 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013791 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013792 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
13793 }
13794 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013795 * 3.3.2.3 The {member type definitions}, in order, must be validly
13796 * derived from the corresponding type definitions in the {base
13797 * type definition}'s {member type definitions} given the empty set,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013798 * as defined in Type Derivation OK (Simple) (§3.14.6).
13799 */
13800 {
13801 xmlSchemaTypeLinkPtr baseMember;
13802
13803 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013804 * OPTIMIZE: if the type is restricting, it has no local defined
13805 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013806 * thus a check for equality can be skipped.
13807 */
13808 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013809 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013810 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000013811 * types of it's base type. This check seems not necessary with
13812 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013813 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013814 */
13815 if (type->memberTypes != NULL) {
13816 member = type->memberTypes;
13817 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013818 if ((member == NULL) && (baseMember != NULL)) {
13819 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13820 "different number of member types in base");
13821 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013822 while (member != NULL) {
13823 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013824 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13825 "different number of member types in base");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013826 }
13827 if ((member->type != baseMember->type) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013828 (xmlSchemaCheckCOSSTDerivedOK(
13829 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013830 xmlChar *strBMT = NULL, *strBT = NULL;
13831
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013832 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013833 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
13834 NULL, type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013835 "The member type %s is not validly "
13836 "derived from its corresponding member "
13837 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013838 xmlSchemaGetComponentQName(&str, member->type),
13839 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
13840 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013841 FREE_AND_NULL(str)
13842 FREE_AND_NULL(strBMT)
13843 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013844 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013845 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013846 member = member->next;
13847 baseMember = baseMember->next;
13848 }
13849 }
13850 }
13851 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013852 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000013853 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013854 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013855 if (type->facets != NULL) {
13856 xmlSchemaFacetPtr facet;
13857 int ok = 1;
13858
13859 facet = type->facets;
13860 do {
13861 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
13862 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013863 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013864 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013865 NULL, type, facet);
13866 ok = 0;
13867 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013868 facet = facet->next;
13869 } while (facet != NULL);
13870 if (ok == 0)
13871 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013872
Daniel Veillard01fa6152004-06-29 17:04:39 +000013873 }
13874 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013875 * SPEC (3.3.2.5) (same as 1.3.2)
13876 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013877 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013878 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013879 */
13880 }
13881 }
13882
13883 return (0);
13884}
13885
13886/**
13887 * xmlSchemaCheckSRCSimpleType:
13888 * @ctxt: the schema parser context
13889 * @type: the simple type definition
13890 *
13891 * Checks crc-simple-type constraints.
13892 *
13893 * Returns 0 if the constraints are satisfied,
13894 * if not a positive error code and -1 on internal
13895 * errors.
13896 */
13897static int
13898xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
13899 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013900{
13901 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013902 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013903 * must satisfy the conditions set out in Constraints on Simple Type
13904 * Definition Schema Components (§3.14.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013905 */
13906 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
13907 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
13908 /*
13909 * TODO: Removed this, since it got annoying to get an
13910 * extra error report, if anything failed until now.
13911 * Enable this if needed.
13912 */
13913 /*
13914 xmlSchemaPErr(ctxt, type->node,
13915 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013916 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000013917 "on simple type definitions.\n",
13918 type->name, NULL);
13919 */
13920 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
13921 }
13922
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013923 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013924 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013925 * src-simple-type.2 If the <restriction> alternative is chosen,
13926 * either it must have a base [attribute] or a <simpleType> among its
Daniel Veillard01fa6152004-06-29 17:04:39 +000013927 * [children], but not both.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013928 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013929 /*
13930 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013931 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013932 */
13933 } else if (VARIETY_LIST(type)) {
13934 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
13935 * an itemType [attribute] or a <simpleType> among its [children],
Daniel Veillard01fa6152004-06-29 17:04:39 +000013936 * but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013937 *
13938 * REMOVED: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013939 */
13940 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013941 xmlSchemaTypeLinkPtr member;
13942 xmlSchemaTypePtr ancestor, anySimpleType;
13943
13944 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13945
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013946 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
13947 * the <union> alternative is chosen, there must not be any entries
13948 * in the memberTypes [attribute] at any depth which resolve to the
Daniel Veillard01fa6152004-06-29 17:04:39 +000013949 * component corresponding to the <simpleType>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013950 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013951 member = type->memberTypes;
13952 while (member != NULL) {
13953 ancestor = member->type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013954 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013955 if (ancestor == type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013956 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013957 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013958 NULL, type, NULL,
13959 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013960 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013961 }
13962 if (IS_NOT_TYPEFIXED(ancestor))
13963 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013964 if (VARIETY_LIST(ancestor)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013965 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000013966 * TODO, FIXME: Although a list simple type must not have a union ST
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013967 * type as item type, which in turn has a list ST as member
13968 * type, we will assume this here as well, since this check
Daniel Veillard01fa6152004-06-29 17:04:39 +000013969 * was not yet performed.
13970 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013971 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013972
Daniel Veillard01fa6152004-06-29 17:04:39 +000013973 ancestor = ancestor->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013974 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013975 member = member->next;
13976 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013977 }
13978
13979 return (0);
13980}
13981
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013982static int
13983xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
13984{
13985 if (ctxt->vctxt == NULL) {
13986 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
13987 if (ctxt->vctxt == NULL) {
13988 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013989 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013990 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013991 "failed to create a temp. validation context.\n",
13992 NULL, NULL);
13993 return (-1);
13994 }
13995 /* TODO: Pass user data. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013996 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013997 }
13998 return (0);
13999}
14000
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014001static int
14002xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
14003 xmlNodePtr node,
14004 xmlSchemaTypePtr type,
14005 const xmlChar *value,
14006 xmlSchemaValPtr *retVal,
14007 int fireErrors,
14008 int normalize,
14009 int isNormalized);
14010
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014011/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014012 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014013 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014014 * @type: the simple type definition
14015 * @value: the default value
14016 * @node: an optional node (the holder of the value)
14017 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014018 * Schema Component Constraint: Element Default Valid (Immediate)
14019 * (cos-valid-default)
14020 * This will be used by the parser only. For the validator there's
14021 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014022 *
14023 * Returns 0 if the constraints are satisfied,
14024 * if not, a positive error code and -1 on internal
14025 * errors.
14026 */
14027static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014028xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
14029 xmlNodePtr node,
14030 xmlSchemaTypePtr type,
14031 const xmlChar *value,
14032 xmlSchemaValPtr *val)
14033{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014034 int ret = 0;
14035
14036 /*
14037 * cos-valid-default:
14038 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014039 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014040 * definition the appropriate case among the following must be true:
14041 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014042 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014043 /*
14044 * Complex type.
14045 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014046 * SPEC (2.1) "its {content type} must be a simple type definition
14047 * or mixed."
14048 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014049 * type}'s particle must be ·emptiable· as defined by
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014050 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014051 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014052 if ((! HAS_SIMPLE_CONTENT(type)) &&
14053 ((! HAS_MIXED_CONTENT(type)) || (! IS_PARTICLE_EMPTIABLE(type)))) {
14054 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014055 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014056 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014057 NULL, type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014058 "For a string to be a valid default, the type definition "
14059 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014060 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014061 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
14062 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014063 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014064 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014065 * 1 If the type definition is a simple type definition, then the string
14066 * must be ·valid· with respect to that definition as defined by String
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014067 * Valid (§3.14.4).
14068 *
14069 * AND
14070 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014071 * 2.2.1 If the {content type} is a simple type definition, then the
14072 * string must be ·valid· with respect to that simple type definition
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014073 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014074 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014075 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014076 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14077 type, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014078 else if (HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014079 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14080 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014081 else
14082 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014083
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014084 if (ret < 0) {
14085 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
14086 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014087 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014088
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014089 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000014090}
14091
14092/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014093 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000014094 * @ctxt: the schema parser context
14095 * @type: the complex type definition
14096 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014097 *.(4.6) Constraints on Complex Type Definition Schema Components
14098 * Schema Component Constraint:
14099 * Complex Type Definition Properties Correct (ct-props-correct)
14100 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000014101 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014102 * Returns 0 if the constraints are satisfied, a positive
14103 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000014104 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014105static int
14106xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
14107 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000014108{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014109 /*
14110 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
14111 *
14112 * SPEC (1) "The values of the properties of a complex type definition must
14113 * be as described in the property tableau in The Complex Type Definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014114 * Schema Component (§3.4.1), modulo the impact of Missing
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014115 * Sub-components (§5.3)."
14116 */
14117 if ((type->baseType != NULL) &&
14118 (IS_SIMPLE_TYPE(type->baseType)) &&
14119 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
14120 /*
14121 * SPEC (2) "If the {base type definition} is a simple type definition,
14122 * the {derivation method} must be extension."
14123 */
14124 xmlSchemaPCustomErr(pctxt,
14125 XML_SCHEMAP_SRC_CT_1,
14126 NULL, type, NULL,
14127 "If the base type is a simple type, the derivation method must be "
14128 "'extension'", NULL);
14129 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014130 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014131 /*
14132 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
14133 * definition·. That is, it must be possible to reach the ·ur-type
14134 * definition by repeatedly following the {base type definition}."
14135 *
14136 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
14137 *
14138 * SPEC (4) "Two distinct attribute declarations in the {attribute uses}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014139 * must not have identical {name}s and {target namespace}s."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014140 * SPEC (5) "Two distinct attribute declarations in the {attribute uses}
14141 * must not have {type definition}s which are or are derived from ID."
14142 *
14143 * NOTE (4) and (5) are done in xmlSchemaBuildAttributeValidation().
14144 */
14145 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014146}
14147
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014148static int
14149xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
14150 xmlSchemaTypePtr typeB)
14151{
14152 /*
14153 * TODO: This should implement component-identity
14154 * in the future.
14155 */
14156 if ((typeA == NULL) || (typeB == NULL))
14157 return (0);
14158 return (typeA == typeB);
14159}
14160
14161/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014162 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014163 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014164 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014165 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014166 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014167 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014168 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014169 * Type Derivation OK (Complex) (cos-ct-derived-ok)
14170 *
14171 * STATUS: completed
14172 *
14173 * Returns 0 if the constraints are satisfied, or 1
14174 * if not.
14175 */
14176static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014177xmlSchemaCheckCOSCTDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014178 xmlSchemaTypePtr baseType,
14179 int set)
14180{
14181 int equal = xmlSchemaAreEqualTypes(type, baseType);
14182 /* TODO: Error codes. */
14183 /*
14184 * SPEC "For a complex type definition (call it D, for derived)
14185 * to be validly derived from a type definition (call this
14186 * B, for base) given a subset of {extension, restriction}
14187 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014188 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014189 if (! equal) {
14190 /*
14191 * SPEC (1) "If B and D are not the same type definition, then the
14192 * {derivation method} of D must not be in the subset."
14193 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014194 if (((set & SUBSET_EXTENSION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014195 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014196 ((set & SUBSET_RESTRICTION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014197 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014198 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014199 } else {
14200 /*
14201 * SPEC (2.1) "B and D must be the same type definition."
14202 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014203 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014204 }
14205 /*
14206 * SPEC (2.2) "B must be D's {base type definition}."
14207 */
14208 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014209 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014210 /*
14211 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
14212 * definition·."
14213 */
14214 if (IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014215 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014216
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014217 if (IS_COMPLEX_TYPE(type->baseType)) {
14218 /*
14219 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
14220 * must be validly derived from B given the subset as defined by this
14221 * constraint."
14222 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014223 return (xmlSchemaCheckCOSCTDerivedOK(type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014224 baseType, set));
14225 } else {
14226 /*
14227 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
14228 * must be validly derived from B given the subset as defined in Type
14229 * Derivation OK (Simple) (§3.14.6).
14230 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014231 return (xmlSchemaCheckCOSSTDerivedOK(type->baseType, baseType, set));
14232 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014233}
14234
14235/**
14236 * xmlSchemaCheckCOSDerivedOK:
14237 * @type: the derived simple type definition
14238 * @baseType: the base type definition
14239 *
14240 * Calls:
14241 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014242 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014243 * Checks wheter @type can be validly derived from @baseType.
14244 *
14245 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014246 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014247static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014248xmlSchemaCheckCOSDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014249 xmlSchemaTypePtr baseType,
14250 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014251{
14252 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014253 return (xmlSchemaCheckCOSSTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014254 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014255 return (xmlSchemaCheckCOSCTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014256}
14257
William M. Brack2f2a6632004-08-20 23:09:47 +000014258/**
14259 * xmlSchemaCheckCOSCTExtends:
14260 * @ctxt: the schema parser context
14261 * @type: the complex type definition
14262 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014263 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014264 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014265 * Derivation Valid (Extension) (cos-ct-extends)
14266 *
14267 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014268 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014269 * (1.5)
14270 * (1.4.3.2.2.2) "Particle Valid (Extension)", which is not really needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014271 *
14272 * Returns 0 if the constraints are satisfied, a positive
14273 * error code if not and -1 if an internal error occured.
14274 */
14275static int
14276xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
14277 xmlSchemaTypePtr type)
14278{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014279 xmlSchemaTypePtr base = type->baseType;
14280 /*
14281 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14282 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000014283 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014284 /*
14285 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014286 * then all of the following must be true:"
14287 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014288 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
14289 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014290 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014291 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000014292 */
14293 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14294 xmlSchemaPCustomErr(ctxt,
14295 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14296 NULL, type, NULL,
14297 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014298 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000014299 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14300 }
14301 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014302 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014303 * uses}
14304 * of the complex type definition itself, that is, for every attribute
14305 * use in the {attribute uses} of the {base type definition}, there
14306 * must be an attribute use in the {attribute uses} of the complex
14307 * type definition itself whose {attribute declaration} has the same
14308 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014309 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000014310 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014311 * NOTE (1.2): This will be already satisfied by the way the attribute
14312 * uses are extended in xmlSchemaBuildAttributeValidation(); thus this
14313 * check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014314 */
14315
14316 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014317 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
14318 * definition must also have one, and the base type definition's
14319 * {attribute wildcard}'s {namespace constraint} must be a subset
14320 * of the complex type definition's {attribute wildcard}'s {namespace
14321 * constraint}, as defined by Wildcard Subset (§3.10.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014322 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014323 * NOTE (1.3) This is already checked in
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014324 * xmlSchemaBuildAttributeValidation; thus this check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014325 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014326 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014327 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014328 if ((type->contentTypeDef != NULL) &&
14329 (type->contentTypeDef == base->contentTypeDef)) {
14330 /*
14331 * SPEC (1.4.1) "The {content type} of the {base type definition}
14332 * and the {content type} of the complex type definition itself
14333 * must be the same simple type definition"
14334 * PASS
14335 */
14336 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
14337 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
14338 /*
14339 * SPEC (1.4.2) "The {content type} of both the {base type
14340 * definition} and the complex type definition itself must
14341 * be empty."
14342 * PASS
14343 */
14344 } else {
14345 /*
14346 * SPEC (1.4.3) "All of the following must be true:"
14347 */
14348 if (type->subtypes == NULL) {
14349 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014350 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014351 * definition itself must specify a particle.
14352 */
14353 xmlSchemaPCustomErr(ctxt,
14354 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14355 NULL, type, NULL,
14356 "The content type must specify a particle", NULL);
14357 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14358 }
14359 /*
14360 * SPEC (1.4.3.2) "One of the following must be true:"
14361 */
14362 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14363 /*
14364 * SPEC (1.4.3.2.1) "The {content type} of the {base type
14365 * definition} must be empty.
14366 * PASS
14367 */
14368 } else {
14369 /*
14370 * SPEC (1.4.3.2.2) "All of the following must be true:"
14371 */
14372 if ((type->contentType != base->contentType) ||
14373 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
14374 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
14375 /*
14376 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
14377 * or both must be element-only."
14378 */
14379 xmlSchemaPCustomErr(ctxt,
14380 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14381 NULL, type, NULL,
14382 "The content type of both, the type and its base "
14383 "type, must either 'mixed' or 'element-only'", NULL);
14384 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014385 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014386 /*
14387 * FUTURE TODO SPEC (1.4.3.2.2.2) "The particle of the
14388 * complex type definition must be a ·valid extension·
14389 * of the {base type definition}'s particle, as defined
14390 * in Particle Valid (Extension) (§3.9.6)."
14391 *
14392 * NOTE that we won't check "Particle Valid (Extension)",
14393 * since it is ensured by the derivation process in
14394 * xmlSchemaTypeFixup(). We need to implement this when heading
14395 * for a construction API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014396 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014397 }
14398 /*
14399 * TODO (1.5)
14400 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014401 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014402 } else {
14403 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014404 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014405 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014406 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014407 if (type->contentTypeDef != base) {
14408 /*
14409 * SPEC (2.1) "The {content type} must be the same simple type
14410 * definition."
14411 */
14412 xmlSchemaPCustomErr(ctxt,
14413 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14414 NULL, type, NULL,
14415 "The content type must be the simple base type", NULL);
14416 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14417 }
14418 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14419 /*
14420 * SPEC (2.2) "The {final} of the {base type definition} must not
14421 * contain extension"
14422 * NOTE that this is the same as (1.1).
14423 */
14424 xmlSchemaPCustomErr(ctxt,
14425 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14426 NULL, type, NULL,
14427 "The 'final' of the base type definition "
14428 "contains 'extension'", NULL);
14429 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014430 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014431 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014432 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014433}
14434
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014435/**
14436 * xmlSchemaCheckDerivationOKRestriction:
14437 * @ctxt: the schema parser context
14438 * @type: the complex type definition
14439 *
14440 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014441 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014442 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
14443 *
14444 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014445 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014446 * (5.4.2), (5.2.2.1)
14447 *
14448 * Returns 0 if the constraints are satisfied, a positive
14449 * error code if not and -1 if an internal error occured.
14450 */
14451static int
14452xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
14453 xmlSchemaTypePtr type)
14454{
14455 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014456
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014457 /*
14458 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14459 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014460 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014461 base = type->baseType;
14462 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
14463 /*
14464 * SPEC (1) "The {base type definition} must be a complex type
14465 * definition whose {final} does not contain restriction."
14466 */
14467 xmlSchemaPCustomErr(ctxt,
14468 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14469 NULL, type, NULL,
14470 "The 'final' of the base type definition "
14471 "contains 'restriction'", NULL);
14472 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14473 }
14474 /*
14475 * NOTE (3) and (4) are done in xmlSchemaBuildAttributeValidation().
14476 *
14477 * SPEC (5) "One of the following must be true:"
14478 */
14479 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
14480 /*
14481 * SPEC (5.1) "The {base type definition} must be the
14482 * ·ur-type definition·."
14483 * PASS
14484 */
14485 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14486 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14487 /*
14488 * SPEC (5.2.1) "The {content type} of the complex type definition
14489 * must be a simple type definition"
14490 *
14491 * SPEC (5.2.2) "One of the following must be true:"
14492 */
14493 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14494 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14495 /*
14496 * SPEC (5.2.2.1) "The {content type} of the {base type
14497 * definition} must be a simple type definition from which
14498 * the {content type} is validly derived given the empty
14499 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
14500 * URGENT TODO
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014501 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014502 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14503 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014504 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014505 /*
14506 * SPEC (5.2.2.2) "The {base type definition} must be mixed
14507 * and have a particle which is ·emptiable· as defined in
14508 * Particle Emptiable (§3.9.6)."
14509 * PASS
14510 */
14511 } else {
14512 xmlSchemaPCustomErr(ctxt,
14513 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14514 NULL, type, NULL,
14515 "The content type of the base type must be either "
14516 "a simple type or 'mixed' and an emptiable particle", NULL);
14517 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14518 }
14519 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14520 /*
14521 * SPEC (5.3.1) "The {content type} of the complex type itself must
14522 * be empty"
14523 */
14524 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14525 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014526 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014527 * definition} must also be empty."
14528 * PASS
14529 */
14530 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
14531 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
14532 xmlSchemaIsParticleEmptiable(
14533 (xmlSchemaParticlePtr) base->subtypes)) {
14534 /*
14535 * SPEC (5.3.2.2) "The {content type} of the {base type
14536 * definition} must be elementOnly or mixed and have a particle
14537 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
14538 * PASS
14539 */
14540 } else {
14541 xmlSchemaPCustomErr(ctxt,
14542 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14543 NULL, type, NULL,
14544 "The content type of the base type must be either "
14545 "empty or 'mixed' (or 'elements-only') and an emptiable "
14546 "particle", NULL);
14547 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14548 }
14549 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014550 HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014551 /*
14552 * SPEC (5.4.1.1) "The {content type} of the complex type definition
14553 * itself must be element-only"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014554 */
14555 if (HAS_MIXED_CONTENT(type) && (! HAS_MIXED_CONTENT(base))) {
14556 /*
14557 * SPEC (5.4.1.2) "The {content type} of the complex type
14558 * definition itself and of the {base type definition} must be
14559 * mixed"
14560 */
14561 xmlSchemaPCustomErr(ctxt,
14562 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14563 NULL, type, NULL,
14564 "If the content type is 'mixed', then the content type of the "
14565 "base type must also be 'mixed'", NULL);
14566 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14567 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014568 /*
14569 * SPEC (5.4.2) "The particle of the complex type definition itself
14570 * must be a ·valid restriction· of the particle of the {content
14571 * type} of the {base type definition} as defined in Particle Valid
14572 * (Restriction) (§3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014573 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014574 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014575 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014576 } else {
14577 xmlSchemaPCustomErr(ctxt,
14578 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14579 NULL, type, NULL,
14580 "The type is not a valid restriction of its base type", NULL);
14581 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14582 }
14583 return (0);
14584}
14585
14586/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014587 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014588 * @ctxt: the schema parser context
14589 * @type: the complex type definition
14590 *
14591 * (3.4.6) Constraints on Complex Type Definition Schema Components
14592 *
14593 * Returns 0 if the constraints are satisfied, a positive
14594 * error code if not and -1 if an internal error occured.
14595 */
14596static int
14597xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
14598 xmlSchemaTypePtr type)
14599{
14600 int ret;
14601 /*
14602 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014603 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014604 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
14605 if (ret != 0)
14606 return (ret);
14607 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
14608 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
14609 else
14610 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
14611 return (ret);
14612}
14613
14614/**
14615 * xmlSchemaCheckSRCCT:
14616 * @ctxt: the schema parser context
14617 * @type: the complex type definition
14618 *
14619 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014620 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014621 * Complex Type Definition Representation OK (src-ct)
14622 *
14623 * Returns 0 if the constraints are satisfied, a positive
14624 * error code if not and -1 if an internal error occured.
14625 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014626static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014627xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014628 xmlSchemaTypePtr type)
14629{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014630 xmlSchemaTypePtr base;
14631 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014632
14633 /*
14634 * TODO: Adjust the error codes here, as I used
14635 * XML_SCHEMAP_SRC_CT_1 only yet.
14636 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014637 base = type->baseType;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014638 if (! HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014639 /*
14640 * 1 If the <complexContent> alternative is chosen, the type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014641 * ·resolved· to by the ·actual value· of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014642 * must be a complex type definition;
14643 */
14644 if (! IS_COMPLEX_TYPE(base)) {
14645 xmlChar *str = NULL;
14646 xmlSchemaPCustomErr(ctxt,
14647 XML_SCHEMAP_SRC_CT_1,
14648 NULL, type, type->node,
14649 "If using <complexContent>, the base type is expected to be "
14650 "a complex type. The base type '%s' is a simple type",
14651 xmlSchemaFormatQName(&str, base->targetNamespace,
14652 base->name));
14653 FREE_AND_NULL(str)
14654 return (XML_SCHEMAP_SRC_CT_1);
14655 }
14656 } else {
14657 /*
14658 * SPEC
14659 * 2 If the <simpleContent> alternative is chosen, all of the
14660 * following must be true:
14661 * 2.1 The type definition ·resolved· to by the ·actual value· of the
14662 * base [attribute] must be one of the following:
14663 */
14664 if (IS_SIMPLE_TYPE(base)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014665 if ((type->flags &
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014666 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0) {
14667 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014668 /*
14669 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014670 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014671 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014672 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014673 xmlSchemaPCustomErr(ctxt,
14674 XML_SCHEMAP_SRC_CT_1,
14675 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014676 "If using <simpleContent> and <restriction>, the base "
14677 "type must be a complex type. The base type '%s' is "
14678 "a simple type",
14679 xmlSchemaFormatQName(&str, base->targetNamespace,
14680 base->name));
14681 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014682 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014683 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014684 } else {
14685 /* Base type is a complex type. */
14686 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14687 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14688 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014689 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014690 * simple type definition;
14691 * PASS
14692 */
14693 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014694 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014695 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014696 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014697 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014698 type->name);
14699 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014700 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014701 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14702 (type->flags &
14703 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014704
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014705 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014706 * 2.1.2 only if the <restriction> alternative is also
14707 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014708 * is mixed and a particle emptiable.
14709 */
14710 if (! xmlSchemaIsParticleEmptiable(
14711 (xmlSchemaParticlePtr) base->subtypes)) {
14712 ret = XML_SCHEMAP_SRC_CT_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014713 } else
14714 /*
14715 * Attention: at this point the <simpleType> child is in
14716 * ->contentTypeDef (put there during parsing).
14717 */
14718 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014719 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014720 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014721 * 2.2 If clause 2.1.2 above is satisfied, then there
14722 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014723 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014724 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014725 /* TODO: Change error code to ..._SRC_CT_2_2. */
14726 xmlSchemaPCustomErr(ctxt,
14727 XML_SCHEMAP_SRC_CT_1,
14728 NULL, type, NULL,
14729 "A <simpleType> is expected among the children "
14730 "of <restriction>, if <simpleContent> is used and "
14731 "the base type '%s' is a complex type",
14732 xmlSchemaFormatQName(&str, base->targetNamespace,
14733 base->name));
14734 FREE_AND_NULL(str)
14735 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014736 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014737 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014738 ret = XML_SCHEMAP_SRC_CT_1;
14739 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014740 }
14741 if (ret > 0) {
14742 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014743 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014744 xmlSchemaPCustomErr(ctxt,
14745 XML_SCHEMAP_SRC_CT_1,
14746 NULL, type, NULL,
14747 "If <simpleContent> and <restriction> is used, the "
14748 "base type must be a simple type or a complex type with "
14749 "mixed content and particle emptiable. The base type "
14750 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014751 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014752 base->name));
14753 } else {
14754 xmlSchemaPCustomErr(ctxt,
14755 XML_SCHEMAP_SRC_CT_1,
14756 NULL, type, NULL,
14757 "If <simpleContent> and <extension> is used, the "
14758 "base type must be a simple type. The base type '%s' "
14759 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014760 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014761 base->name));
14762 }
14763 FREE_AND_NULL(str)
14764 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014765 }
14766 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014767 * SPEC (3) "The corresponding complex type definition component must
14768 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014769 * Definition Schema Components (§3.4.6);"
14770 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014771 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014772 /*
14773 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014774 * above for {attribute wildcard} is satisfied, the intensional
14775 * intersection must be expressible, as defined in Attribute Wildcard
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014776 * Intersection (§3.10.6).
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014777 * NOTE (4) is done in xmlSchemaBuildAttributeValidation().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014778 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014779 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014780}
William M. Brack2f2a6632004-08-20 23:09:47 +000014781
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014782#ifdef ENABLE_PARTICLE_RESTRICTION
14783/**
14784 * xmlSchemaCheckParticleRangeOK:
14785 * @ctxt: the schema parser context
14786 * @type: the complex type definition
14787 *
14788 * (3.9.6) Constraints on Particle Schema Components
14789 * Schema Component Constraint:
14790 * Occurrence Range OK (range-ok)
14791 *
14792 * STATUS: complete
14793 *
14794 * Returns 0 if the constraints are satisfied, a positive
14795 * error code if not and -1 if an internal error occured.
14796 */
14797static int
14798xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
14799 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014800{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014801 if (rmin < bmin)
14802 return (1);
14803 if ((bmax != UNBOUNDED) &&
14804 (rmax > bmax))
14805 return (1);
14806 return (0);
14807}
14808
14809/**
14810 * xmlSchemaCheckRCaseNameAndTypeOK:
14811 * @ctxt: the schema parser context
14812 * @r: the restricting element declaration particle
14813 * @b: the base element declaration particle
14814 *
14815 * (3.9.6) Constraints on Particle Schema Components
14816 * Schema Component Constraint:
14817 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
14818 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014819 *
14820 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014821 * MISSING (3.2.3)
14822 * CLARIFY: (3.2.2)
14823 *
14824 * Returns 0 if the constraints are satisfied, a positive
14825 * error code if not and -1 if an internal error occured.
14826 */
14827static int
14828xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
14829 xmlSchemaParticlePtr r,
14830 xmlSchemaParticlePtr b)
14831{
14832 xmlSchemaElementPtr elemR, elemB;
14833
14834 /* TODO: Error codes (rcase-NameAndTypeOK). */
14835 elemR = (xmlSchemaElementPtr) r->children;
14836 elemB = (xmlSchemaElementPtr) b->children;
14837 /*
14838 * SPEC (1) "The declarations' {name}s and {target namespace}s are
14839 * the same."
14840 */
14841 if ((elemR != elemB) &&
14842 ((! xmlStrEqual(elemR->name, elemB->name)) ||
14843 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
14844 return (1);
14845 /*
14846 * SPEC (2) "R's occurrence range is a valid restriction of B's
14847 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
14848 */
14849 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
14850 b->minOccurs, b->maxOccurs) != 0)
14851 return (1);
14852 /*
14853 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
14854 * {scope} are global."
14855 */
14856 if (elemR == elemB)
14857 return (0);
14858 /*
14859 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
14860 */
14861 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
14862 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
14863 return (1);
14864 /*
14865 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
14866 * or is not fixed, or R's declaration's {value constraint} is fixed
14867 * with the same value."
14868 */
14869 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
14870 ((elemR->value == NULL) ||
14871 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
14872 /* TODO: Equality of the initial value or normalized or canonical? */
14873 (! xmlStrEqual(elemR->value, elemB->value))))
14874 return (1);
14875 /*
14876 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
14877 * definitions} is a subset of B's declaration's {identity-constraint
14878 * definitions}, if any."
14879 */
14880 if (elemB->idcs != NULL) {
14881 /* TODO */
14882 }
14883 /*
14884 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
14885 * superset of B's declaration's {disallowed substitutions}."
14886 */
14887 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
14888 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
14889 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
14890 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
14891 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
14892 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
14893 return (1);
14894 /*
14895 * SPEC (3.2.5) "R's {type definition} is validly derived given
14896 * {extension, list, union} from B's {type definition}"
14897 *
14898 * BADSPEC TODO: What's the point of adding "list" and "union" to the
14899 * set, if the corresponding constraints handle "restriction" and
14900 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014901 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014902 */
14903 {
14904 int set = 0;
14905
14906 set |= SUBSET_EXTENSION;
14907 set |= SUBSET_LIST;
14908 set |= SUBSET_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014909 if (xmlSchemaCheckCOSDerivedOK(elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014910 elemB->subtypes, set) != 0)
14911 return (1);
14912 }
14913 return (0);
14914}
14915
14916/**
14917 * xmlSchemaCheckRCaseNSCompat:
14918 * @ctxt: the schema parser context
14919 * @r: the restricting element declaration particle
14920 * @b: the base wildcard particle
14921 *
14922 * (3.9.6) Constraints on Particle Schema Components
14923 * Schema Component Constraint:
14924 * Particle Derivation OK (Elt:Any -- NSCompat)
14925 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014926 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014927 * STATUS: complete
14928 *
14929 * Returns 0 if the constraints are satisfied, a positive
14930 * error code if not and -1 if an internal error occured.
14931 */
14932static int
14933xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
14934 xmlSchemaParticlePtr r,
14935 xmlSchemaParticlePtr b)
14936{
14937 /* TODO:Error codes (rcase-NSCompat). */
14938 /*
14939 * SPEC "For an element declaration particle to be a ·valid restriction·
14940 * of a wildcard particle all of the following must be true:"
14941 *
14942 * SPEC (1) "The element declaration's {target namespace} is ·valid·
14943 * with respect to the wildcard's {namespace constraint} as defined by
14944 * Wildcard allows Namespace Name (§3.10.4)."
14945 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014946 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014947 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
14948 return (1);
14949 /*
14950 * SPEC (2) "R's occurrence range is a valid restriction of B's
14951 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
14952 */
14953 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
14954 b->minOccurs, b->maxOccurs) != 0)
14955 return (1);
14956
14957 return (0);
14958}
14959
14960/**
14961 * xmlSchemaCheckRCaseRecurseAsIfGroup:
14962 * @ctxt: the schema parser context
14963 * @r: the restricting element declaration particle
14964 * @b: the base model group particle
14965 *
14966 * (3.9.6) Constraints on Particle Schema Components
14967 * Schema Component Constraint:
14968 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
14969 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014970 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014971 * STATUS: TODO
14972 *
14973 * Returns 0 if the constraints are satisfied, a positive
14974 * error code if not and -1 if an internal error occured.
14975 */
14976static int
14977xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
14978 xmlSchemaParticlePtr r,
14979 xmlSchemaParticlePtr b)
14980{
14981 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
14982 TODO
14983 return (0);
14984}
14985
14986/**
14987 * xmlSchemaCheckRCaseNSSubset:
14988 * @ctxt: the schema parser context
14989 * @r: the restricting wildcard particle
14990 * @b: the base wildcard particle
14991 *
14992 * (3.9.6) Constraints on Particle Schema Components
14993 * Schema Component Constraint:
14994 * Particle Derivation OK (Any:Any -- NSSubset)
14995 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014996 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014997 * STATUS: complete
14998 *
14999 * Returns 0 if the constraints are satisfied, a positive
15000 * error code if not and -1 if an internal error occured.
15001 */
15002static int
15003xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
15004 xmlSchemaParticlePtr r,
15005 xmlSchemaParticlePtr b,
15006 int isAnyTypeBase)
15007{
15008 /* TODO: Error codes (rcase-NSSubset). */
15009 /*
15010 * SPEC (1) "R's occurrence range is a valid restriction of B's
15011 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15012 */
15013 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15014 b->minOccurs, b->maxOccurs))
15015 return (1);
15016 /*
15017 * SPEC (2) "R's {namespace constraint} must be an intensional subset
15018 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
15019 */
15020 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
15021 (xmlSchemaWildcardPtr) b->children))
15022 return (1);
15023 /*
15024 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
15025 * definition·, R's {process contents} must be identical to or stronger
15026 * than B's {process contents}, where strict is stronger than lax is
15027 * stronger than skip."
15028 */
15029 if (! isAnyTypeBase) {
15030 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
15031 ((xmlSchemaWildcardPtr) b->children)->processContents)
15032 return (1);
15033 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015034
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015035 return (0);
15036}
15037
15038/**
15039 * xmlSchemaCheckCOSParticleRestrict:
15040 * @ctxt: the schema parser context
15041 * @type: the complex type definition
15042 *
15043 * (3.9.6) Constraints on Particle Schema Components
15044 * Schema Component Constraint:
15045 * Particle Valid (Restriction) (cos-particle-restrict)
15046 *
15047 * STATUS: TODO
15048 *
15049 * Returns 0 if the constraints are satisfied, a positive
15050 * error code if not and -1 if an internal error occured.
15051 */
15052static int
15053xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
15054 xmlSchemaParticlePtr r,
15055 xmlSchemaParticlePtr b)
15056{
15057 int ret = 0;
15058
15059 /*part = GET_PARTICLE(type);
15060 basePart = GET_PARTICLE(base);
15061 */
15062
15063 TODO
15064
15065 /*
15066 * SPEC (1) "They are the same particle."
15067 */
15068 if (r == b)
15069 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015070
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015071
15072 return (0);
15073}
15074
15075/**
15076 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
15077 * @ctxt: the schema parser context
15078 * @r: the model group particle
15079 * @b: the base wildcard particle
15080 *
15081 * (3.9.6) Constraints on Particle Schema Components
15082 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015083 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015084 * NSRecurseCheckCardinality)
15085 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015086 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015087 * STATUS: TODO: subst-groups
15088 *
15089 * Returns 0 if the constraints are satisfied, a positive
15090 * error code if not and -1 if an internal error occured.
15091 */
15092static int
15093xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
15094 xmlSchemaParticlePtr r,
15095 xmlSchemaParticlePtr b)
15096{
15097 xmlSchemaParticlePtr part;
15098 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
15099 if ((r->children == NULL) || (r->children->children == NULL))
15100 return (-1);
15101 /*
15102 * SPEC "For a group particle to be a ·valid restriction· of a
15103 * wildcard particle..."
15104 *
15105 * SPEC (1) "Every member of the {particles} of the group is a ·valid
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015106 * restriction· of the wildcard as defined by
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015107 * Particle Valid (Restriction) (§3.9.6)."
15108 */
15109 part = (xmlSchemaParticlePtr) r->children->children;
15110 do {
15111 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
15112 return (1);
15113 part = (xmlSchemaParticlePtr) part->next;
15114 } while (part != NULL);
15115 /*
15116 * SPEC (2) "The effective total range of the group [...] is a
15117 * valid restriction of B's occurrence range as defined by
15118 * Occurrence Range OK (§3.9.6)."
15119 */
15120 if (xmlSchemaCheckParticleRangeOK(
15121 xmlSchemaGetParticleTotalRangeMin(r),
15122 xmlSchemaGetParticleTotalRangeMax(r),
15123 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015124 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015125 return (0);
15126}
15127
15128/**
15129 * xmlSchemaCheckRCaseRecurse:
15130 * @ctxt: the schema parser context
15131 * @r: the <all> or <sequence> model group particle
15132 * @b: the base <all> or <sequence> model group particle
15133 *
15134 * (3.9.6) Constraints on Particle Schema Components
15135 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015136 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015137 Recurse)
15138 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015139 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015140 * STATUS: ?
15141 * TODO: subst-groups
15142 *
15143 * Returns 0 if the constraints are satisfied, a positive
15144 * error code if not and -1 if an internal error occured.
15145 */
15146static int
15147xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
15148 xmlSchemaParticlePtr r,
15149 xmlSchemaParticlePtr b)
15150{
15151 /* xmlSchemaParticlePtr part; */
15152 /* TODO: Error codes (rcase-Recurse). */
15153 if ((r->children == NULL) || (b->children == NULL) ||
15154 (r->children->type != b->children->type))
15155 return (-1);
15156 /*
15157 * SPEC "For an all or sequence group particle to be a ·valid
15158 * restriction· of another group particle with the same {compositor}..."
15159 *
15160 * SPEC (1) "R's occurrence range is a valid restriction of B's
15161 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15162 */
15163 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15164 b->minOccurs, b->maxOccurs))
15165 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015166
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015167
15168 return (0);
15169}
15170
15171#endif
15172
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015173#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
15174 xmlSchemaPCustomErrExt(pctxt, \
15175 XML_SCHEMAP_INVALID_FACET_VALUE, \
15176 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
15177 "It is an error for both '%s' and '%s' to be specified on the "\
15178 "same type definition", \
15179 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
15180 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
15181
15182#define FACET_RESTR_ERR(fac1, msg) \
15183 xmlSchemaPCustomErr(pctxt, \
15184 XML_SCHEMAP_INVALID_FACET_VALUE, \
15185 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015186 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015187
15188#define FACET_RESTR_FIXED_ERR(fac) \
15189 xmlSchemaPCustomErr(pctxt, \
15190 XML_SCHEMAP_INVALID_FACET_VALUE, \
15191 NULL, (xmlSchemaTypePtr) fac, fac->node, \
15192 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015193 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015194
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015195static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015196xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
15197 xmlSchemaFacetPtr facet1,
15198 xmlSchemaFacetPtr facet2,
15199 int lessGreater,
15200 int orEqual,
15201 int ofBase)
15202{
15203 xmlChar *msg = NULL;
15204
15205 msg = xmlStrdup(BAD_CAST "'");
15206 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
15207 msg = xmlStrcat(msg, BAD_CAST "' has to be");
15208 if (lessGreater == 0)
15209 msg = xmlStrcat(msg, BAD_CAST " equal to");
15210 if (lessGreater == 1)
15211 msg = xmlStrcat(msg, BAD_CAST " greater than");
15212 else
15213 msg = xmlStrcat(msg, BAD_CAST " less than");
15214
15215 if (orEqual)
15216 msg = xmlStrcat(msg, BAD_CAST " or equal to");
15217 msg = xmlStrcat(msg, BAD_CAST " '");
15218 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
15219 if (ofBase)
15220 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
15221 else
15222 msg = xmlStrcat(msg, BAD_CAST "'");
15223
15224 xmlSchemaPCustomErr(pctxt,
15225 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015226 NULL, (xmlSchemaTypePtr) facet1, facet1->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015227 (const char *) msg, NULL);
15228
15229 if (msg != NULL)
15230 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015231}
15232
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015233static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015234xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
15235 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015236{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015237 xmlSchemaTypePtr base = type->baseType;
15238 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015239 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015240 flength = NULL, ftotdig = NULL, ffracdig = NULL,
15241 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
15242 fmininc = NULL, fmaxinc = NULL,
15243 fminexc = NULL, fmaxexc = NULL,
15244 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
15245 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
15246 bfmininc = NULL, bfmaxinc = NULL,
15247 bfminexc = NULL, bfmaxexc = NULL;
15248 int res, err = 0, fixedErr;
15249 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015250 * 3 The {facets} of R are the union of S and the {facets}
15251 * of B, eliminating duplicates. To eliminate duplicates,
15252 * when a facet of the same kind occurs in both S and the
15253 * {facets} of B, the one in the {facets} of B is not
15254 * included, with the exception of enumeration and pattern
15255 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015256 * are allowed.
15257 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015258
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015259 if ((type->facetSet == NULL) && (base->facetSet == NULL))
15260 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015261
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015262 last = type->facetSet;
15263 if (last != NULL)
15264 while (last->next != NULL)
15265 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015266
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015267 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
15268 facet = cur->facet;
15269 switch (facet->type) {
15270 case XML_SCHEMA_FACET_LENGTH:
15271 flength = facet; break;
15272 case XML_SCHEMA_FACET_MINLENGTH:
15273 fminlen = facet; break;
15274 case XML_SCHEMA_FACET_MININCLUSIVE:
15275 fmininc = facet; break;
15276 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15277 fminexc = facet; break;
15278 case XML_SCHEMA_FACET_MAXLENGTH:
15279 fmaxlen = facet; break;
15280 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15281 fmaxinc = facet; break;
15282 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15283 fmaxexc = facet; break;
15284 case XML_SCHEMA_FACET_TOTALDIGITS:
15285 ftotdig = facet; break;
15286 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15287 ffracdig = facet; break;
15288 default:
15289 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015290 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015291 }
15292 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15293 facet = cur->facet;
15294 switch (facet->type) {
15295 case XML_SCHEMA_FACET_LENGTH:
15296 bflength = facet; break;
15297 case XML_SCHEMA_FACET_MINLENGTH:
15298 bfminlen = facet; break;
15299 case XML_SCHEMA_FACET_MININCLUSIVE:
15300 bfmininc = facet; break;
15301 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15302 bfminexc = facet; break;
15303 case XML_SCHEMA_FACET_MAXLENGTH:
15304 bfmaxlen = facet; break;
15305 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15306 bfmaxinc = facet; break;
15307 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15308 bfmaxexc = facet; break;
15309 case XML_SCHEMA_FACET_TOTALDIGITS:
15310 bftotdig = facet; break;
15311 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15312 bffracdig = facet; break;
15313 default:
15314 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015315 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015316 }
15317 err = 0;
15318 /*
15319 * length and minLength or maxLength (2.2) + (3.2)
15320 */
15321 if (flength && (fminlen || fmaxlen)) {
15322 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
15323 "either of 'minLength' or 'maxLength' to be specified on "
15324 "the same type definition")
15325 }
15326 /*
15327 * Mutual exclusions in the same derivation step.
15328 */
15329 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015330 /*
15331 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015332 */
15333 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
15334 }
15335 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015336 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015337 * SCC "minInclusive and minExclusive"
15338 */
15339 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015340 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015341
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015342 if (flength && bflength) {
15343 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015344 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015345 * The values have to be equal.
15346 */
15347 res = xmlSchemaCompareValues(flength->val, bflength->val);
15348 if (res == -2)
15349 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015350 if (res != 0)
15351 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
15352 if ((res != 0) && (bflength->fixed)) {
15353 FACET_RESTR_FIXED_ERR(flength)
15354 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015355
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015356 }
15357 if (fminlen && bfminlen) {
15358 /*
15359 * SCC "minLength valid restriction"
15360 * minLength >= BASE minLength
15361 */
15362 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
15363 if (res == -2)
15364 goto internal_error;
15365 if (res == -1)
15366 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
15367 if ((res != 0) && (bfminlen->fixed)) {
15368 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015369 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015370 }
15371 if (fmaxlen && bfmaxlen) {
15372 /*
15373 * SCC "maxLength valid restriction"
15374 * maxLength <= BASE minLength
15375 */
15376 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
15377 if (res == -2)
15378 goto internal_error;
15379 if (res == 1)
15380 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
15381 if ((res != 0) && (bfmaxlen->fixed)) {
15382 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015383 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015384 }
15385 /*
15386 * SCC "length and minLength or maxLength"
15387 */
15388 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015389 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015390 if (flength) {
15391 if (! fminlen)
15392 flength = bflength;
15393 if (fminlen) {
15394 /* (1.1) length >= minLength */
15395 res = xmlSchemaCompareValues(flength->val, fminlen->val);
15396 if (res == -2)
15397 goto internal_error;
15398 if (res == -1)
15399 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
15400 }
15401 if (! fmaxlen)
15402 fmaxlen = bfmaxlen;
15403 if (fmaxlen) {
15404 /* (2.1) length <= maxLength */
15405 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
15406 if (res == -2)
15407 goto internal_error;
15408 if (res == 1)
15409 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
15410 }
15411 }
15412 if (fmaxinc) {
15413 /*
15414 * "maxInclusive"
15415 */
15416 if (fmininc) {
15417 /* SCC "maxInclusive >= minInclusive" */
15418 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
15419 if (res == -2)
15420 goto internal_error;
15421 if (res == -1) {
15422 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
15423 }
15424 }
15425 /*
15426 * SCC "maxInclusive valid restriction"
15427 */
15428 if (bfmaxinc) {
15429 /* maxInclusive <= BASE maxInclusive */
15430 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
15431 if (res == -2)
15432 goto internal_error;
15433 if (res == 1)
15434 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
15435 if ((res != 0) && (bfmaxinc->fixed)) {
15436 FACET_RESTR_FIXED_ERR(fmaxinc)
15437 }
15438 }
15439 if (bfmaxexc) {
15440 /* maxInclusive < BASE maxExclusive */
15441 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
15442 if (res == -2)
15443 goto internal_error;
15444 if (res != -1) {
15445 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
15446 }
15447 }
15448 if (bfmininc) {
15449 /* maxInclusive >= BASE minInclusive */
15450 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
15451 if (res == -2)
15452 goto internal_error;
15453 if (res == -1) {
15454 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
15455 }
15456 }
15457 if (bfminexc) {
15458 /* maxInclusive > BASE minExclusive */
15459 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
15460 if (res == -2)
15461 goto internal_error;
15462 if (res != 1) {
15463 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
15464 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015465 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015466 }
15467 if (fmaxexc) {
15468 /*
15469 * "maxExclusive >= minExclusive"
15470 */
15471 if (fminexc) {
15472 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
15473 if (res == -2)
15474 goto internal_error;
15475 if (res == -1) {
15476 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
15477 }
15478 }
15479 /*
15480 * "maxExclusive valid restriction"
15481 */
15482 if (bfmaxexc) {
15483 /* maxExclusive <= BASE maxExclusive */
15484 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
15485 if (res == -2)
15486 goto internal_error;
15487 if (res == 1) {
15488 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
15489 }
15490 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015491 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015492 }
15493 }
15494 if (bfmaxinc) {
15495 /* maxExclusive <= BASE maxInclusive */
15496 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
15497 if (res == -2)
15498 goto internal_error;
15499 if (res == 1) {
15500 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
15501 }
15502 }
15503 if (bfmininc) {
15504 /* maxExclusive > BASE minInclusive */
15505 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
15506 if (res == -2)
15507 goto internal_error;
15508 if (res != 1) {
15509 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
15510 }
15511 }
15512 if (bfminexc) {
15513 /* maxExclusive > BASE minExclusive */
15514 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
15515 if (res == -2)
15516 goto internal_error;
15517 if (res != 1) {
15518 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
15519 }
15520 }
15521 }
15522 if (fminexc) {
15523 /*
15524 * "minExclusive < maxInclusive"
15525 */
15526 if (fmaxinc) {
15527 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
15528 if (res == -2)
15529 goto internal_error;
15530 if (res != -1) {
15531 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
15532 }
15533 }
15534 /*
15535 * "minExclusive valid restriction"
15536 */
15537 if (bfminexc) {
15538 /* minExclusive >= BASE minExclusive */
15539 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
15540 if (res == -2)
15541 goto internal_error;
15542 if (res == -1) {
15543 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
15544 }
15545 if ((res != 0) && (bfminexc->fixed)) {
15546 FACET_RESTR_FIXED_ERR(fminexc)
15547 }
15548 }
15549 if (bfmaxinc) {
15550 /* minExclusive <= BASE maxInclusive */
15551 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
15552 if (res == -2)
15553 goto internal_error;
15554 if (res == 1) {
15555 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
15556 }
15557 }
15558 if (bfmininc) {
15559 /* minExclusive >= BASE minInclusive */
15560 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
15561 if (res == -2)
15562 goto internal_error;
15563 if (res == -1) {
15564 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
15565 }
15566 }
15567 if (bfmaxexc) {
15568 /* minExclusive < BASE maxExclusive */
15569 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
15570 if (res == -2)
15571 goto internal_error;
15572 if (res != -1) {
15573 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
15574 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015575 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015576 }
15577 if (fmininc) {
15578 /*
15579 * "minInclusive < maxExclusive"
15580 */
15581 if (fmaxexc) {
15582 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
15583 if (res == -2)
15584 goto internal_error;
15585 if (res != -1) {
15586 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
15587 }
15588 }
15589 /*
15590 * "minExclusive valid restriction"
15591 */
15592 if (bfmininc) {
15593 /* minInclusive >= BASE minInclusive */
15594 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
15595 if (res == -2)
15596 goto internal_error;
15597 if (res == -1) {
15598 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
15599 }
15600 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015601 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015602 }
15603 }
15604 if (bfmaxinc) {
15605 /* minInclusive <= BASE maxInclusive */
15606 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
15607 if (res == -2)
15608 goto internal_error;
15609 if (res == -1) {
15610 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
15611 }
15612 }
15613 if (bfminexc) {
15614 /* minInclusive > BASE minExclusive */
15615 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
15616 if (res == -2)
15617 goto internal_error;
15618 if (res != 1)
15619 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
15620 }
15621 if (bfmaxexc) {
15622 /* minInclusive < BASE maxExclusive */
15623 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
15624 if (res == -2)
15625 goto internal_error;
15626 if (res != -1)
15627 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
15628 }
15629 }
15630 if (ftotdig && bftotdig) {
15631 /*
15632 * SCC " totalDigits valid restriction"
15633 * totalDigits <= BASE totalDigits
15634 */
15635 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
15636 if (res == -2)
15637 goto internal_error;
15638 if (res == 1)
15639 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
15640 -1, 1, 1);
15641 if ((res != 0) && (bftotdig->fixed)) {
15642 FACET_RESTR_FIXED_ERR(ftotdig)
15643 }
15644 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015645 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015646 /*
15647 * SCC "fractionDigits valid restriction"
15648 * fractionDigits <= BASE fractionDigits
15649 */
15650 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
15651 if (res == -2)
15652 goto internal_error;
15653 if (res == 1)
15654 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
15655 -1, 1, 1);
15656 if ((res != 0) && (bffracdig->fixed)) {
15657 FACET_RESTR_FIXED_ERR(ffracdig)
15658 }
15659 }
15660 /*
15661 * SCC "fractionDigits less than or equal to totalDigits"
15662 */
15663 if (! ftotdig)
15664 ftotdig = bftotdig;
15665 if (! ffracdig)
15666 ffracdig = bffracdig;
15667 if (ftotdig && ffracdig) {
15668 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
15669 if (res == -2)
15670 goto internal_error;
15671 if (res == 1)
15672 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
15673 -1, 1, 0);
15674 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015675 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015676 * *Enumerations* won' be added here, since only the first set
15677 * of enumerations in the ancestor-or-self axis is used
15678 * for validation, plus we need to use the base type of those
15679 * enumerations for whitespace.
15680 *
15681 * *Patterns*: won't be add here, since they are ORed at
15682 * type level and ANDed at ancestor level. This will
15683 * happed during validation by walking the base axis
15684 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015685 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015686 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15687 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015688 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015689 * Special handling of enumerations and patterns.
15690 * TODO: hmm, they should not appear in the set, so remove this.
15691 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015692 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015693 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015694 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015695 /*
15696 * Search for a duplicate facet in the current type.
15697 */
15698 link = type->facetSet;
15699 err = 0;
15700 fixedErr = 0;
15701 while (link != NULL) {
15702 facet = link->facet;
15703 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015704 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015705 case XML_SCHEMA_FACET_WHITESPACE:
15706 /*
15707 * The whitespace must be stronger.
15708 */
15709 if (facet->whitespace < bfacet->whitespace) {
15710 FACET_RESTR_ERR(flength,
15711 "The 'whitespace' value has to be equal to "
15712 "or stronger than the 'whitespace' value of "
15713 "the base type")
15714 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015715 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015716 (facet->whitespace != bfacet->whitespace)) {
15717 FACET_RESTR_FIXED_ERR(facet)
15718 }
15719 break;
15720 default:
15721 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015722 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015723 /* Duplicate found. */
15724 break;
15725 }
15726 link = link->next;
15727 }
15728 /*
15729 * If no duplicate was found: add the base types's facet
15730 * to the set.
15731 */
15732 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015733 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015734 xmlMalloc(sizeof(xmlSchemaFacetLink));
15735 if (link == NULL) {
15736 xmlSchemaPErrMemory(pctxt,
15737 "deriving facets, creating a facet link", NULL);
15738 return (-1);
15739 }
15740 link->facet = cur->facet;
15741 link->next = NULL;
15742 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015743 type->facetSet = link;
15744 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015745 last->next = link;
15746 last = link;
15747 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015748
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015749 }
15750
15751 return (0);
15752internal_error:
15753 xmlSchemaPCustomErr(pctxt,
15754 XML_SCHEMAP_INVALID_FACET_VALUE,
15755 NULL, type, NULL,
15756 "Internal error: xmlSchemaDeriveAndValidateFacets", NULL);
15757 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015758}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015759
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015760static int
15761xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
15762 xmlSchemaTypePtr type)
15763{
15764 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
15765 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015766 * The actual value is then formed by replacing any union type
15767 * definition in the ·explicit members· with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015768 * {member type definitions}, in order.
15769 */
15770 link = type->memberTypes;
15771 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015772
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015773 if (IS_NOT_TYPEFIXED(link->type))
15774 xmlSchemaTypeFixup(link->type, pctxt, NULL);
15775
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015776 if (VARIETY_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015777 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015778 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015779 link->type = subLink->type;
15780 if (subLink->next != NULL) {
15781 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015782 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015783 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015784 while (subLink != NULL) {
15785 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015786 xmlMalloc(sizeof(xmlSchemaTypeLink));
15787 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015788 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015789 NULL);
15790 return (-1);
15791 }
15792 newLink->type = subLink->type;
15793 prevLink->next = newLink;
15794 prevLink = newLink;
15795 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015796
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015797 subLink = subLink->next;
15798 }
15799 }
15800 }
15801 }
15802 link = link->next;
15803 }
15804 return (0);
15805}
15806
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015807static void
15808xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
15809{
15810 int has = 0, needVal = 0, normVal = 0;
15811
15812 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
15813 if (has) {
15814 needVal = (type->baseType->flags &
15815 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
15816 normVal = (type->baseType->flags &
15817 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
15818 }
15819 if (type->facets != NULL) {
15820 xmlSchemaFacetPtr fac;
15821
15822 for (fac = type->facets; fac != NULL; fac = fac->next) {
15823 switch (fac->type) {
15824 case XML_SCHEMA_FACET_WHITESPACE:
15825 break;
15826 case XML_SCHEMA_FACET_PATTERN:
15827 normVal = 1;
15828 has = 1;
15829 break;
15830 case XML_SCHEMA_FACET_ENUMERATION:
15831 needVal = 1;
15832 normVal = 1;
15833 has = 1;
15834 break;
15835 default:
15836 has = 1;
15837 break;
15838 }
15839 }
15840 }
15841 if (normVal)
15842 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
15843 if (needVal)
15844 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15845 if (has)
15846 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
15847
15848 if (has && (! needVal) && VARIETY_ATOMIC(type)) {
15849 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
15850 /*
15851 * OPTIMIZE VAL TODO: Some facets need a computed value.
15852 */
15853 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
15854 (prim->builtInType != XML_SCHEMAS_STRING)) {
15855 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15856 }
15857 }
15858}
15859
15860static int
15861xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
15862{
15863
15864
15865 /*
15866 * Evaluate the whitespace-facet value.
15867 */
15868 if (VARIETY_LIST(type)) {
15869 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15870 return (0);
15871 } else if (VARIETY_UNION(type))
15872 return (0);
15873
15874 if (type->facetSet != NULL) {
15875 xmlSchemaFacetLinkPtr lin;
15876
15877 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
15878 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
15879 switch (lin->facet->whitespace) {
15880 case XML_SCHEMAS_FACET_PRESERVE:
15881 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
15882 break;
15883 case XML_SCHEMAS_FACET_REPLACE:
15884 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
15885 break;
15886 case XML_SCHEMAS_FACET_COLLAPSE:
15887 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15888 break;
15889 default:
15890 return (-1);
15891 }
15892 return (0);
15893 }
15894 }
15895 }
15896 /*
15897 * For all ·atomic· datatypes other than string (and types ·derived·
15898 * by ·restriction· from it) the value of whiteSpace is fixed to
15899 * collapse
15900 */
15901 {
15902 xmlSchemaTypePtr anc;
15903
15904 for (anc = type->baseType; anc != NULL &&
15905 anc->builtInType != XML_SCHEMAS_ANYTYPE;
15906 anc = anc->baseType) {
15907
15908 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
15909 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
15910 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
15911
15912 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
15913 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
15914 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
15915
15916 } else
15917 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15918 break;
15919 }
15920 }
15921 return (0);
15922 }
15923 return (0);
15924}
15925
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015926/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015927 * xmlSchemaTypeFixup:
15928 * @typeDecl: the schema type definition
15929 * @ctxt: the schema parser context
15930 *
15931 * Fixes the content model of the type.
15932 */
15933static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015934xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015935 xmlSchemaParserCtxtPtr pctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000015936{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015937 if (type == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000015938 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015939 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) &&
15940 (type->type != XML_SCHEMA_TYPE_SIMPLE))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000015941 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015942 if (! IS_NOT_TYPEFIXED(type))
15943 return;
15944 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000015945 if (name == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015946 name = type->name;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015947
15948 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015949 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015950 XML_SCHEMAP_INTERNAL,
15951 NULL, type, NULL,
15952 "Internal error: xmlSchemaTypeFixup, "
15953 "baseType is missing on '%s'", type->name);
15954 return;
15955 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015956
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015957 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015958 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015959
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015960 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015961 * Type-fix the base type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015962 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015963 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015964 xmlSchemaTypeFixup(baseType, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015965 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
15966 /*
15967 * Skip fixup if the base type is invalid.
15968 * TODO: Generate a warning!
15969 */
15970 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015971 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015972 /*
15973 * This basically checks if the base type can be derived.
15974 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015975 if (xmlSchemaCheckSRCCT(pctxt, type) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015976 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
15977 return;
15978 }
15979 /*
15980 * Fixup the content type.
15981 */
15982 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
15983 /*
15984 * Corresponds to <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015985 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015986 if ((IS_COMPLEX_TYPE(baseType)) &&
15987 (baseType->contentTypeDef != NULL) &&
15988 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015989 xmlSchemaTypePtr contentBase, content;
15990 char buf[30];
15991 const xmlChar *tmpname;
15992 /*
15993 * SPEC (1) If <restriction> + base type is <complexType>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015994 * "whose own {content type} is a simple type..."
Daniel Veillard01fa6152004-06-29 17:04:39 +000015995 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015996 if (type->contentTypeDef != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015997 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015998 * SPEC (1.1) "the simple type definition corresponding to the
15999 * <simpleType> among the [children] of <restriction> if there
16000 * is one;"
16001 * Note that this "<simpleType> among the [children]" was put
16002 * into ->contentTypeDef during parsing.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016003 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016004 contentBase = type->contentTypeDef;
16005 type->contentTypeDef = NULL;
16006 } else {
16007 /*
16008 * (1.2) "...otherwise (<restriction> has no <simpleType>
16009 * among its [children]), the simple type definition which
16010 * is the {content type} of the ... base type."
16011 */
16012 contentBase = baseType->contentTypeDef;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016013 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016014 /*
16015 * SPEC
16016 * "... a simple type definition which restricts the simple
16017 * type definition identified in clause 1.1 or clause 1.2
16018 * with a set of facet components"
16019 *
16020 * Create the anonymous simple type, which will be the content
16021 * type of the complex type.
16022 */
16023 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
16024 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
16025 content = xmlSchemaAddType(pctxt,
16026 pctxt->schema, tmpname, tmpname, type->node);
16027 if (content == NULL)
16028 return;
16029 /*
16030 * We will use the same node as for the <complexType>
16031 * to have it somehow anchored in the schema doc.
16032 */
16033 content->node = type->node;
16034 content->type = XML_SCHEMA_TYPE_SIMPLE;
16035 content->contentType = XML_SCHEMA_CONTENT_SIMPLE;
16036 content->baseType = contentBase;
16037 /*
16038 * Move the facets, previously anchored on the complexType.
16039 */
16040 content->facets = type->facets;
16041 type->facets = NULL;
16042 content->facetSet = type->facetSet;
16043 type->facetSet = NULL;
16044
16045 type->contentTypeDef = content;
16046 if (IS_NOT_TYPEFIXED(contentBase))
16047 xmlSchemaTypeFixup(contentBase, pctxt, NULL);
16048 xmlSchemaTypeFixup(content, pctxt, NULL);
16049
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016050 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16051 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16052 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
16053 /*
16054 * SPEC (2) If <restriction> + base is a mixed <complexType> with
16055 * an emptiable particle, then a simple type definition which
16056 * restricts the <restriction>'s <simpleType> child.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016057 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016058 if ((type->contentTypeDef == NULL) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016059 (type->contentTypeDef->baseType == NULL)) {
16060 /*
16061 * TODO: Check if this ever happens.
16062 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016063 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016064 XML_SCHEMAP_INTERNAL,
16065 NULL, type, NULL,
16066 "Internal error: xmlSchemaTypeFixup, "
16067 "complex type '%s': the <simpleContent><restriction> "
16068 "is missing a <simpleType> child, but was not catched "
16069 "by xmlSchemaCheckSRCCT()", type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016070 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016071 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16072 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16073 /*
16074 * SPEC (3) If <extension> + base is <complexType> with
16075 * <simpleType> content, "...then the {content type} of that
16076 * complex type definition"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016077 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016078 if (baseType->contentTypeDef == NULL) {
16079 /*
16080 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
16081 * should have catched this already.
16082 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016083 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016084 XML_SCHEMAP_INTERNAL,
16085 NULL, type, NULL,
16086 "Internal error: xmlSchemaTypeFixup, "
16087 "complex type '%s': the <extension>ed base type is "
16088 "a complex type with no simple content type",
16089 type->name);
16090 }
16091 type->contentTypeDef = baseType->contentTypeDef;
16092 } else if ((IS_SIMPLE_TYPE(baseType)) &&
16093 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16094 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016095 * SPEC (4) <extension> + base is <simpleType>
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016096 * "... then that simple type definition"
16097 */
16098 type->contentTypeDef = baseType;
16099 } else {
16100 /*
16101 * TODO: Check if this ever happens.
16102 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016103 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016104 XML_SCHEMAP_INTERNAL,
16105 NULL, type, NULL,
16106 "Internal error: xmlSchemaTypeFixup, "
16107 "complex type '%s' with <simpleContent>: unhandled "
16108 "derivation case", type->name);
16109 }
16110 } else {
16111 int dummySequence = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016112 xmlSchemaParticlePtr particle =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016113 (xmlSchemaParticlePtr) type->subtypes;
16114 /*
16115 * Corresponds to <complexType><complexContent>...
16116 *
16117 * NOTE that the effective mixed was already set during parsing of
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016118 * <complexType> and <complexContent>; its flag value is
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016119 * XML_SCHEMAS_TYPE_MIXED.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016120 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016121 * Compute the "effective content":
16122 * (2.1.1) + (2.1.2) + (2.1.3)
16123 */
16124 if ((particle == NULL) ||
16125 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
16126 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
16127 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
16128 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
16129 (particle->minOccurs == 0))) &&
16130 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016131 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016132 /*
16133 * SPEC (2.1.4) "If the ·effective mixed· is true, then
16134 * a particle whose properties are as follows:..."
16135 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016136 * Empty sequence model group with
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016137 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
16138 * NOTE that we sill assign it the <complexType> node to
16139 * somehow anchor it in the doc.
16140 */
16141 if ((particle == NULL) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016142 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016143 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016144 * Create the particle.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016145 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016146 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016147 type->node, 1, 1);
16148 if (particle == NULL)
16149 return;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016150 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016151 * Create the model group.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016152 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016153 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016154 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016155 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16156 if (particle->children == NULL)
16157 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016158
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016159 type->subtypes = (xmlSchemaTypePtr) particle;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016160 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016161 dummySequence = 1;
16162 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16163 } else {
16164 /*
16165 * SPEC (2.1.5) "otherwise empty"
16166 */
16167 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016168 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016169 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016170 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016171 * SPEC (2.2) "otherwise the particle corresponding to the
16172 * <all>, <choice>, <group> or <sequence> among the
16173 * [children]."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016174 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016175 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16176 }
16177 /*
16178 * Compute the "content type".
16179 */
16180 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016181 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016182 * SPEC (3.1) "If <restriction>..."
16183 * (3.1.1) + (3.1.2) */
16184 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
16185 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16186 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16187 }
16188 } else {
16189 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016190 * SPEC (3.2) "If <extension>..."
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016191 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016192 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16193 /*
16194 * SPEC (3.2.1)
16195 */
16196 type->contentType = baseType->contentType;
16197 type->subtypes = baseType->subtypes;
16198 /*
16199 * NOTE that the effective mixed is ignored here.
16200 */
16201 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16202 /*
16203 * SPEC (3.2.2)
16204 */
16205 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16206 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16207 } else {
16208 /*
16209 * SPEC (3.2.3)
16210 */
16211 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16212 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16213 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016214 * "A model group whose {compositor} is sequence and whose
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016215 * {particles} are..."
16216 */
16217 if (! dummySequence) {
16218 xmlSchemaTreeItemPtr effectiveContent =
16219 (xmlSchemaTreeItemPtr) type->subtypes;
16220 /*
16221 * Create the particle.
16222 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016223 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016224 type->node, 1, 1);
16225 if (particle == NULL)
16226 return;
16227 /*
16228 * Create the "sequence" model group.
16229 */
16230 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016231 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016232 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16233 if (particle->children == NULL)
16234 return;
16235 type->subtypes = (xmlSchemaTypePtr) particle;
16236 /*
16237 * SPEC "the particle of the {content type} of
16238 * the ... base ..."
16239 * Create a duplicate of the base type's particle
16240 * and assign its "term" to it.
16241 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016242 particle->children->children =
16243 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
16244 pctxt->schema, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016245 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016246 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016247 if (particle->children->children == NULL)
16248 return;
16249 particle = (xmlSchemaParticlePtr)
16250 particle->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016251 particle->children =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016252 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
16253 /*
16254 * SPEC "followed by the ·effective content·."
16255 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016256 particle->next = effectiveContent;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016257 } else {
16258 /*
16259 * This is the case when there is already an empty
16260 * <sequence> with minOccurs==maxOccurs==1.
16261 * Just add the base types's content type.
16262 * NOTE that, although we miss to add an intermediate
16263 * <sequence>, this should produce no difference to
16264 * neither the regex compilation of the content model,
16265 * nor to the complex type contraints.
16266 */
16267 particle->children->children =
16268 (xmlSchemaTreeItemPtr) baseType->subtypes;
16269 }
16270 }
16271 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016272 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016273 /*
16274 * Apply the complex type component constraints; this will not
16275 * check attributes, since this is done in
16276 * xmlSchemaBuildAttributeValidation().
16277 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016278 if (xmlSchemaCheckCTComponent(pctxt, type) != 0)
16279 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016280 /*
16281 * Inherit & check constraints for attributes.
16282 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016283 xmlSchemaBuildAttributeValidation(pctxt, type);
16284 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016285 /*
16286 * Simple Type Definition Schema Component
16287 */
16288 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016289 if (VARIETY_LIST(type)) {
16290 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016291 * Corresponds to <simpleType><list>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016292 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016293 if (type->subtypes == NULL) {
16294 /*
16295 * This one is really needed, so get out.
16296 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016297 PERROR_INT("xmlSchemaTypeFixup",
16298 "list type has no item-type assigned");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016299 return;
16300 }
16301 if (IS_NOT_TYPEFIXED(type->subtypes))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016302 xmlSchemaTypeFixup(type->subtypes, pctxt, NULL);
16303 } else if (VARIETY_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016304 /*
16305 * Corresponds to <simpleType><union>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016306 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016307 if (type->memberTypes == NULL) {
16308 /*
16309 * This one is really needed, so get out.
16310 */
16311 return;
16312 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016313 if (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016314 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016315 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016316 xmlSchemaTypePtr baseType = type->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016317 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016318 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016319 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016320 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016321 xmlSchemaTypeFixup(baseType, pctxt, NULL);
16322 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016323 * Variety
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016324 * If the <restriction> alternative is chosen, then the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016325 * {variety} of the {base type definition}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016326 */
16327 if (VARIETY_ATOMIC(baseType))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016328 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016329 else if (VARIETY_LIST(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016330 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
16331 /*
16332 * Inherit the itemType.
16333 */
16334 type->subtypes = baseType->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016335 } else if (VARIETY_UNION(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016336 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
16337 /*
16338 * NOTE that we won't assign the memberTypes of the base,
16339 * since this will make trouble when freeing them; we will
16340 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016341 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016342 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016343 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016344 /*
16345 * Check constraints.
16346 *
16347 * TODO: Split this somehow, we need to know first if we can derive
16348 * from the base type at all!
16349 */
16350 if (type->baseType != NULL) {
16351 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016352 * Schema Component Constraint: Simple Type Restriction
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016353 * (Facets)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016354 * NOTE: Satisfaction of 1 and 2 arise from the fixup
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016355 * applied beforehand.
16356 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016357 xmlSchemaCheckSRCSimpleType(pctxt, type);
16358 xmlSchemaCheckFacetValues(type, pctxt);
16359 if ((type->facetSet != NULL) ||
16360 (type->baseType->facetSet != NULL))
16361 xmlSchemaDeriveAndValidateFacets(pctxt, type);
16362 /*
16363 * Whitespace value.
16364 */
16365 xmlSchemaTypeFixupWhitespace(type);
16366 xmlSchemaTypeFixupOptimFacets(type);
16367 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016368 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016369
Daniel Veillard8651f532002-04-17 09:06:27 +000016370#ifdef DEBUG_TYPE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016371 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016372 xmlGenericError(xmlGenericErrorContext,
16373 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016374 type->node->doc->URL,
16375 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016376 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016377 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016378 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016379 if ((IS_SIMPLE_TYPE(type)) || (IS_COMPLEX_TYPE(type))) {
16380 switch (type->contentType) {
16381 case XML_SCHEMA_CONTENT_SIMPLE:
16382 xmlGenericError(xmlGenericErrorContext, "simple\n");
16383 break;
16384 case XML_SCHEMA_CONTENT_ELEMENTS:
16385 xmlGenericError(xmlGenericErrorContext, "elements\n");
16386 break;
16387 case XML_SCHEMA_CONTENT_UNKNOWN:
16388 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
16389 break;
16390 case XML_SCHEMA_CONTENT_EMPTY:
16391 xmlGenericError(xmlGenericErrorContext, "empty\n");
16392 break;
16393 case XML_SCHEMA_CONTENT_MIXED:
16394 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016395 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016396 xmlGenericError(xmlGenericErrorContext,
16397 "mixed as emptiable particle\n");
16398 else
16399 xmlGenericError(xmlGenericErrorContext, "mixed\n");
16400 break;
16401 /* Removed, since not used. */
16402 /*
16403 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
16404 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
16405 break;
16406 */
16407 case XML_SCHEMA_CONTENT_BASIC:
16408 xmlGenericError(xmlGenericErrorContext, "basic\n");
16409 break;
16410 default:
16411 xmlGenericError(xmlGenericErrorContext,
16412 "not registered !!!\n");
16413 break;
16414 }
Daniel Veillard8651f532002-04-17 09:06:27 +000016415 }
16416#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016417}
16418
16419/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016420 * xmlSchemaCheckFacet:
16421 * @facet: the facet
16422 * @typeDecl: the schema type definition
16423 * @ctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016424 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016425 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016426 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016427 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016428 * Returns 0 if valid, a positive error code if not valid and
16429 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016430 */
16431int
16432xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016433 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016434 xmlSchemaParserCtxtPtr pctxt,
16435 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016436{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016437 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016438
Daniel Veillardce682bc2004-11-05 17:22:25 +000016439 if ((facet == NULL) || (typeDecl == NULL))
16440 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016441 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016442 * TODO: will the parser context be given if used from
16443 * the relaxNG module?
16444 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016445 if (pctxt == NULL)
16446 ctxtGiven = 0;
16447 else
16448 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016449
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016450 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016451 case XML_SCHEMA_FACET_MININCLUSIVE:
16452 case XML_SCHEMA_FACET_MINEXCLUSIVE:
16453 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016454 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
16455 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016456 /*
16457 * Okay we need to validate the value
16458 * at that point.
16459 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016460 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016461
16462 /* 4.3.5.5 Constraints on enumeration Schema Components
16463 * Schema Component Constraint: enumeration valid restriction
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016464 * It is an ·error· if any member of {value} is not in the
16465 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016466 *
16467 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016468 * The value ·must· be in the
16469 * ·value space· of the ·base type·.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016470 */
16471 /*
16472 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016473 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016474 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016475 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016476 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016477 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016478 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016479 */
16480 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
16481 base = typeDecl->baseType;
16482 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016483 PERROR_INT("xmlSchemaCheckFacet",
16484 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016485 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016486 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016487 } else
16488 base = typeDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016489
16490 if (! ctxtGiven) {
16491 /*
16492 * A context is needed if called from RelaxNG.
16493 */
16494 pctxt = xmlSchemaNewParserCtxt("*");
16495 if (pctxt == NULL)
16496 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016497 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016498 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016499 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016500 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016501 * facet->node is just the node holding the facet
16502 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016503 * of the facet.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016504 */
16505 ret = xmlSchemaVCheckCVCSimpleType(
16506 (xmlSchemaAbstractCtxtPtr) pctxt, facet->node, base,
16507 facet->value, &(facet->val), 1, 1, 0);
16508 if (ret != 0) {
16509 if (ret < 0) {
16510 /* No error message for RelaxNG. */
16511 if (ctxtGiven) {
16512 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16513 XML_SCHEMAP_INTERNAL, facet->node, NULL,
16514 "Internal error: xmlSchemaCheckFacet, "
16515 "failed to validate the value '%s' of the "
16516 "facet '%s' against the base type",
16517 facet->value, xmlSchemaFacetTypeToString(facet->type));
16518 }
16519 goto internal_error;
16520 }
16521 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16522 /* No error message for RelaxNG. */
16523 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016524 xmlChar *str = NULL;
16525
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016526 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16527 ret, facet->node, (xmlSchemaTypePtr) facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016528 "The value '%s' of the facet does not validate "
16529 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016530 facet->value,
16531 xmlSchemaFormatQName(&str,
16532 base->targetNamespace, base->name));
16533 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016534 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016535 goto exit;
16536 } else if (facet->val == NULL) {
16537 if (ctxtGiven) {
16538 PERROR_INT("xmlSchemaCheckFacet",
16539 "value was not computed");
16540 }
16541 TODO
16542 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016543 break;
16544 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016545 case XML_SCHEMA_FACET_PATTERN:
16546 facet->regexp = xmlRegexpCompile(facet->value);
16547 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016548 ret = XML_SCHEMAP_REGEXP_INVALID;
16549 /* No error message for RelaxNG. */
16550 if (ctxtGiven) {
16551 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16552 ret, facet->node, typeDecl,
16553 "The value '%s' of the facet 'pattern' is not a "
16554 "valid regular expression",
16555 facet->value, NULL);
16556 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016557 }
16558 break;
16559 case XML_SCHEMA_FACET_TOTALDIGITS:
16560 case XML_SCHEMA_FACET_FRACTIONDIGITS:
16561 case XML_SCHEMA_FACET_LENGTH:
16562 case XML_SCHEMA_FACET_MAXLENGTH:
16563 case XML_SCHEMA_FACET_MINLENGTH:{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016564 ret = xmlSchemaValidatePredefinedType(
16565 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
16566 facet->value, &(facet->val));
16567 if (ret != 0) {
16568 if (ret < 0) {
16569 /* No error message for RelaxNG. */
16570 if (ctxtGiven) {
16571 PERROR_INT("xmlSchemaCheckFacet",
16572 "validating facet value");
16573 }
16574 goto internal_error;
16575 }
16576 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16577 /* No error message for RelaxNG. */
16578 if (ctxtGiven) {
16579 /* error code */
16580 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16581 ret, facet->node, typeDecl,
16582 "The value '%s' of the facet '%s' is not a valid "
16583 "'nonNegativeInteger'",
16584 facet->value,
16585 xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016586 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016587 }
16588 break;
16589 }
16590 case XML_SCHEMA_FACET_WHITESPACE:{
16591 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
16592 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
16593 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
16594 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
16595 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
16596 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
16597 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016598 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16599 /* No error message for RelaxNG. */
16600 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016601 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016602 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16603 ret, facet->node, typeDecl,
16604 "The value '%s' of the facet 'whitespace' is not "
16605 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016606 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016607 }
16608 }
16609 default:
16610 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016611 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016612exit:
16613 if ((! ctxtGiven) && (pctxt != NULL))
16614 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016615 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016616internal_error:
16617 if ((! ctxtGiven) && (pctxt != NULL))
16618 xmlSchemaFreeParserCtxt(pctxt);
16619 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016620}
16621
16622/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016623 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000016624 * @typeDecl: the schema type definition
16625 * @ctxt: the schema parser context
16626 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016627 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000016628 */
16629static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016630xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
16631 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000016632{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016633 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016634 /*
16635 * NOTE: It is intended to use the facets list, instead
16636 * of facetSet.
16637 */
16638 if (typeDecl->facets != NULL) {
16639 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016640
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016641 /*
16642 * Temporarily assign the "schema" to the validation context
16643 * of the parser context. This is needed for NOTATION validation.
16644 */
16645 if (ctxt->vctxt == NULL) {
16646 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
16647 return;
16648 }
16649 ctxt->vctxt->schema = ctxt->schema;
16650
Daniel Veillard01fa6152004-06-29 17:04:39 +000016651 while (facet != NULL) {
16652 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
16653 facet = facet->next;
16654 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016655
16656 ctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016657 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016658}
16659
16660/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016661 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016662 * @ctxtMGroup: the searched model group
16663 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016664 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016665 *
16666 * This one is intended to be used by
16667 * xmlSchemaCheckGroupDefCircular only.
16668 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016669 * Returns the particle with the circular model group definition reference,
16670 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016671 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016672static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016673xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016674 xmlSchemaTreeItemPtr particle)
16675{
16676 xmlSchemaTreeItemPtr circ = NULL;
16677 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016678 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016679
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016680 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016681 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016682 if (term == NULL)
16683 continue;
16684 switch (term->type) {
16685 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016686 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016687 if (gdef == groupDef)
16688 return (particle);
16689 /*
16690 * Mark this model group definition to avoid infinite
16691 * recursion on circular references not yet examined.
16692 */
16693 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
16694 continue;
16695 if (gdef->children != NULL) {
16696 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16697 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
16698 gdef->children->children);
16699 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16700 if (circ != NULL)
16701 return (circ);
16702 }
16703 break;
16704 case XML_SCHEMA_TYPE_SEQUENCE:
16705 case XML_SCHEMA_TYPE_CHOICE:
16706 case XML_SCHEMA_TYPE_ALL:
16707 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
16708 if (circ != NULL)
16709 return (circ);
16710 break;
16711 default:
16712 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016713 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016714 }
16715 return (NULL);
16716}
16717
16718/**
16719 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016720 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016721 * @ctxt: the parser context
16722 * @name: the name
16723 *
16724 * Checks for circular references to model group definitions.
16725 */
16726static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016727xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016728 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016729 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016730{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016731 /*
16732 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016733 * 2 Circular groups are disallowed. That is, within the {particles}
16734 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016735 * is the group itself.
16736 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016737 if ((item == NULL) ||
16738 (item->type != XML_SCHEMA_TYPE_GROUP) ||
16739 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016740 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016741 {
16742 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016743
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016744 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016745 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016746 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016747 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016748 * TODO: The error report is not adequate: this constraint
16749 * is defined for model groups but not definitions, but since
16750 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016751 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016752 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016753 */
16754 xmlSchemaPCustomErr(ctxt,
16755 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016756 NULL, NULL, GET_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016757 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016758 "defined", xmlSchemaFormatQName(&str,
16759 item->targetNamespace, item->name));
16760 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016761 /*
16762 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016763 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016764 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016765 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016766 }
16767 }
16768}
16769
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016770/**
16771 * xmlSchemaGroupDefTermFixup:
16772 * @item: the particle with a model group definition as term
16773 * @ctxt: the parser context
16774 * @name: the name
16775 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016776 * Checks cos-all-limited.
16777 *
16778 * Assigns the model group of model group definitions to the "term"
16779 * of the referencing particle.
16780 * In xmlSchemaMiscRefFixup the model group definitions was assigned
16781 * to the "term", since needed for the circularity check.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016782 */
16783static void
16784xmlSchemaGroupDefTermFixup(xmlSchemaParticlePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016785 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016786 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016787{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016788 if ((item == NULL) ||
16789 (item->type != XML_SCHEMA_TYPE_PARTICLE) ||
16790 (item->children == NULL) ||
16791 (item->children->type != XML_SCHEMA_TYPE_GROUP) ||
16792 (item->children->children == NULL))
16793 return;
16794 item->children = item->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016795 /*
16796 * TODO: Not nice, but we will anchor cos-all-limited here.
16797 */
16798 if ((item->children->type == XML_SCHEMA_TYPE_ALL) &&
16799 (item->maxOccurs != 1)) {
16800 /*
16801 * SPEC (1.2) "the {term} property of a particle with
16802 * {max occurs}=1which is part of a pair which constitutes the
16803 * {content type} of a complex type definition."
16804 */
16805 xmlSchemaPCustomErr(ctxt,
16806 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16807 NULL, (xmlSchemaTypePtr) item, item->node,
16808 "The particle's 'maxOccurs' must be 1, since an xs:all model "
16809 "group is its term", NULL);
16810 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016811}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016812
16813/**
16814 * xmlSchemaGetCircAttrGrRef:
16815 * @ctxtGr: the searched attribute group
16816 * @attr: the current attribute list to be processed
16817 *
16818 * This one is intended to be used by
16819 * xmlSchemaCheckSRCAttributeGroupCircular only.
16820 *
16821 * Returns the circular attribute grou reference, otherwise NULL.
16822 */
16823static xmlSchemaAttributeGroupPtr
16824xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
16825 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016826{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016827 xmlSchemaAttributeGroupPtr circ = NULL, gr;
16828 int marked;
16829 /*
16830 * We will search for an attribute group reference which
16831 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016832 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016833 while (attr != NULL) {
16834 marked = 0;
16835 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
16836 gr = (xmlSchemaAttributeGroupPtr) attr;
16837 if (gr->refItem != NULL) {
16838 if (gr->refItem == ctxtGr)
16839 return (gr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016840 else if (gr->refItem->flags &
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016841 XML_SCHEMAS_ATTRGROUP_MARKED) {
16842 attr = attr->next;
16843 continue;
16844 } else {
16845 /*
16846 * Mark as visited to avoid infinite recursion on
16847 * circular references not yet examined.
16848 */
16849 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
16850 marked = 1;
16851 }
16852 }
16853 if (gr->attributes != NULL)
16854 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
16855 /*
16856 * Unmark the visited group's attributes.
16857 */
16858 if (marked)
16859 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
16860 if (circ != NULL)
16861 return (circ);
16862 }
16863 attr = attr->next;
16864 }
16865 return (NULL);
16866}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016867
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016868/**
16869 * xmlSchemaCheckSRCAttributeGroupCircular:
16870 * attrGr: the attribute group definition
16871 * @ctxt: the parser context
16872 * @name: the name
16873 *
16874 * Checks for circular references of attribute groups.
16875 */
16876static void
16877xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016878 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016879 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016880{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016881 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016882 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016883 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016884 * 3 Circular group reference is disallowed outside <redefine>.
16885 * That is, unless this element information item's parent is
16886 * <redefine>, then among the [children], if any, there must
16887 * not be an <attributeGroup> with ref [attribute] which resolves
16888 * to the component corresponding to this <attributeGroup>. Indirect
16889 * circularity is also ruled out. That is, when QName resolution
16890 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
16891 * any <attributeGroup>s with a ref [attribute] among the [children],
16892 * it must not be the case that a ·QName· is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016893 * which resolves to the component corresponding to this <attributeGroup>.
16894 */
16895 /*
16896 * Only global components can be referenced.
16897 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016898 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016899 (attrGr->attributes == NULL))
16900 return;
16901 else {
16902 xmlSchemaAttributeGroupPtr circ;
16903
16904 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
16905 if (circ != NULL) {
16906 /*
16907 * TODO: Report the referenced attr group as QName.
16908 */
16909 xmlSchemaPCustomErr(ctxt,
16910 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16911 NULL, NULL, circ->node,
16912 "Circular reference to the attribute group '%s' "
16913 "defined", attrGr->name);
16914 /*
16915 * NOTE: We will cut the reference to avoid further
16916 * confusion of the processor.
16917 * BADSPEC: The spec should define how to process in this case.
16918 */
16919 circ->attributes = NULL;
16920 circ->refItem = NULL;
16921 }
16922 }
16923}
16924
16925/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000016926 * xmlSchemaAttrGrpFixup:
16927 * @attrgrpDecl: the schema attribute definition
16928 * @ctxt: the schema parser context
16929 * @name: the attribute name
16930 *
16931 * Fixes finish doing the computations on the attributes definitions
16932 */
16933static void
Daniel Veillard3646d642004-06-02 19:19:14 +000016934xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016935 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000016936{
16937 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000016938 name = attrgrp->name;
16939 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016940 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000016941 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016942 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000016943
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016944 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016945 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016946 if (ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016947 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016948 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016949 (xmlSchemaTypePtr) attrgrp, attrgrp->node,
16950 "ref", attrgrp->ref, attrgrp->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016951 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016952 return;
16953 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016954 attrgrp->refItem = ref;
16955 /*
16956 * Check for self reference!
16957 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016958 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000016959 attrgrp->attributes = ref->attributes;
16960 attrgrp->attributeWildcard = ref->attributeWildcard;
16961 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000016962}
16963
16964/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016965 * xmlSchemaAttrCheckValConstr:
16966 * @item: an schema attribute declaration/use
16967 * @ctxt: a schema parser context
16968 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016969 *
16970 *
16971 * Schema Component Constraint: Attribute Declaration Properties Correct
16972 * (a-props-correct)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016973 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000016974 *
16975 * Fixes finish doing the computations on the attributes definitions
16976 */
16977static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016978xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016979 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016980 const xmlChar * name ATTRIBUTE_UNUSED)
16981{
16982
16983 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016984 * 2 if there is a {value constraint}, the canonical lexical
16985 * representation of its value must be ·valid· with respect
16986 * to the {type definition} as defined in String Valid (§3.14.4).
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016987 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016988 if (item->defValue != NULL) {
16989 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016990
16991 if (item->subtypes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016992 PERROR_INT("xmlSchemaCheckAttrValConstr",
16993 "type is missing");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016994 return;
16995 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016996 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt,
16997 item->node, item->subtypes, item->defValue, &(item->defVal),
16998 1, 1, 0);
16999 if (ret != 0) {
17000 if (ret < 0) {
17001 PERROR_INT("xmlSchemaAttrCheckValConstr",
17002 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017003 return;
17004 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017005 ret = XML_SCHEMAP_A_PROPS_CORRECT_2;
17006 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
17007 ret, item->node, (xmlSchemaTypePtr) item,
17008 "The value of the value constraint is not valid", NULL, NULL);
17009 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017010 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017011 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017012}
17013
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017014static xmlSchemaElementPtr
17015xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
17016 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017017{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017018 xmlSchemaElementPtr ret;
17019
17020 if (SUBST_GROUP_AFF(ancestor) == NULL)
17021 return (NULL);
17022 if (SUBST_GROUP_AFF(ancestor) == elemDecl)
17023 return (ancestor);
17024
17025 if (SUBST_GROUP_AFF(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
17026 return (NULL);
17027 SUBST_GROUP_AFF(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
17028 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
17029 SUBST_GROUP_AFF(ancestor));
17030 SUBST_GROUP_AFF(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
17031
17032 return (ret);
17033}
17034
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017035/**
17036 * xmlSchemaCheckElemPropsCorrect:
17037 * @ctxt: a schema parser context
17038 * @decl: the element declaration
17039 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017040 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017041 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017042 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017043 *
17044 * STATUS:
17045 * missing: (6)
17046 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017047static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017048xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
17049 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017050{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017051 int ret = 0;
17052 xmlSchemaTypePtr typeDef = ELEM_TYPE(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017053 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017054 * SPEC (1) "The values of the properties of an element declaration
17055 * must be as described in the property tableau in The Element
17056 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
17057 * Sub-components (§5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017058 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017059 if (SUBST_GROUP_AFF(elemDecl) != NULL) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017060 xmlSchemaElementPtr head = SUBST_GROUP_AFF(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017061
17062 xmlSchemaCheckElementDeclComponent(head, pctxt, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017063 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017064 * SPEC (3) "If there is a non-·absent· {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017065 * affiliation}, then {scope} must be global."
17066 */
17067 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
17068 xmlSchemaPCustomErr(pctxt,
17069 XML_SCHEMAP_E_PROPS_CORRECT_3,
17070 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17071 "Only global element declarations can have a "
17072 "substitution group affiliation", NULL);
17073 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017074 }
17075 /*
17076 * TODO: SPEC (6) "Circular substitution groups are disallowed.
17077 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017078 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017079 * property."
17080 */
17081 if (head == elemDecl)
17082 circ = head;
17083 else if (SUBST_GROUP_AFF(head) != NULL)
17084 circ = xmlSchemaCheckSubstGroupCircular(head, head);
17085 else
17086 circ = NULL;
17087 if (circ != NULL) {
17088 xmlChar *strA = NULL, *strB = NULL;
17089
17090 xmlSchemaPCustomErrExt(pctxt,
17091 XML_SCHEMAP_E_PROPS_CORRECT_6,
17092 NULL, (xmlSchemaTypePtr) circ, circ->node,
17093 "The element declaration '%s' defines a circular "
17094 "substitution group to element declaration '%s'",
17095 xmlSchemaGetComponentQName(&strA, circ),
17096 xmlSchemaGetComponentQName(&strB, head),
17097 NULL);
17098 FREE_AND_NULL(strA)
17099 FREE_AND_NULL(strB)
17100 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
17101 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017102 /*
17103 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017104 * the {type definition}
17105 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017106 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017107 * of the {substitution group exclusions} of the {substitution group
17108 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
17109 * (if the {type definition} is complex) or as defined in
17110 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017111 * simple)."
17112 *
17113 * NOTE: {substitution group exclusions} means the values of the
17114 * attribute "final".
17115 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017116
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017117 if (typeDef != ELEM_TYPE(SUBST_GROUP_AFF(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017118 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017119
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017120 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
17121 set |= SUBSET_EXTENSION;
17122 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
17123 set |= SUBSET_RESTRICTION;
17124
17125 if (xmlSchemaCheckCOSDerivedOK(typeDef,
17126 ELEM_TYPE(head), set) != 0) {
17127 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
17128
17129 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017130 xmlSchemaPCustomErrExt(pctxt,
17131 XML_SCHEMAP_E_PROPS_CORRECT_4,
17132 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017133 "The type definition '%s' was "
17134 "either rejected by the substitution group "
17135 "affiliation '%s', or not validly derived from its type "
17136 "definition '%s'",
17137 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017138 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017139 xmlSchemaGetComponentQName(&strC, ELEM_TYPE(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017140 FREE_AND_NULL(strA)
17141 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017142 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017143 }
17144 }
17145 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017146 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017147 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017148 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017149 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017150 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017151 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017152 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017153 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017154 ((IS_SIMPLE_TYPE(typeDef) &&
17155 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017156 (IS_COMPLEX_TYPE(typeDef) &&
17157 HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017158 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
17159 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017160
17161 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
17162 xmlSchemaPCustomErr(pctxt,
17163 XML_SCHEMAP_E_PROPS_CORRECT_5,
17164 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17165 "The type definition (or type definition's content type) is or "
17166 "is derived from ID; value constraints are not allowed in "
17167 "conjunction with such a type definition", NULL);
17168 } else if (elemDecl->value != NULL) {
17169 int vcret;
17170 xmlNodePtr node = NULL;
17171
17172 /*
17173 * SPEC (2) "If there is a {value constraint}, the canonical lexical
17174 * representation of its value must be ·valid· with respect to the
17175 * {type definition} as defined in Element Default Valid (Immediate)
17176 * (§3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017177 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017178 if (typeDef == NULL) {
17179 xmlSchemaPErr(pctxt, elemDecl->node,
17180 XML_SCHEMAP_INTERNAL,
17181 "Internal error: xmlSchemaCheckElemPropsCorrect, "
17182 "type is missing... skipping validation of "
17183 "the value constraint", NULL, NULL);
17184 return (-1);
17185 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017186 if (elemDecl->node != NULL) {
17187 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
17188 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17189 BAD_CAST "fixed");
17190 else
17191 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17192 BAD_CAST "default");
17193 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017194 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
17195 typeDef, elemDecl->value, &(elemDecl->defVal));
17196 if (vcret != 0) {
17197 if (vcret < 0) {
17198 PERROR_INT("xmlSchemaElemCheckValConstr",
17199 "failed to validate the value constraint of an "
17200 "element declaration");
17201 return (-1);
17202 }
17203 return (vcret);
17204 }
17205 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017206
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017207 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017208}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017209
17210/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017211 * xmlSchemaCheckElemSubstGroup:
17212 * @ctxt: a schema parser context
17213 * @decl: the element declaration
17214 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017215 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017216 * Schema Component Constraint:
17217 * Substitution Group (cos-equiv-class)
17218 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017219 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017220 * a list will be built for each subst. group head, holding all direct
17221 * referents to this head.
17222 * NOTE that this function needs:
17223 * 1. circular subst. groups to be checked beforehand
17224 * 2. the declaration's type to be derived from the head's type
17225 *
17226 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017227 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017228 */
17229static void
17230xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
17231 xmlSchemaElementPtr elemDecl)
17232{
17233 if ((SUBST_GROUP_AFF(elemDecl) == NULL) ||
17234 /* SPEC (1) "Its {abstract} is false." */
17235 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
17236 return;
17237 {
17238 xmlSchemaElementPtr head;
17239 xmlSchemaTypePtr headType, type;
17240 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017241 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017242 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
17243 * {disallowed substitutions} as the blocking constraint, as defined in
17244 * Substitution Group OK (Transitive) (§3.3.6)."
17245 */
17246 for (head = SUBST_GROUP_AFF(elemDecl); head != NULL;
17247 head = SUBST_GROUP_AFF(head)) {
17248 set = 0;
17249 methSet = 0;
17250 /*
17251 * The blocking constraints.
17252 */
17253 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
17254 continue;
17255 headType = head->subtypes;
17256 type = elemDecl->subtypes;
17257 if (headType == type)
17258 goto add_member;
17259 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
17260 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17261 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
17262 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17263 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017264 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017265 * "The set of all {derivation method}s involved in the
17266 * derivation of D's {type definition} from C's {type definition}
17267 * does not intersect with the union of the blocking constraint,
17268 * C's {prohibited substitutions} (if C is complex, otherwise the
17269 * empty set) and the {prohibited substitutions} (respectively the
17270 * empty set) of any intermediate {type definition}s in the
17271 * derivation of D's {type definition} from C's {type definition}."
17272 */
17273 /*
17274 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
17275 * subst.head axis, the methSet does not need to be computed for
17276 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017277 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017278 /*
17279 * The set of all {derivation method}s involved in the derivation
17280 */
17281 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017282 if ((type->flags &
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017283 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
17284 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17285 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017286
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017287 if ((type->flags &
17288 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) &&
17289 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17290 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17291
17292 type = type->baseType;
17293 }
17294 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017295 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017296 * the head's type.
17297 */
17298 type = elemDecl->subtypes->baseType;
17299 while (type != NULL) {
17300 if (IS_COMPLEX_TYPE(type)) {
17301 if ((type->flags &
17302 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17303 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
17304 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17305 if ((type->flags &
17306 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17307 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17308 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17309 } else
17310 break;
17311 if (type == headType)
17312 break;
17313 type = type->baseType;
17314 }
17315 if ((set != 0) &&
17316 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17317 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
17318 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17319 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
17320 continue;
17321 }
17322add_member:
17323 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
17324 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
17325 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
17326 }
17327 }
17328}
17329
17330/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017331 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017332 * @item: an schema element declaration/particle
17333 * @ctxt: a schema parser context
17334 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017335 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017336 * Validates the value constraints of an element declaration.
17337 *
17338 * Fixes finish doing the computations on the element declarations.
17339 */
17340static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017341xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017342 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017343 const xmlChar * name ATTRIBUTE_UNUSED)
17344{
17345 if (elemDecl == NULL)
17346 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017347 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
17348 return;
17349 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017350 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
17351 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017352}
17353
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017354/**
17355 * xmlSchemaMiscRefFixup:
17356 * @item: an schema component
17357 * @ctxt: a schema parser context
17358 * @name: the internal name of the component
17359 *
17360 * Resolves references of misc. schema components.
17361 */
17362static void
17363xmlSchemaMiscRefFixup(xmlSchemaTreeItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017364 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017365 const xmlChar * name ATTRIBUTE_UNUSED)
17366{
17367 if (item->type == XML_SCHEMA_TYPE_PARTICLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017368 if ((item->children != NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017369 (item->children->type == XML_SCHEMA_EXTRA_QNAMEREF)) {
17370 xmlSchemaQNameRefPtr ref = (xmlSchemaQNameRefPtr) item->children;
17371 xmlSchemaTreeItemPtr refItem;
17372 /*
17373 * Resolve the reference.
17374 */
17375 item->children = NULL;
17376 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
17377 ref->itemType, ref->name, ref->targetNamespace);
17378 if (refItem == NULL) {
17379 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017380 NULL, GET_NODE(item), "ref", ref->name,
17381 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017382 } else {
17383 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
17384 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017385 * NOTE that we will assign the model group definition
17386 * itself to the "term" of the particle. This will ease
17387 * the check for circular model group definitions. After
17388 * that the "term" will be assigned the model group of the
17389 * model group definition.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017390 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017391 item->children = refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017392 } else
17393 item->children = refItem;
17394 }
17395 }
17396 }
17397}
17398
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017399static int
17400xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
17401 xmlSchemaValPtr y)
17402{
17403 xmlSchemaTypePtr tx, ty, ptx, pty;
17404 int ret;
17405
17406 while (x != NULL) {
17407 /* Same types. */
17408 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
17409 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
17410 ptx = xmlSchemaGetPrimitiveType(tx);
17411 pty = xmlSchemaGetPrimitiveType(ty);
17412 /*
17413 * (1) if a datatype T' is ·derived· by ·restriction· from an
17414 * atomic datatype T then the ·value space· of T' is a subset of
17415 * the ·value space· of T. */
17416 /*
17417 * (2) if datatypes T' and T'' are ·derived· by ·restriction·
17418 * from a common atomic ancestor T then the ·value space·s of T'
17419 * and T'' may overlap.
17420 */
17421 if (ptx != pty)
17422 return(0);
17423 /*
17424 * We assume computed values to be normalized, so do a fast
17425 * string comparison for string based types.
17426 */
17427 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
17428 IS_ANY_SIMPLE_TYPE(ptx)) {
17429 if (! xmlStrEqual(
17430 xmlSchemaValueGetAsString(x),
17431 xmlSchemaValueGetAsString(y)))
17432 return (0);
17433 } else {
17434 ret = xmlSchemaCompareValuesWhtsp(
17435 x, XML_SCHEMA_WHITESPACE_PRESERVE,
17436 y, XML_SCHEMA_WHITESPACE_PRESERVE);
17437 if (ret == -2)
17438 return(-1);
17439 if (ret != 0)
17440 return(0);
17441 }
17442 /*
17443 * Lists.
17444 */
17445 x = xmlSchemaValueGetNext(x);
17446 if (x != NULL) {
17447 y = xmlSchemaValueGetNext(y);
17448 if (y == NULL)
17449 return (0);
17450 } else if (xmlSchemaValueGetNext(y) != NULL)
17451 return (0);
17452 else
17453 return (1);
17454 }
17455 return (0);
17456}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017457
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017458/**
17459 * xmlSchemaAttrFixup:
17460 * @item: an schema attribute declaration/use.
17461 * @ctxt: a schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017462 * @name: the name of the attribute
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017463 *
17464 * Fixes finish doing the computations on attribute declarations/uses.
17465 */
17466static void
17467xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017468 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017469 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000017470{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017471 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017472 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017473 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000017474 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000017475 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017476 * The simple type definition corresponding to the <simpleType> element
17477 * information item in the [children], if present, otherwise the simple
17478 * type definition ·resolved· to by the ·actual value· of the type
Daniel Veillard01fa6152004-06-29 17:04:39 +000017479 * [attribute], if present, otherwise the ·simple ur-type definition·.
17480 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017481 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000017482 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017483 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
17484 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017485 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017486 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017487 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000017488
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017489 type = xmlSchemaGetType(ctxt->schema, item->typeName,
17490 item->typeNs);
17491 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017492 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017493 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017494 (xmlSchemaTypePtr) item, item->node,
17495 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017496 XML_SCHEMA_TYPE_SIMPLE, NULL);
17497 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017498 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017499
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017500 } else if (item->ref != NULL) {
17501 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000017502
Daniel Veillardc0826a72004-08-10 14:17:33 +000017503 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017504 * We have an attribute use here; assign the referenced
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017505 * attribute declaration.
17506 */
17507 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017508 * TODO: Evaluate, what errors could occur if the declaration is not
17509 * found. It might be possible that the "typefixup" might crash if
17510 * no ref declaration was found.
17511 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017512 decl = xmlSchemaGetAttributeDecl(ctxt->schema, item->ref, item->refNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017513 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017514 xmlSchemaPResCompAttrErr(ctxt,
17515 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017516 (xmlSchemaTypePtr) item, item->node,
17517 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017518 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017519 return;
17520 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017521 item->refDecl = decl;
17522 xmlSchemaAttrFixup(decl, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017523 item->subtypes = decl->subtypes;
17524 /*
17525 * Attribute Use Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017526 * au-props-correct.2: If the {attribute declaration} has a fixed
17527 * {value constraint}, then if the attribute use itself has a
17528 * {value constraint}, it must also be fixed and its value must match
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017529 * that of the {attribute declaration}'s {value constraint}.
17530 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017531 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017532 (item->defValue != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017533 if ((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017534 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017535 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17536 NULL, NULL, item->node,
17537 "The attribute declaration has a 'fixed' value constraint "
17538 ", thus it must be 'fixed' in attribute use as well",
17539 NULL);
17540 } else {
17541 if (! xmlSchemaAreValuesEqual(item->defVal, decl->defVal)) {
17542 xmlSchemaPCustomErr(ctxt,
17543 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17544 NULL, NULL, item->node,
17545 "The 'fixed' value constraint of the attribute use "
17546 "must match the attribute declaration's value "
17547 "constraint '%s'",
17548 decl->defValue);
17549 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017550 }
17551 /*
17552 * FUTURE: One should change the values of the attr. use
17553 * if ever validation should be attempted even if the
17554 * schema itself was not fully valid.
17555 */
17556 }
Daniel Veillard3646d642004-06-02 19:19:14 +000017557 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017558 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
17559 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017560}
17561
17562/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017563 * xmlSchemaResolveIDCKeyRef:
17564 * @idc: the identity-constraint definition
17565 * @ctxt: the schema parser context
17566 * @name: the attribute name
17567 *
17568 * Resolve keyRef references to key/unique IDCs.
17569 */
17570static void
17571xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017572 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000017573 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017574{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017575 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
17576 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017577 if (idc->ref->name != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017578 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017579 ctxt->schema->idcDef,
17580 idc->ref->name,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017581 idc->ref->targetNamespace);
17582 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017583 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017584 * TODO: It is actually not an error to fail to resolve.
17585 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017586 xmlSchemaPResCompAttrErr(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017587 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017588 (xmlSchemaTypePtr) idc, idc->node,
17589 "refer", idc->ref->name,
17590 idc->ref->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017591 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
17592 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017593 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017594 }
17595}
17596
17597/**
Daniel Veillard4255d502002-04-16 15:50:10 +000017598 * xmlSchemaParse:
17599 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017600 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017601 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000017602 * XML Shema struture which can be used to validate instances.
17603 * *WARNING* this interface is highly subject to change
17604 *
17605 * Returns the internal XML Schema structure built from the resource or
17606 * NULL in case of error
17607 */
17608xmlSchemaPtr
17609xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
17610{
17611 xmlSchemaPtr ret = NULL;
17612 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017613 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017614 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017615
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017616 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017617 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017618 * the API; i.e. not automatically by the validated instance document.
17619 */
17620
Daniel Veillard4255d502002-04-16 15:50:10 +000017621 xmlSchemaInitTypes();
17622
Daniel Veillard6045c902002-10-09 21:13:59 +000017623 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000017624 return (NULL);
17625
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017626 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017627 ctxt->counter = 0;
17628 ctxt->container = NULL;
17629
17630 /*
17631 * First step is to parse the input document into an DOM/Infoset
17632 */
Daniel Veillard6045c902002-10-09 21:13:59 +000017633 if (ctxt->URL != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017634 doc = xmlReadFile((const char *) ctxt->URL, NULL,
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017635 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017636 if (doc == NULL) {
17637 xmlSchemaPErr(ctxt, NULL,
17638 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017639 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017640 ctxt->URL, NULL);
17641 return (NULL);
17642 }
Daniel Veillard6045c902002-10-09 21:13:59 +000017643 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017644 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
17645 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017646 if (doc == NULL) {
17647 xmlSchemaPErr(ctxt, NULL,
17648 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017649 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017650 NULL, NULL);
17651 return (NULL);
17652 }
17653 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000017654 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000017655 } else if (ctxt->doc != NULL) {
17656 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017657 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000017658 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017659 xmlSchemaPErr(ctxt, NULL,
17660 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017661 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017662 NULL, NULL);
17663 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000017664 }
17665
17666 /*
17667 * Then extract the root and Schema parse it
17668 */
17669 root = xmlDocGetRootElement(doc);
17670 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017671 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
17672 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017673 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000017674 if (!preserve) {
17675 xmlFreeDoc(doc);
17676 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017677 return (NULL);
17678 }
17679
17680 /*
17681 * Remove all the blank text nodes
17682 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017683 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000017684
17685 /*
17686 * Then do the parsing for good
17687 */
17688 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000017689 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000017690 if (!preserve) {
17691 xmlFreeDoc(doc);
17692 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017693 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000017694 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017695 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017696 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000017697 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017698 ctxt->ctxtType = NULL;
17699 ctxt->parentItem = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017700
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017701 /*
17702 * Resolve base types of simple/complex types.
17703 */
17704 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaResolveTypeDefs, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017705
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017706 if (ctxt->nberrors != 0)
17707 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017708
17709 if (ret->volatiles != NULL) {
17710 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17711 int i;
17712 xmlSchemaTreeItemPtr item;
17713
17714 for (i = 0; i < list->nbItems; i++) {
17715 item = (xmlSchemaTreeItemPtr) list->items[i];
17716 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17717 xmlSchemaMiscRefFixup(item, ctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017718 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017719 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017720 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000017721 * Then fixup all attributes declarations
17722 */
17723 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017724 /*
17725 * Then fixup all attributes group declarations
17726 */
17727 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
17728 ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017729 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017730 * Resolve identity-constraint keyRefs.
17731 */
17732 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017733 /*
17734 * Check type defnitions for circular references.
17735 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017736 xmlHashScan(ret->typeDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017737 xmlSchemaCheckTypeDefCircular, ctxt);
17738 /*
17739 * Check model groups defnitions for circular references.
17740 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017741 xmlHashScan(ret->groupDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017742 xmlSchemaCheckGroupDefCircular, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017743 /*
17744 * Set the "term" of particles pointing to model group definitions
17745 * to the contained model group.
17746 */
17747 if (ret->volatiles != NULL) {
17748 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17749 int i;
17750 xmlSchemaParticlePtr item;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017751
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017752 for (i = 0; i < list->nbItems; i++) {
17753 item = (xmlSchemaParticlePtr) list->items[i];
17754 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17755 xmlSchemaGroupDefTermFixup(item, ctxt, NULL);
17756 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017757 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017758 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017759 * Check attribute groups for circular references.
17760 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017761 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
17762 xmlSchemaCheckAttributeGroupCircular, ctxt);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017763 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017764 * Then fix references of element declaration; apply constraints.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017765 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000017766 xmlHashScanFull(ret->elemDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017767 (xmlHashScannerFull) xmlSchemaElementFixup, ctxt);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017768 /*
17769 * We will stop here if the schema was not valid to avoid internal errors
17770 * on missing sub-components. This is not conforming to the spec, since it
17771 * allows missing components, but it might make further processing crash.
17772 * So see it as a very strict handling, which might be made more lax in the
17773 * future.
17774 */
17775 if (ctxt->nberrors != 0)
17776 goto exit;
17777 /*
17778 * Then fixup all types properties
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017779 */
17780 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017781 /*
17782 * Validate the value constraint of attribute declarations/uses.
17783 */
17784 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017785 /*
17786 * Validate the value constraint of element declarations.
17787 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017788 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElementDeclComponent, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017789
17790 if (ctxt->nberrors != 0)
17791 goto exit;
17792
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017793 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017794 * TODO: cos-element-consistent, cos-all-limited
17795 *
17796 * Then build the content model for all complex types
17797 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017798 xmlHashScan(ret->typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017799 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017800
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017801exit:
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017802 if (ctxt->nberrors != 0) {
17803 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017804 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017805 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017806 return (ret);
17807}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017808
Daniel Veillard4255d502002-04-16 15:50:10 +000017809/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000017810 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000017811 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000017812 * @err: the error callback
17813 * @warn: the warning callback
17814 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000017815 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017816 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017817 */
17818void
17819xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017820 xmlSchemaValidityErrorFunc err,
17821 xmlSchemaValidityWarningFunc warn, void *ctx)
17822{
Daniel Veillard4255d502002-04-16 15:50:10 +000017823 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017824 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000017825 ctxt->error = err;
17826 ctxt->warning = warn;
17827 ctxt->userData = ctx;
17828}
17829
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017830/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000017831 * xmlSchemaGetParserErrors:
17832 * @ctxt: a XMl-Schema parser context
17833 * @err: the error callback result
17834 * @warn: the warning callback result
17835 * @ctx: contextual data for the callbacks result
17836 *
17837 * Get the callback information used to handle errors for a parser context
17838 *
17839 * Returns -1 in case of failure, 0 otherwise
17840 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017841int
Daniel Veillard259f0df2004-08-18 09:13:18 +000017842xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
17843 xmlSchemaValidityErrorFunc * err,
17844 xmlSchemaValidityWarningFunc * warn, void **ctx)
17845{
17846 if (ctxt == NULL)
17847 return(-1);
17848 if (err != NULL)
17849 *err = ctxt->error;
17850 if (warn != NULL)
17851 *warn = ctxt->warning;
17852 if (ctx != NULL)
17853 *ctx = ctxt->userData;
17854 return(0);
17855}
17856
17857/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017858 * xmlSchemaFacetTypeToString:
17859 * @type: the facet type
17860 *
17861 * Convert the xmlSchemaTypeType to a char string.
17862 *
17863 * Returns the char string representation of the facet type if the
17864 * type is a facet and an "Internal Error" string otherwise.
17865 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017866static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017867xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
17868{
17869 switch (type) {
17870 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017871 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017872 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017873 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017874 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017875 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017876 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017877 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017878 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017879 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017880 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017881 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017882 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017883 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017884 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017885 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017886 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017887 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017888 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017889 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017890 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017891 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017892 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017893 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017894 default:
17895 break;
17896 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017897 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017898}
17899
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017900static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000017901xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
17902{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017903 /*
17904 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000017905 * from xsd:string.
17906 */
17907 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017908 /*
17909 * Note that we assume a whitespace of preserve for anySimpleType.
17910 */
17911 if ((type->builtInType == XML_SCHEMAS_STRING) ||
17912 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
17913 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000017914 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017915 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017916 else {
17917 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017918 * For all ·atomic· datatypes other than string (and types ·derived·
17919 * by ·restriction· from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000017920 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017921 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000017922 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017923 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017924 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017925 } else if (VARIETY_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017926 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017927 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017928 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017929 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
17930 } else if (VARIETY_UNION(type)) {
17931 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
17932 } else if (VARIETY_ATOMIC(type)) {
17933 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
17934 return (XML_SCHEMA_WHITESPACE_PRESERVE);
17935 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
17936 return (XML_SCHEMA_WHITESPACE_REPLACE);
17937 else
17938 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017939 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017940 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017941}
17942
Daniel Veillard4255d502002-04-16 15:50:10 +000017943/************************************************************************
17944 * *
17945 * Simple type validation *
17946 * *
17947 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000017948
Daniel Veillard4255d502002-04-16 15:50:10 +000017949
17950/************************************************************************
17951 * *
17952 * DOM Validation code *
17953 * *
17954 ************************************************************************/
17955
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017956static void
17957xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
17958{
17959 int i, nbItems;
17960 xmlSchemaTypePtr item, *items;
17961
17962
17963 /*
17964 * During the Assemble of the schema ctxt->curItems has
17965 * been filled with the relevant new items. Fix those up.
17966 */
17967 nbItems = ctxt->assemble->nbItems;
17968 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017969
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017970 for (i = 0; i < nbItems; i++) {
17971 item = items[i];
17972 switch (item->type) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017973 case XML_SCHEMA_TYPE_COMPLEX:
17974 case XML_SCHEMA_TYPE_SIMPLE:
17975 xmlSchemaResolveTypeDefs(item, ctxt, NULL);
17976 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017977 case XML_SCHEMA_TYPE_ATTRIBUTE:
17978 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
17979 break;
17980 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017981 xmlSchemaElementFixup((xmlSchemaElementPtr) item, ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017982 NULL, NULL, NULL);
17983 break;
17984 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017985 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017986 ctxt, NULL);
17987 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017988 case XML_SCHEMA_TYPE_PARTICLE:
17989 xmlSchemaMiscRefFixup((xmlSchemaTreeItemPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017990 default:
17991 break;
17992 }
17993 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017994 if (ctxt->nberrors != 0)
17995 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017996 /*
17997 * Circularity checks.
17998 */
17999 for (i = 0; i < nbItems; i++) {
18000 item = items[i];
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018001 switch (item->type) {
18002 case XML_SCHEMA_TYPE_COMPLEX:
18003 case XML_SCHEMA_TYPE_SIMPLE:
18004 xmlSchemaCheckTypeDefCircular(
18005 (xmlSchemaTypePtr) item, ctxt, NULL);
18006 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018007 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018008 xmlSchemaCheckGroupDefCircular(
18009 (xmlSchemaModelGroupDefPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018010 break;
18011 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
18012 xmlSchemaCheckAttributeGroupCircular(
18013 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
18014 break;
18015 default:
18016 break;
18017 }
18018 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018019 if (ctxt->nberrors != 0)
18020 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018021 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018022 * Set the "term" of particles pointing to model group definitions
18023 * to the contained model group.
18024 */
18025 for (i = 0; i < nbItems; i++) {
18026 item = items[i];
18027 if ((item->type == XML_SCHEMA_TYPE_PARTICLE) &&
18028 (((xmlSchemaParticlePtr) item)->children != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018029 (((xmlSchemaParticlePtr) item)->children->type ==
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018030 XML_SCHEMA_TYPE_GROUP)) {
18031 xmlSchemaGroupDefTermFixup((xmlSchemaParticlePtr) item,
18032 ctxt, NULL);
18033 }
18034 }
18035 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018036 * Fixup for simple/complex types.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018037 */
18038 for (i = 0; i < nbItems; i++) {
18039 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018040 switch (item->type) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018041 case XML_SCHEMA_TYPE_SIMPLE:
18042 case XML_SCHEMA_TYPE_COMPLEX:
18043 xmlSchemaTypeFixup(item, ctxt, NULL);
18044 break;
18045 default:
18046 break;
18047 }
18048 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018049 if (ctxt->nberrors != 0)
18050 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018051 /*
18052 * Validate value contraint values.
18053 */
18054 for (i = 0; i < nbItems; i++) {
18055 item = items[i];
18056 switch (item->type) {
18057 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018058 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item,
18059 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018060 break;
18061 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018062 xmlSchemaCheckElementDeclComponent((xmlSchemaElementPtr) item,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018063 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018064 break;
18065 default:
18066 break;
18067 }
18068 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018069 if (ctxt->nberrors != 0)
18070 return;
18071 /*
18072 * Build the content model for complex types.
18073 */
18074 for (i = 0; i < nbItems; i++) {
18075 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018076 switch (item->type) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018077 case XML_SCHEMA_TYPE_COMPLEX:
18078 xmlSchemaBuildContentModel(item, ctxt, NULL);
18079 break;
18080 default:
18081 break;
18082 }
18083 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018084}
18085
18086/**
18087 * xmlSchemaAssembleByLocation:
18088 * @pctxt: a schema parser context
18089 * @vctxt: a schema validation context
18090 * @schema: the existing schema
18091 * @node: the node that fired the assembling
18092 * @nsName: the namespace name of the new schema
18093 * @location: the location of the schema
18094 *
18095 * Expands an existing schema by an additional schema.
18096 *
18097 * Returns 0 if the new schema is correct, a positive error code
18098 * number otherwise and -1 in case of an internal or API error.
18099 */
18100static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018101xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018102 xmlSchemaPtr schema,
18103 xmlNodePtr node,
18104 const xmlChar *nsName,
18105 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018106{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018107 const xmlChar *targetNs, *oldtns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018108 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018109 int oldflags, ret = 0, oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018110 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018111 xmlSchemaParserCtxtPtr pctxt;
18112
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018113 /*
18114 * This should be used:
18115 * 1. on <import>(s)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018116 * 2. if requested by the validated instance
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018117 * 3. if requested via the API
18118 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018119 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018120 return (-1);
18121 /*
18122 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018123 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018124 if ((vctxt->pctxt == NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018125 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
18126 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018127 pctxt = vctxt->pctxt;
18128 /*
18129 * Set the counter to produce unique names for anonymous items.
18130 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018131 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018132 /*
18133 * Acquire the schema document.
18134 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018135 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) vctxt, schema,
18136 node, nsName, location, &doc, &targetNs, 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018137 if (ret != 0) {
18138 if (doc != NULL)
18139 xmlFreeDoc(doc);
18140 } else if (doc != NULL) {
18141 docElem = xmlDocGetRootElement(doc);
18142 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018143 * Create new assemble info.
18144 */
18145 if (pctxt->assemble == NULL) {
18146 pctxt->assemble = xmlSchemaNewAssemble();
18147 if (pctxt->assemble == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018148 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018149 "Memory error: xmlSchemaAssembleByLocation, "
18150 "allocating assemble info", NULL);
18151 xmlFreeDoc(doc);
18152 return (-1);
18153 }
18154 }
18155 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018156 * Save and reset the context & schema.
18157 */
18158 oldflags = schema->flags;
18159 oldtns = schema->targetNamespace;
18160 olddoc = schema->doc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018161 oldIsS4S = vctxt->pctxt->isS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018162
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018163 xmlSchemaClearSchemaDefaults(schema);
18164 schema->targetNamespace = targetNs;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018165 if ((targetNs != NULL) &&
18166 xmlStrEqual(targetNs, xmlSchemaNs)) {
18167 /*
18168 * We are parsing the schema for schema!
18169 */
18170 vctxt->pctxt->isS4S = 1;
18171 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018172 /* schema->nbCurItems = 0; */
18173 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018174 pctxt->ctxtType = NULL;
18175 pctxt->parentItem = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018176
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018177 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
18178 if (pctxt->nberrors != 0) {
18179 vctxt->nberrors += pctxt->nberrors;
18180 goto finally;
18181 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018182 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018183 if (pctxt->nberrors != 0) {
18184 vctxt->nberrors += pctxt->nberrors;
18185 goto finally;
18186 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018187 xmlSchemaPostSchemaAssembleFixup(pctxt);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018188 if (pctxt->nberrors != 0)
18189 vctxt->nberrors += pctxt->nberrors;
18190finally:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018191 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018192 * Set the counter of items.
18193 */
18194 schema->counter = pctxt->counter;
18195 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018196 * Free the list of assembled components.
18197 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018198 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018199 /*
18200 * Restore the context & schema.
18201 */
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018202 vctxt->pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018203 schema->flags = oldflags;
18204 schema->targetNamespace = oldtns;
18205 schema->doc = olddoc;
18206 ret = pctxt->err;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018207 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018208 return (ret);
18209}
18210
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018211static xmlSchemaAttrInfoPtr
18212xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
18213 int metaType)
18214{
18215 if (vctxt->nbAttrInfos == 0)
18216 return (NULL);
18217 {
18218 int i;
18219 xmlSchemaAttrInfoPtr iattr;
18220
18221 for (i = 0; i < vctxt->nbAttrInfos; i++) {
18222 iattr = vctxt->attrInfos[i];
18223 if (iattr->metaType == metaType)
18224 return (iattr);
18225 }
18226
18227 }
18228 return (NULL);
18229}
18230
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018231/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018232 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018233 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018234 *
18235 * Expands an existing schema by an additional schema using
18236 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
18237 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
18238 * must be set to 1.
18239 *
18240 * Returns 0 if the new schema is correct, a positive error code
18241 * number otherwise and -1 in case of an internal or API error.
18242 */
18243static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018244xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018245{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018246 const xmlChar *cur, *end;
18247 const xmlChar *nsname = NULL, *location;
18248 int count = 0;
18249 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018250 xmlSchemaAttrInfoPtr iattr;
18251
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018252 /*
18253 * Parse the value; we will assume an even number of values
18254 * to be given (this is how Xerces and XSV work).
18255 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018256 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
18257 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
18258 if (iattr == NULL)
18259 xmlSchemaGetMetaAttrInfo(vctxt,
18260 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
18261 if (iattr == NULL)
18262 return (0);
18263 cur = iattr->value;
18264 do {
18265 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018266 /*
18267 * Get the namespace name.
18268 */
18269 while (IS_BLANK_CH(*cur))
18270 cur++;
18271 end = cur;
18272 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18273 end++;
18274 if (end == cur)
18275 break;
18276 count++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018277 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018278 cur = end;
18279 }
18280 /*
18281 * Get the URI.
18282 */
18283 while (IS_BLANK_CH(*cur))
18284 cur++;
18285 end = cur;
18286 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18287 end++;
18288 if (end == cur)
18289 break;
18290 count++;
18291 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018292 cur = end;
18293 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
18294 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018295 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018296 VERROR_INT("xmlSchemaAssembleByXSI",
18297 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018298 return (-1);
18299 }
18300 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018301 return (ret);
18302}
18303
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018304#define VAL_CREATE_DICT if (vctxt->dict == NULL) vctxt->dict = xmlDictCreate();
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018305
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018306static const xmlChar *
18307xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
18308 const xmlChar *prefix)
18309{
18310 if (vctxt->sax != NULL) {
18311 int i, j;
18312 xmlSchemaNodeInfoPtr inode;
18313
18314 for (i = vctxt->depth; i >= 0; i--) {
18315 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
18316 inode = vctxt->elemInfos[i];
18317 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
18318 if (((prefix == NULL) &&
18319 (inode->nsBindings[j] == NULL)) ||
18320 ((prefix != NULL) && xmlStrEqual(prefix,
18321 inode->nsBindings[j]))) {
18322
18323 /*
18324 * Note that the namespace bindings are already
18325 * in a string dict.
18326 */
18327 return (inode->nsBindings[j+1]);
18328 }
18329 }
18330 }
18331 }
18332 return (NULL);
18333 } else if (vctxt->reader != NULL) {
18334 xmlChar *nsName;
18335
18336 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
18337 if (nsName != NULL) {
18338 const xmlChar *ret;
18339
18340 VAL_CREATE_DICT;
18341 ret = xmlDictLookup(vctxt->dict, nsName, -1);
18342 xmlFree(nsName);
18343 return (ret);
18344 } else
18345 return (NULL);
18346 } else {
18347 xmlNsPtr ns;
18348
18349 if ((vctxt->inode->node == NULL) ||
18350 (vctxt->inode->node->doc == NULL)) {
18351 VERROR_INT("xmlSchemaLookupNamespace",
18352 "no node or node's doc avaliable");
18353 return (NULL);
18354 }
18355 ns = xmlSearchNs(vctxt->inode->node->doc,
18356 vctxt->inode->node, prefix);
18357 if (ns != NULL)
18358 return (ns->href);
18359 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018360 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018361}
18362
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018363/*
18364* This one works on the schema of the validation context.
18365*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018366static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018367xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
18368 xmlSchemaPtr schema,
18369 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018370 const xmlChar *value,
18371 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018372 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018373{
18374 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018375
18376 if (vctxt && (vctxt->schema == NULL)) {
18377 VERROR_INT("xmlSchemaValidateNotation",
18378 "a schema is needed on the validation context");
18379 return (-1);
18380 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018381 ret = xmlValidateQName(value, 1);
18382 if (ret != 0)
18383 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018384 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018385 xmlChar *localName = NULL;
18386 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018387
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018388 localName = xmlSplitQName2(value, &prefix);
18389 if (prefix != NULL) {
18390 const xmlChar *nsName = NULL;
18391
18392 if (vctxt != NULL)
18393 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
18394 else if (node != NULL) {
18395 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
18396 if (ns != NULL)
18397 nsName = ns->href;
18398 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018399 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018400 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018401 return (1);
18402 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018403 if (nsName == NULL) {
18404 xmlFree(prefix);
18405 xmlFree(localName);
18406 return (1);
18407 }
18408 if (xmlHashLookup2(schema->notaDecl, localName,
18409 nsName) != NULL) {
18410 if (valNeeded && (val != NULL)) {
18411 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
18412 BAD_CAST xmlStrdup(nsName));
18413 if (*val == NULL)
18414 ret = -1;
18415 }
18416 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018417 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018418 xmlFree(prefix);
18419 xmlFree(localName);
18420 } else {
18421 if (xmlHashLookup2(schema->notaDecl, value, NULL) != NULL) {
18422 if (valNeeded && (val != NULL)) {
18423 (*val) = xmlSchemaNewNOTATIONValue(
18424 BAD_CAST xmlStrdup(value), NULL);
18425 if (*val == NULL)
18426 ret = -1;
18427 }
18428 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018429 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018430 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018431 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018432 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018433}
18434
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018435/************************************************************************
18436 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018437 * Validation of identity-constraints (IDC) *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018438 * *
18439 ************************************************************************/
18440
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018441/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018442 * xmlSchemaAugmentIDC:
18443 * @idcDef: the IDC definition
18444 *
18445 * Creates an augmented IDC definition item.
18446 *
18447 * Returns the item, or NULL on internal errors.
18448 */
18449static void
18450xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
18451 xmlSchemaValidCtxtPtr vctxt)
18452{
18453 xmlSchemaIDCAugPtr aidc;
18454
18455 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
18456 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018457 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018458 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
18459 NULL);
18460 return;
18461 }
18462 aidc->bubbleDepth = -1;
18463 aidc->def = idcDef;
18464 aidc->next = NULL;
18465 if (vctxt->aidcs == NULL)
18466 vctxt->aidcs = aidc;
18467 else {
18468 aidc->next = vctxt->aidcs;
18469 vctxt->aidcs = aidc;
18470 }
18471}
18472
18473/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018474 * xmlSchemaIDCNewBinding:
18475 * @idcDef: the IDC definition of this binding
18476 *
18477 * Creates a new IDC binding.
18478 *
18479 * Returns the new binding in case of succeeded, NULL on internal errors.
18480 */
18481static xmlSchemaPSVIIDCBindingPtr
18482xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
18483{
18484 xmlSchemaPSVIIDCBindingPtr ret;
18485
18486 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
18487 sizeof(xmlSchemaPSVIIDCBinding));
18488 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018489 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018490 "allocating a PSVI IDC binding item", NULL);
18491 return (NULL);
18492 }
18493 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
18494 ret->definition = idcDef;
18495 return (ret);
18496}
18497
18498/**
18499 * xmlSchemaIDCStoreNodeTableItem:
18500 * @vctxt: the WXS validation context
18501 * @item: the IDC node table item
18502 *
18503 * The validation context is used to store an IDC node table items.
18504 * They are stored to avoid copying them if IDC node-tables are merged
18505 * with corresponding parent IDC node-tables (bubbling).
18506 *
18507 * Returns 0 if succeeded, -1 on internal errors.
18508 */
18509static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018510xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018511 xmlSchemaPSVIIDCNodePtr item)
18512{
18513 /*
18514 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018515 */
18516 if (vctxt->idcNodes == NULL) {
18517 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018518 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
18519 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018520 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018521 "allocating the IDC node table item list", NULL);
18522 return (-1);
18523 }
18524 vctxt->sizeIdcNodes = 20;
18525 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
18526 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018527 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
18528 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018529 sizeof(xmlSchemaPSVIIDCNodePtr));
18530 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018531 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018532 "re-allocating the IDC node table item list", NULL);
18533 return (-1);
18534 }
18535 }
18536 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018537
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018538 return (0);
18539}
18540
18541/**
18542 * xmlSchemaIDCStoreKey:
18543 * @vctxt: the WXS validation context
18544 * @item: the IDC key
18545 *
18546 * The validation context is used to store an IDC key.
18547 *
18548 * Returns 0 if succeeded, -1 on internal errors.
18549 */
18550static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018551xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018552 xmlSchemaPSVIIDCKeyPtr key)
18553{
18554 /*
18555 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018556 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018557 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018558 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018559 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
18560 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018561 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018562 "allocating the IDC key storage list", NULL);
18563 return (-1);
18564 }
18565 vctxt->sizeIdcKeys = 40;
18566 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
18567 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018568 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
18569 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018570 sizeof(xmlSchemaPSVIIDCKeyPtr));
18571 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018572 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018573 "re-allocating the IDC key storage list", NULL);
18574 return (-1);
18575 }
18576 }
18577 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018578
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018579 return (0);
18580}
18581
18582/**
18583 * xmlSchemaIDCAppendNodeTableItem:
18584 * @bind: the IDC binding
18585 * @ntItem: the node-table item
18586 *
18587 * Appends the IDC node-table item to the binding.
18588 *
18589 * Returns 0 on success and -1 on internal errors.
18590 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018591static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018592xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
18593 xmlSchemaPSVIIDCNodePtr ntItem)
18594{
18595 if (bind->nodeTable == NULL) {
18596 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018597 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018598 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
18599 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018600 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018601 "allocating an array of IDC node-table items", NULL);
18602 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018603 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018604 } else if (bind->sizeNodes <= bind->nbNodes) {
18605 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018606 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18607 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018608 sizeof(xmlSchemaPSVIIDCNodePtr));
18609 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018610 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018611 "re-allocating an array of IDC node-table items", NULL);
18612 return(-1);
18613 }
18614 }
18615 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018616 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018617}
18618
18619/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018620 * xmlSchemaIDCAquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018621 * @vctxt: the WXS validation context
18622 * @matcher: the IDC matcher
18623 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018624 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018625 * of the given matcher. If none found, a new one is created
18626 * and added to the IDC table.
18627 *
18628 * Returns an IDC binding or NULL on internal errors.
18629 */
18630static xmlSchemaPSVIIDCBindingPtr
18631xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
18632 xmlSchemaIDCMatcherPtr matcher)
18633{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018634 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018635
18636 info = vctxt->elemInfos[matcher->depth];
18637
18638 if (info->idcTable == NULL) {
18639 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
18640 if (info->idcTable == NULL)
18641 return (NULL);
18642 return(info->idcTable);
18643 } else {
18644 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018645
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018646 bind = info->idcTable;
18647 do {
18648 if (bind->definition == matcher->aidc->def)
18649 return(bind);
18650 if (bind->next == NULL) {
18651 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
18652 if (bind->next == NULL)
18653 return (NULL);
18654 return(bind->next);
18655 }
18656 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018657 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018658 }
18659 return (NULL);
18660}
18661
18662/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018663 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018664 * @key: the IDC key
18665 *
18666 * Frees an IDC key together with its compiled value.
18667 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018668static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018669xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
18670{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018671 if (key->val != NULL)
18672 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018673 xmlFree(key);
18674}
18675
18676/**
18677 * xmlSchemaIDCFreeBinding:
18678 *
18679 * Frees an IDC binding. Note that the node table-items
18680 * are not freed.
18681 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018682static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018683xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
18684{
18685 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018686 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18687 int i;
18688 /*
18689 * Node-table items for keyrefs are not stored globally
18690 * to the validation context, since they are not bubbled.
18691 * We need to free them here.
18692 */
18693 for (i = 0; i < bind->nbNodes; i++) {
18694 xmlFree(bind->nodeTable[i]->keys);
18695 xmlFree(bind->nodeTable[i]);
18696 }
18697 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018698 xmlFree(bind->nodeTable);
18699 }
18700 xmlFree(bind);
18701}
18702
18703/**
18704 * xmlSchemaIDCFreeIDCTable:
18705 * @bind: the first IDC binding in the list
18706 *
18707 * Frees an IDC table, i.e. all the IDC bindings in the list.
18708 */
18709static void
18710xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
18711{
18712 xmlSchemaPSVIIDCBindingPtr prev;
18713
18714 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018715 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018716 bind = bind->next;
18717 xmlSchemaIDCFreeBinding(prev);
18718 }
18719}
18720
18721/**
18722 * xmlSchemaIDCFreeMatcherList:
18723 * @matcher: the first IDC matcher in the list
18724 *
18725 * Frees a list of IDC matchers.
18726 */
18727static void
18728xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
18729{
18730 xmlSchemaIDCMatcherPtr next;
18731
18732 while (matcher != NULL) {
18733 next = matcher->next;
18734 if (matcher->keySeqs != NULL) {
18735 int i;
18736 for (i = 0; i < matcher->sizeKeySeqs; i++)
18737 if (matcher->keySeqs[i] != NULL)
18738 xmlFree(matcher->keySeqs[i]);
18739 xmlFree(matcher->keySeqs);
18740 }
18741 xmlFree(matcher);
18742 matcher = next;
18743 }
18744}
18745
18746/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018747 * xmlSchemaIDCAddStateObject:
18748 * @vctxt: the WXS validation context
18749 * @matcher: the IDC matcher
18750 * @sel: the XPath information
18751 * @parent: the parent "selector" state object if any
18752 * @type: "selector" or "field"
18753 *
18754 * Creates/reuses and activates state objects for the given
18755 * XPath information; if the XPath expression consists of unions,
18756 * multiple state objects are created for every unioned expression.
18757 *
18758 * Returns 0 on success and -1 on internal errors.
18759 */
18760static int
18761xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
18762 xmlSchemaIDCMatcherPtr matcher,
18763 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018764 int type)
18765{
18766 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018767
18768 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018769 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018770 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018771 if (vctxt->xpathStatePool != NULL) {
18772 sto = vctxt->xpathStatePool;
18773 vctxt->xpathStatePool = sto->next;
18774 sto->next = NULL;
18775 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018776 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018777 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018778 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018779 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
18780 if (sto == NULL) {
18781 xmlSchemaVErrMemory(NULL,
18782 "allocating an IDC state object", NULL);
18783 return (-1);
18784 }
18785 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
18786 }
18787 /*
18788 * Add to global list.
18789 */
18790 if (vctxt->xpathStates != NULL)
18791 sto->next = vctxt->xpathStates;
18792 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018793
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018794 /*
18795 * Free the old xpath validation context.
18796 */
18797 if (sto->xpathCtxt != NULL)
18798 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
18799
18800 /*
18801 * Create a new XPath (pattern) validation context.
18802 */
18803 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
18804 (xmlPatternPtr) sel->xpathComp);
18805 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018806 VERROR_INT("xmlSchemaIDCAddStateObject",
18807 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018808 return (-1);
18809 }
18810 sto->type = type;
18811 sto->depth = vctxt->depth;
18812 sto->matcher = matcher;
18813 sto->sel = sel;
18814 sto->nbHistory = 0;
18815
18816#if DEBUG_IDC
18817 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
18818 sto->sel->xpath);
18819#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018820 return (0);
18821}
18822
18823/**
18824 * xmlSchemaXPathEvaluate:
18825 * @vctxt: the WXS validation context
18826 * @nodeType: the nodeType of the current node
18827 *
18828 * Evaluates all active XPath state objects.
18829 *
18830 * Returns the number of IC "field" state objects which resolved to
18831 * this node, 0 if none resolved and -1 on internal errors.
18832 */
18833static int
18834xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018835 xmlElementType nodeType)
18836{
18837 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018838 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018839
18840 if (vctxt->xpathStates == NULL)
18841 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018842
18843 if (nodeType == XML_ATTRIBUTE_NODE)
18844 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018845#if DEBUG_IDC
18846 {
18847 xmlChar *str = NULL;
18848 xmlGenericError(xmlGenericErrorContext,
18849 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018850 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
18851 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018852 FREE_AND_NULL(str)
18853 }
18854#endif
18855 /*
18856 * Process all active XPath state objects.
18857 */
18858 first = vctxt->xpathStates;
18859 sto = first;
18860 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018861#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018862 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018863 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
18864 sto->matcher->aidc->def->name, sto->sel->xpath);
18865 else
18866 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
18867 sto->matcher->aidc->def->name, sto->sel->xpath);
18868#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018869 if (nodeType == XML_ELEMENT_NODE)
18870 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018871 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018872 else
18873 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018874 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018875
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018876 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018877 VERROR_INT("xmlSchemaXPathEvaluate",
18878 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018879 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018880 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018881 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018882 goto next_sto;
18883 /*
18884 * Full match.
18885 */
18886#if DEBUG_IDC
18887 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018888 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018889#endif
18890 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018891 * Register a match in the state object history.
18892 */
18893 if (sto->history == NULL) {
18894 sto->history = (int *) xmlMalloc(5 * sizeof(int));
18895 if (sto->history == NULL) {
18896 xmlSchemaVErrMemory(NULL,
18897 "allocating the state object history", NULL);
18898 return(-1);
18899 }
18900 sto->sizeHistory = 10;
18901 } else if (sto->sizeHistory <= sto->nbHistory) {
18902 sto->sizeHistory *= 2;
18903 sto->history = (int *) xmlRealloc(sto->history,
18904 sto->sizeHistory * sizeof(int));
18905 if (sto->history == NULL) {
18906 xmlSchemaVErrMemory(NULL,
18907 "re-allocating the state object history", NULL);
18908 return(-1);
18909 }
18910 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018911 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018912
18913#ifdef DEBUG_IDC
18914 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
18915 vctxt->depth);
18916#endif
18917
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018918 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
18919 xmlSchemaIDCSelectPtr sel;
18920 /*
18921 * Activate state objects for the IDC fields of
18922 * the IDC selector.
18923 */
18924#if DEBUG_IDC
18925 xmlGenericError(xmlGenericErrorContext, "IDC: "
18926 "activating field states\n");
18927#endif
18928 sel = sto->matcher->aidc->def->fields;
18929 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018930 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
18931 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
18932 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018933 sel = sel->next;
18934 }
18935 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
18936 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018937 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018938 */
18939#if DEBUG_IDC
18940 xmlGenericError(xmlGenericErrorContext,
18941 "IDC: key found\n");
18942#endif
18943 /*
18944 * Notify that the character value of this node is
18945 * needed.
18946 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018947 if (resolved == 0) {
18948 if ((vctxt->inode->flags &
18949 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
18950 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
18951 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018952 resolved++;
18953 }
18954next_sto:
18955 if (sto->next == NULL) {
18956 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018957 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018958 */
18959 head = first;
18960 sto = vctxt->xpathStates;
18961 } else
18962 sto = sto->next;
18963 }
18964 return (resolved);
18965}
18966
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000018967static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018968xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000018969 xmlChar **buf,
18970 xmlSchemaPSVIIDCKeyPtr *seq,
18971 int count)
18972{
18973 int i, res;
18974 const xmlChar *value = NULL;
18975
18976 *buf = xmlStrdup(BAD_CAST "[");
18977 for (i = 0; i < count; i++) {
18978 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018979 res = xmlSchemaGetCanonValueWhtsp(seq[i]->val, &value,
18980 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type));
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000018981 if (res == 0)
18982 *buf = xmlStrcat(*buf, value);
18983 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018984 VERROR_INT("xmlSchemaFormatIDCKeySequence",
18985 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000018986 *buf = xmlStrcat(*buf, BAD_CAST "???");
18987 }
18988 if (i < count -1)
18989 *buf = xmlStrcat(*buf, BAD_CAST "', ");
18990 else
18991 *buf = xmlStrcat(*buf, BAD_CAST "'");
18992 if (value != NULL) {
18993 xmlFree((xmlChar *) value);
18994 value = NULL;
18995 }
18996 }
18997 *buf = xmlStrcat(*buf, BAD_CAST "]");
18998
18999 return (BAD_CAST *buf);
19000}
19001
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019002/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019003 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019004 * @vctxt: the WXS validation context
19005 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019006 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019007 *
19008 * Processes and pops the history items of the IDC state objects.
19009 * IDC key-sequences are validated/created on IDC bindings.
19010 *
19011 * Returns 0 on success and -1 on internal errors.
19012 */
19013static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019014xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019015 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019016{
19017 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019018 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019019 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019020 xmlSchemaTypePtr type = vctxt->inode->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019021
19022 if (vctxt->xpathStates == NULL)
19023 return (0);
19024 sto = vctxt->xpathStates;
19025
19026#if DEBUG_IDC
19027 {
19028 xmlChar *str = NULL;
19029 xmlGenericError(xmlGenericErrorContext,
19030 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019031 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19032 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019033 FREE_AND_NULL(str)
19034 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019035#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019036 /*
19037 * Evaluate the state objects.
19038 */
19039 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000019040 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
19041 if (res == -1) {
19042 VERROR_INT("xmlSchemaXPathProcessHistory",
19043 "calling xmlStreamPop()");
19044 return (-1);
19045 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019046#if DEBUG_IDC
19047 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
19048 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019049#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019050 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019051 goto deregister_check;
19052
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019053 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019054
19055 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019056 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019057 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019058 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019059 sto = sto->next;
19060 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019061 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019062 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19063 if (! IS_SIMPLE_TYPE(type)) {
19064 /*
19065 * Not qualified if the field resolves to a node of non
19066 * simple type.
19067 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019068 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19069 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019070 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19071 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019072 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019073
19074 sto->nbHistory--;
19075 goto deregister_check;
19076 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019077 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019078 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019079 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019080 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019081 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019082 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019083 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19084 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019085 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019086 sto->nbHistory--;
19087 goto deregister_check;
19088 } else {
19089 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
19090 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019091 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019092
19093 /*
19094 * The key will be anchored on the matcher's list of
19095 * key-sequences. The position in this list is determined
19096 * by the target node's depth relative to the matcher's
19097 * depth of creation (i.e. the depth of the scope element).
19098 */
19099 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019100 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019101
19102 /*
19103 * Create/grow the array of key-sequences.
19104 */
19105 if (matcher->keySeqs == NULL) {
19106 if (pos > 9)
19107 matcher->sizeKeySeqs = pos * 2;
19108 else
19109 matcher->sizeKeySeqs = 10;
19110 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19111 xmlMalloc(matcher->sizeKeySeqs *
19112 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19113 if (matcher->keySeqs == NULL) {
19114 xmlSchemaVErrMemory(NULL,
19115 "allocating an array of key-sequences",
19116 NULL);
19117 return(-1);
19118 }
19119 memset(matcher->keySeqs, 0,
19120 matcher->sizeKeySeqs *
19121 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19122 } else if (pos >= matcher->sizeKeySeqs) {
19123 int i = matcher->sizeKeySeqs;
19124
19125 matcher->sizeKeySeqs *= 2;
19126 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19127 xmlRealloc(matcher->keySeqs,
19128 matcher->sizeKeySeqs *
19129 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019130 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019131 xmlSchemaVErrMemory(NULL,
19132 "reallocating an array of key-sequences",
19133 NULL);
19134 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019135 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019136 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019137 * The array needs to be NULLed.
19138 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019139 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019140 for (; i < matcher->sizeKeySeqs; i++)
19141 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019142 }
19143
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019144 /*
19145 * Get/create the key-sequence.
19146 */
19147 keySeq = matcher->keySeqs[pos];
19148 if (keySeq == NULL) {
19149 goto create_sequence;
19150 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019151 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019152 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019153 * cvc-identity-constraint:
19154 * 3 For each node in the ·target node set· all
19155 * of the {fields}, with that node as the context
19156 * node, evaluate to either an empty node-set or
19157 * a node-set with exactly one member, which must
19158 * have a simple type.
19159 *
19160 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019161 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019162 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19163 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019164 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019165 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019166 "with more than one member",
19167 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019168 sto->nbHistory--;
19169 goto deregister_check;
19170 } else {
19171 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019172 }
19173 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019174
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019175create_sequence:
19176 /*
19177 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019178 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019179 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
19180 matcher->aidc->def->nbFields *
19181 sizeof(xmlSchemaPSVIIDCKeyPtr));
19182 if (keySeq == NULL) {
19183 xmlSchemaVErrMemory(NULL,
19184 "allocating an IDC key-sequence", NULL);
19185 return(-1);
19186 }
19187 memset(keySeq, 0, matcher->aidc->def->nbFields *
19188 sizeof(xmlSchemaPSVIIDCKeyPtr));
19189 matcher->keySeqs[pos] = keySeq;
19190create_key:
19191 /*
19192 * Created a key once per node only.
19193 */
19194 if (key == NULL) {
19195 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
19196 sizeof(xmlSchemaPSVIIDCKey));
19197 if (key == NULL) {
19198 xmlSchemaVErrMemory(NULL,
19199 "allocating a IDC key", NULL);
19200 xmlFree(keySeq);
19201 matcher->keySeqs[pos] = NULL;
19202 return(-1);
19203 }
19204 /*
19205 * Consume the compiled value.
19206 */
19207 key->type = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019208 key->val = vctxt->inode->val;
19209 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019210 /*
19211 * Store the key in a global list.
19212 */
19213 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
19214 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019215 return (-1);
19216 }
19217 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019218 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019219 }
19220 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019221
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019222 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
19223 xmlSchemaPSVIIDCBindingPtr bind;
19224 xmlSchemaPSVIIDCNodePtr ntItem;
19225 xmlSchemaIDCMatcherPtr matcher;
19226 xmlSchemaIDCPtr idc;
19227 int pos, i, j, nbKeys;
19228 /*
19229 * Here we have the following scenario:
19230 * An IDC 'selector' state object resolved to a target node,
19231 * during the time this target node was in the
19232 * ancestor-or-self axis, the 'field' state object(s) looked
19233 * out for matching nodes to create a key-sequence for this
19234 * target node. Now we are back to this target node and need
19235 * to put the key-sequence, together with the target node
19236 * itself, into the node-table of the corresponding IDC
19237 * binding.
19238 */
19239 matcher = sto->matcher;
19240 idc = matcher->aidc->def;
19241 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019242 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019243 /*
19244 * Check if the matcher has any key-sequences at all, plus
19245 * if it has a key-sequence for the current target node.
19246 */
19247 if ((matcher->keySeqs == NULL) ||
19248 (matcher->sizeKeySeqs <= pos)) {
19249 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19250 goto selector_key_error;
19251 else
19252 goto selector_leave;
19253 }
19254
19255 keySeq = &(matcher->keySeqs[pos]);
19256 if (*keySeq == NULL) {
19257 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19258 goto selector_key_error;
19259 else
19260 goto selector_leave;
19261 }
19262
19263 for (i = 0; i < nbKeys; i++) {
19264 if ((*keySeq)[i] == NULL) {
19265 /*
19266 * Not qualified, if not all fields did resolve.
19267 */
19268 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
19269 /*
19270 * All fields of a "key" IDC must resolve.
19271 */
19272 goto selector_key_error;
19273 }
19274 goto selector_leave;
19275 }
19276 }
19277 /*
19278 * All fields did resolve.
19279 */
19280
19281 /*
19282 * 4.1 If the {identity-constraint category} is unique(/key),
19283 * then no two members of the ·qualified node set· have
19284 * ·key-sequences· whose members are pairwise equal, as
19285 * defined by Equal in [XML Schemas: Datatypes].
19286 *
19287 * Get the IDC binding from the matcher and check for
19288 * duplicate key-sequences.
19289 */
19290 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
19291 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
19292 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019293 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019294
19295 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019296 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019297 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019298 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019299 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019300 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019301 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019302 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019303 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019304 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019305 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019306 if (res == -1) {
19307 return (-1);
19308 } else if (res == 0)
19309 break;
19310 }
19311 if (res == 1) {
19312 /*
19313 * Duplicate found.
19314 */
19315 break;
19316 }
19317 i++;
19318 } while (i < bind->nbNodes);
19319 if (i != bind->nbNodes) {
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019320 xmlChar *str = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019321 /*
19322 * TODO: Try to report the key-sequence.
19323 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019324 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19325 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019326 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019327 "Duplicate key-sequence %s",
19328 xmlSchemaFormatIDCKeySequence(vctxt, &str,
19329 (*keySeq), nbKeys), NULL);
19330 FREE_AND_NULL(str)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019331 goto selector_leave;
19332 }
19333 }
19334 /*
19335 * Add a node-table item to the IDC binding.
19336 */
19337 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
19338 sizeof(xmlSchemaPSVIIDCNode));
19339 if (ntItem == NULL) {
19340 xmlSchemaVErrMemory(NULL,
19341 "allocating an IDC node-table item", NULL);
19342 xmlFree(*keySeq);
19343 *keySeq = NULL;
19344 return(-1);
19345 }
19346 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
19347
19348 /*
19349 * Store the node-table item on global list.
19350 */
19351 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
19352 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
19353 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019354 xmlFree(*keySeq);
19355 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019356 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019357 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019358 }
19359 /*
19360 * Init the node-table item. Consume the key-sequence.
19361 */
19362 ntItem->node = vctxt->node;
19363 ntItem->keys = *keySeq;
19364 *keySeq = NULL;
19365 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
19366 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19367 /*
19368 * Free the item, since keyref items won't be
19369 * put on a global list.
19370 */
19371 xmlFree(ntItem->keys);
19372 xmlFree(ntItem);
19373 }
19374 return (-1);
19375 }
19376
19377 goto selector_leave;
19378selector_key_error:
19379 /*
19380 * 4.2.1 (KEY) The ·target node set· and the
19381 * ·qualified node set· are equal, that is, every
19382 * member of the ·target node set· is also a member
19383 * of the ·qualified node set· and vice versa.
19384 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019385 VERROR(XML_SCHEMAV_CVC_IDC, (xmlSchemaTypePtr) idc,
19386 "All 'key' fields must evaluate to a node");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019387selector_leave:
19388 /*
19389 * Free the key-sequence if not added to the IDC table.
19390 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019391 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019392 xmlFree(*keySeq);
19393 *keySeq = NULL;
19394 }
19395 } /* if selector */
19396
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019397 sto->nbHistory--;
19398
19399deregister_check:
19400 /*
19401 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019402 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019403 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019404#if DEBUG_IDC
19405 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
19406 sto->sel->xpath);
19407#endif
19408 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019409 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019410 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019411 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019412 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019413 nextsto = sto->next;
19414 /*
19415 * Unlink from the list of active XPath state objects.
19416 */
19417 vctxt->xpathStates = sto->next;
19418 sto->next = vctxt->xpathStatePool;
19419 /*
19420 * Link it to the pool of reusable state objects.
19421 */
19422 vctxt->xpathStatePool = sto;
19423 sto = nextsto;
19424 } else
19425 sto = sto->next;
19426 } /* while (sto != NULL) */
19427 return (0);
19428}
19429
19430/**
19431 * xmlSchemaIDCRegisterMatchers:
19432 * @vctxt: the WXS validation context
19433 * @elemDecl: the element declaration
19434 *
19435 * Creates helper objects to evaluate IDC selectors/fields
19436 * successively.
19437 *
19438 * Returns 0 if OK and -1 on internal errors.
19439 */
19440static int
19441xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
19442 xmlSchemaElementPtr elemDecl)
19443{
19444 xmlSchemaIDCMatcherPtr matcher, last = NULL;
19445 xmlSchemaIDCPtr idc, refIdc;
19446 xmlSchemaIDCAugPtr aidc;
19447
19448 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
19449 if (idc == NULL)
19450 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019451
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019452#if DEBUG_IDC
19453 {
19454 xmlChar *str = NULL;
19455 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019456 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019457 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19458 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019459 FREE_AND_NULL(str)
19460 }
19461#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019462 if (vctxt->inode->idcMatchers != NULL) {
19463 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19464 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019465 return (-1);
19466 }
19467 do {
19468 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19469 /*
19470 * Since IDCs bubbles are expensive we need to know the
19471 * depth at which the bubbles should stop; this will be
19472 * the depth of the top-most keyref IDC. If no keyref
19473 * references a key/unique IDC, the bubbleDepth will
19474 * be -1, indicating that no bubbles are needed.
19475 */
19476 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
19477 if (refIdc != NULL) {
19478 /*
19479 * Lookup the augmented IDC.
19480 */
19481 aidc = vctxt->aidcs;
19482 while (aidc != NULL) {
19483 if (aidc->def == refIdc)
19484 break;
19485 aidc = aidc->next;
19486 }
19487 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019488 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019489 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019490 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019491 return (-1);
19492 }
19493 if ((aidc->bubbleDepth == -1) ||
19494 (vctxt->depth < aidc->bubbleDepth))
19495 aidc->bubbleDepth = vctxt->depth;
19496 }
19497 }
19498 /*
19499 * Lookup the augmented IDC item for the IDC definition.
19500 */
19501 aidc = vctxt->aidcs;
19502 while (aidc != NULL) {
19503 if (aidc->def == idc)
19504 break;
19505 aidc = aidc->next;
19506 }
19507 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019508 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19509 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019510 return (-1);
19511 }
19512 /*
19513 * Create an IDC matcher for every IDC definition.
19514 */
19515 matcher = (xmlSchemaIDCMatcherPtr)
19516 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
19517 if (matcher == NULL) {
19518 xmlSchemaVErrMemory(vctxt,
19519 "allocating an IDC matcher", NULL);
19520 return (-1);
19521 }
19522 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
19523 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019524 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019525 else
19526 last->next = matcher;
19527 last = matcher;
19528
19529 matcher->type = IDC_MATCHER;
19530 matcher->depth = vctxt->depth;
19531 matcher->aidc = aidc;
19532#if DEBUG_IDC
19533 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
19534#endif
19535 /*
19536 * Init the automaton state object.
19537 */
19538 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019539 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019540 return (-1);
19541
19542 idc = idc->next;
19543 } while (idc != NULL);
19544 return (0);
19545}
19546
19547/**
19548 * xmlSchemaBubbleIDCNodeTables:
19549 * @depth: the current tree depth
19550 *
19551 * Merges IDC bindings of an element at @depth into the corresponding IDC
19552 * bindings of its parent element. If a duplicate note-table entry is found,
19553 * both, the parent node-table entry and child entry are discarded from the
19554 * node-table of the parent.
19555 *
19556 * Returns 0 if OK and -1 on internal errors.
19557 */
19558static int
19559xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
19560{
19561 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019562 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
19563 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019564 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
19565 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019566 int i, j, k, ret = 0, oldNum, newDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019567 int duplTop;
19568
19569 /*
19570 * The node table has the following sections:
19571 *
19572 * O --> old node-table entries (first)
19573 * O
19574 * + --> new node-table entries
19575 * +
19576 * % --> new duplicate node-table entries
19577 * %
19578 * # --> old duplicate node-table entries
19579 * # (last)
19580 *
19581 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019582 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019583 if (bind == NULL) {
19584 /* Fine, no table, no bubbles. */
19585 return (0);
19586 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019587
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019588 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
19589 /*
19590 * Walk all bindings; create new or add to existing bindings.
19591 * Remove duplicate key-sequences.
19592 */
19593start_binding:
19594 while (bind != NULL) {
19595 /*
19596 * Skip keyref IDCs.
19597 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019598 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19599 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019600 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019601 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019602 /*
19603 * Check if the key/unique IDC table needs to be bubbled.
19604 */
19605 aidc = vctxt->aidcs;
19606 do {
19607 if (aidc->def == bind->definition) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019608 if ((aidc->bubbleDepth == -1) ||
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019609 (aidc->bubbleDepth >= vctxt->depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019610 bind = bind->next;
19611 goto start_binding;
19612 }
19613 break;
19614 }
19615 aidc = aidc->next;
19616 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019617
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019618 if (parTable != NULL)
19619 parBind = *parTable;
19620 while (parBind != NULL) {
19621 /*
19622 * Search a matching parent binding for the
19623 * IDC definition.
19624 */
19625 if (parBind->definition == bind->definition) {
19626
19627 /*
19628 * Compare every node-table entry of the child node,
19629 * i.e. the key-sequence within, ...
19630 */
19631 oldNum = parBind->nbNodes; /* Skip newly added items. */
19632 duplTop = oldNum + parBind->nbDupls;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019633 newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019634
19635 for (i = 0; i < bind->nbNodes; i++) {
19636 node = bind->nodeTable[i];
19637 if (node == NULL)
19638 continue;
19639 /*
19640 * ...with every key-sequence of the parent node, already
19641 * evaluated to be a duplicate key-sequence.
19642 */
19643 if (parBind->nbDupls != 0) {
19644 j = bind->nbNodes + newDupls;
19645 while (j < duplTop) {
19646 parNode = parBind->nodeTable[j];
19647 for (k = 0; k < bind->definition->nbFields; k++) {
19648 key = node->keys[k];
19649 parKey = parNode->keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019650 ret = xmlSchemaAreValuesEqual(key->val,
19651 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019652 if (ret == -1) {
19653 /* TODO: Internal error */
19654 return(-1);
19655 } else if (ret == 0)
19656 break;
19657
19658 }
19659 if (ret == 1)
19660 /* Duplicate found. */
19661 break;
19662 j++;
19663 }
19664 if (j != duplTop) {
19665 /* Duplicate found. */
19666 continue;
19667 }
19668 }
19669 /*
19670 * ... and with every key-sequence of the parent node.
19671 */
19672 j = 0;
19673 while (j < oldNum) {
19674 parNode = parBind->nodeTable[j];
19675 /*
19676 * Compare key by key.
19677 */
19678 for (k = 0; k < parBind->definition->nbFields; k++) {
19679 key = node->keys[k];
19680 parKey = parNode->keys[k];
19681
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019682 ret = xmlSchemaAreValuesEqual(key->val,
19683 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019684 if (ret == -1) {
19685 /* TODO: Internal error */
19686 } else if (ret == 0)
19687 break;
19688
19689 }
19690 if (ret == 1)
19691 /*
19692 * The key-sequences are equal.
19693 */
19694 break;
19695 j++;
19696 }
19697 if (j != oldNum) {
19698 /*
19699 * Handle duplicates.
19700 */
19701 newDupls++;
19702 oldNum--;
19703 parBind->nbNodes--;
19704 /*
19705 * Move last old item to pos of duplicate.
19706 */
19707 parBind->nodeTable[j] =
19708 parBind->nodeTable[oldNum];
19709
19710 if (parBind->nbNodes != oldNum) {
19711 /*
19712 * If new items exist, move last new item to
19713 * last of old items.
19714 */
19715 parBind->nodeTable[oldNum] =
19716 parBind->nodeTable[parBind->nbNodes];
19717 }
19718 /*
19719 * Move duplicate to last pos of new/old items.
19720 */
19721 parBind->nodeTable[parBind->nbNodes] = parNode;
19722
19723 } else {
19724 /*
19725 * Add the node-table entry (node and key-sequence) of
19726 * the child node to the node table of the parent node.
19727 */
19728 if (parBind->nodeTable == NULL) {
19729 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019730 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019731 if (parBind->nodeTable == NULL) {
19732 xmlSchemaVErrMemory(NULL,
19733 "allocating IDC list of node-table items", NULL);
19734 return(-1);
19735 }
19736 parBind->sizeNodes = 1;
19737 } else if (duplTop >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019738 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019739 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19740 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
19741 sizeof(xmlSchemaPSVIIDCNodePtr));
19742 if (parBind->nodeTable == NULL) {
19743 xmlSchemaVErrMemory(NULL,
19744 "re-allocating IDC list of node-table items", NULL);
19745 return(-1);
19746 }
19747 }
19748
19749 /*
19750 * Move first old duplicate to last position
19751 * of old duplicates +1.
19752 */
19753 if (parBind->nbDupls != 0) {
19754 parBind->nodeTable[duplTop] =
19755 parBind->nodeTable[parBind->nbNodes + newDupls];
19756 }
19757 /*
19758 * Move first new duplicate to last position of
19759 * new duplicates +1.
19760 */
19761 if (newDupls != 0) {
19762 parBind->nodeTable[parBind->nbNodes + newDupls] =
19763 parBind->nodeTable[parBind->nbNodes];
19764 }
19765 /*
19766 * Append the new node-table entry to the 'new node-table
19767 * entries' section.
19768 */
19769 parBind->nodeTable[parBind->nbNodes] = node;
19770 parBind->nbNodes++;
19771 duplTop++;
19772 }
19773 }
19774 parBind->nbDupls += newDupls;
19775 break;
19776 }
19777 if (parBind->next == NULL)
19778 lastParBind = parBind;
19779 parBind = parBind->next;
19780 }
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019781 if ((parBind == NULL) && (bind->nbNodes != 0)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019782 /*
19783 * No binding for the IDC was found: create a new one and
19784 * copy all node-tables.
19785 */
19786 parBind = xmlSchemaIDCNewBinding(bind->definition);
19787 if (parBind == NULL)
19788 return(-1);
19789
19790 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19791 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
19792 if (parBind->nodeTable == NULL) {
19793 xmlSchemaVErrMemory(NULL,
19794 "allocating an array of IDC node-table items", NULL);
19795 xmlSchemaIDCFreeBinding(parBind);
19796 return(-1);
19797 }
19798 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019799 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019800 memcpy(parBind->nodeTable, bind->nodeTable,
19801 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019802 if (*parTable == NULL)
19803 *parTable = parBind;
19804 else
19805 lastParBind->next = parBind;
19806 }
19807 bind = bind->next;
19808 }
19809 return (0);
19810}
19811
19812/**
19813 * xmlSchemaCheckCVCIDCKeyRef:
19814 * @vctxt: the WXS validation context
19815 * @elemDecl: the element declaration
19816 *
19817 * Check the cvc-idc-keyref constraints.
19818 */
19819static int
19820xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
19821{
19822 xmlSchemaPSVIIDCBindingPtr refbind, bind;
19823
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019824 refbind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019825 /*
19826 * Find a keyref.
19827 */
19828 while (refbind != NULL) {
19829 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19830 int i, j, k, res;
19831 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
19832 xmlSchemaPSVIIDCKeyPtr refKey, key;
19833
19834 /*
19835 * Find the referred key/unique.
19836 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019837 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019838 do {
19839 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
19840 bind->definition)
19841 break;
19842 bind = bind->next;
19843 } while (bind != NULL);
19844
19845 /*
19846 * Search for a matching key-sequences.
19847 */
19848 for (i = 0; i < refbind->nbNodes; i++) {
19849 res = 0;
19850 if (bind != NULL) {
19851 refKeys = refbind->nodeTable[i]->keys;
19852 for (j = 0; j < bind->nbNodes; j++) {
19853 keys = bind->nodeTable[j]->keys;
19854 for (k = 0; k < bind->definition->nbFields; k++) {
19855 refKey = refKeys[k];
19856 key = keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019857 res = xmlSchemaAreValuesEqual(key->val,
19858 refKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019859 if (res == 0)
19860 break;
19861 else if (res == -1) {
19862 return (-1);
19863 }
19864 }
19865 if (res == 1) {
19866 /*
19867 * Match found.
19868 */
19869 break;
19870 }
19871 }
19872 }
19873 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019874 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019875 /* TODO: Report the key-sequence. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019876 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19877 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019878 (xmlSchemaTypePtr) refbind->definition,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019879 "No match found for key-sequence %s of key "
19880 "reference '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019881 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019882 refbind->nodeTable[i]->keys,
19883 refbind->definition->nbFields),
19884 xmlSchemaFormatQName(&strB,
19885 refbind->definition->targetNamespace,
19886 refbind->definition->name));
19887 FREE_AND_NULL(str);
19888 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019889 }
19890 }
19891 }
19892 refbind = refbind->next;
19893 }
19894 return (0);
19895}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019896
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019897/************************************************************************
19898 * *
19899 * XML Reader validation code *
19900 * *
19901 ************************************************************************/
19902
19903static xmlSchemaAttrInfoPtr
19904xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019905{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019906 xmlSchemaAttrInfoPtr iattr;
19907 /*
19908 * Grow/create list of attribute infos.
19909 */
19910 if (vctxt->attrInfos == NULL) {
19911 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
19912 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
19913 vctxt->sizeAttrInfos = 1;
19914 if (vctxt->attrInfos == NULL) {
19915 xmlSchemaVErrMemory(vctxt,
19916 "allocating attribute info list", NULL);
19917 return (NULL);
19918 }
19919 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
19920 vctxt->sizeAttrInfos++;
19921 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
19922 xmlRealloc(vctxt->attrInfos,
19923 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
19924 if (vctxt->attrInfos == NULL) {
19925 xmlSchemaVErrMemory(vctxt,
19926 "re-allocating attribute info list", NULL);
19927 return (NULL);
19928 }
19929 } else {
19930 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
19931 if (iattr->localName != NULL) {
19932 VERROR_INT("xmlSchemaGetFreshAttrInfo",
19933 "attr info not cleared");
19934 return (NULL);
19935 }
19936 iattr->nodeType = XML_ATTRIBUTE_NODE;
19937 return (iattr);
19938 }
19939 /*
19940 * Create an attribute info.
19941 */
19942 iattr = (xmlSchemaAttrInfoPtr)
19943 xmlMalloc(sizeof(xmlSchemaAttrInfo));
19944 if (iattr == NULL) {
19945 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
19946 return (NULL);
19947 }
19948 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
19949 iattr->nodeType = XML_ATTRIBUTE_NODE;
19950 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
19951
19952 return (iattr);
19953}
19954
19955static int
19956xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
19957 xmlNodePtr attrNode,
19958 const xmlChar *localName,
19959 const xmlChar *nsName,
19960 int ownedNames,
19961 xmlChar *value,
19962 int ownedValue)
19963{
19964 xmlSchemaAttrInfoPtr attr;
19965
19966 attr = xmlSchemaGetFreshAttrInfo(vctxt);
19967 if (attr == NULL) {
19968 VERROR_INT("xmlSchemaPushAttribute",
19969 "calling xmlSchemaGetFreshAttrInfo()");
19970 return (-1);
19971 }
19972 attr->node = attrNode;
19973 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
19974 attr->localName = localName;
19975 attr->nsName = nsName;
19976 if (ownedNames)
19977 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
19978 /*
19979 * Evaluate if it's an XSI attribute.
19980 */
19981 if (nsName != NULL) {
19982 if (xmlStrEqual(localName, BAD_CAST "nil")) {
19983 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
19984 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
19985 }
19986 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
19987 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
19988 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
19989 }
19990 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
19991 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
19992 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
19993 }
19994 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
19995 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
19996 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
19997 }
19998 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
19999 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
20000 }
20001 }
20002 attr->value = value;
20003 if (ownedValue)
20004 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
20005 if (attr->metaType != 0)
20006 attr->state = XML_SCHEMAS_ATTR_META;
20007 return (0);
20008}
20009
20010static void
20011xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
20012{
20013 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
20014 FREE_AND_NULL(ielem->localName);
20015 FREE_AND_NULL(ielem->nsName);
20016 } else {
20017 ielem->localName = NULL;
20018 ielem->nsName = NULL;
20019 }
20020 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
20021 FREE_AND_NULL(ielem->value);
20022 } else {
20023 ielem->value = NULL;
20024 }
20025 if (ielem->val != NULL) {
20026 xmlSchemaFreeValue(ielem->val);
20027 ielem->val = NULL;
20028 }
20029 if (ielem->idcMatchers != NULL) {
20030 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
20031 ielem->idcMatchers = NULL;
20032 }
20033 if (ielem->idcTable != NULL) {
20034 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
20035 ielem->idcTable = NULL;
20036 }
20037 if (ielem->regexCtxt != NULL) {
20038 xmlRegFreeExecCtxt(ielem->regexCtxt);
20039 ielem->regexCtxt = NULL;
20040 }
20041 if (ielem->nsBindings != NULL) {
20042 xmlFree((xmlChar **)ielem->nsBindings);
20043 ielem->nsBindings = NULL;
20044 ielem->nbNsBindings = 0;
20045 ielem->sizeNsBindings = 0;
20046 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020047}
20048
20049/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020050 * xmlSchemaGetFreshElemInfo:
20051 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020052 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020053 * Creates/reuses and initializes the element info item for
20054 * the currect tree depth.
20055 *
20056 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020057 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020058static xmlSchemaNodeInfoPtr
20059xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020060{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020061 xmlSchemaNodeInfoPtr info = NULL;
20062
20063 if (vctxt->depth > vctxt->sizeElemInfos) {
20064 VERROR_INT("xmlSchemaGetFreshElemInfo",
20065 "inconsistent depth encountered");
20066 return (NULL);
20067 }
20068 if (vctxt->elemInfos == NULL) {
20069 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20070 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
20071 if (vctxt->elemInfos == NULL) {
20072 xmlSchemaVErrMemory(vctxt,
20073 "allocating the element info array", NULL);
20074 return (NULL);
20075 }
20076 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
20077 vctxt->sizeElemInfos = 10;
20078 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
20079 int i = vctxt->sizeElemInfos;
20080
20081 vctxt->sizeElemInfos *= 2;
20082 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20083 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
20084 sizeof(xmlSchemaNodeInfoPtr));
20085 if (vctxt->elemInfos == NULL) {
20086 xmlSchemaVErrMemory(vctxt,
20087 "re-allocating the element info array", NULL);
20088 return (NULL);
20089 }
20090 /*
20091 * We need the new memory to be NULLed.
20092 * TODO: Use memset instead?
20093 */
20094 for (; i < vctxt->sizeElemInfos; i++)
20095 vctxt->elemInfos[i] = NULL;
20096 } else
20097 info = vctxt->elemInfos[vctxt->depth];
20098
20099 if (info == NULL) {
20100 info = (xmlSchemaNodeInfoPtr)
20101 xmlMalloc(sizeof(xmlSchemaNodeInfo));
20102 if (info == NULL) {
20103 xmlSchemaVErrMemory(vctxt,
20104 "allocating an element info", NULL);
20105 return (NULL);
20106 }
20107 vctxt->elemInfos[vctxt->depth] = info;
20108 } else {
20109 if (info->localName != NULL) {
20110 VERROR_INT("xmlSchemaGetFreshElemInfo",
20111 "elem info has not been cleared");
20112 return (NULL);
20113 }
20114 }
20115 memset(info, 0, sizeof(xmlSchemaNodeInfo));
20116 info->nodeType = XML_ELEMENT_NODE;
20117 info->depth = vctxt->depth;
20118
20119 return (info);
20120}
20121
20122#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
20123#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
20124#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
20125
20126static int
20127xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
20128 xmlNodePtr node,
20129 xmlSchemaTypePtr type,
20130 xmlSchemaValType valType,
20131 const xmlChar * value,
20132 xmlSchemaValPtr val,
20133 unsigned long length,
20134 int fireErrors)
20135{
20136 int ret, error = 0;
20137
20138 xmlSchemaTypePtr tmpType;
20139 xmlSchemaFacetLinkPtr facetLink;
20140 xmlSchemaFacetPtr facet;
20141 unsigned long len = 0;
20142 xmlSchemaWhitespaceValueType ws;
20143
20144 /*
20145 * In Libxml2, derived built-in types have currently no explicit facets.
20146 */
20147 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020148 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020149
20150 /*
20151 * NOTE: Do not jump away, if the facetSet of the given type is
20152 * empty: until now, "pattern" and "enumeration" facets of the
20153 * *base types* need to be checked as well.
20154 */
20155 if (type->facetSet == NULL)
20156 goto pattern_and_enum;
20157
20158 if (! VARIETY_ATOMIC(type)) {
20159 if (VARIETY_LIST(type))
20160 goto variety_list;
20161 else
20162 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020163 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020164 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020165 * Whitespace handling is only of importance for string-based
20166 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020167 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020168 tmpType = xmlSchemaGetPrimitiveType(type);
20169 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
20170 IS_ANY_SIMPLE_TYPE(tmpType)) {
20171 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20172 } else
20173 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
20174 /*
20175 * If the value was not computed (for string or
20176 * anySimpleType based types), then use the provided
20177 * type.
20178 */
20179 if (val == NULL)
20180 valType = valType;
20181 else
20182 valType = xmlSchemaGetValType(val);
20183
20184 ret = 0;
20185 for (facetLink = type->facetSet; facetLink != NULL;
20186 facetLink = facetLink->next) {
20187 /*
20188 * Skip the pattern "whiteSpace": it is used to
20189 * format the character content beforehand.
20190 */
20191 switch (facetLink->facet->type) {
20192 case XML_SCHEMA_FACET_WHITESPACE:
20193 case XML_SCHEMA_FACET_PATTERN:
20194 case XML_SCHEMA_FACET_ENUMERATION:
20195 continue;
20196 case XML_SCHEMA_FACET_LENGTH:
20197 case XML_SCHEMA_FACET_MINLENGTH:
20198 case XML_SCHEMA_FACET_MAXLENGTH:
20199 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
20200 valType, value, val, &len, ws);
20201 break;
20202 default:
20203 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
20204 valType, value, val, ws);
20205 break;
20206 }
20207 if (ret < 0) {
20208 AERROR_INT("xmlSchemaValidateFacets",
20209 "validating against a atomic type facet");
20210 return (-1);
20211 } else if (ret > 0) {
20212 if (fireErrors)
20213 xmlSchemaFacetErr(actxt, ret, node,
20214 value, len, type, facetLink->facet, NULL, NULL, NULL);
20215 else
20216 return (ret);
20217 if (error == 0)
20218 error = ret;
20219 }
20220 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020221 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020222
20223variety_list:
20224 if (! VARIETY_LIST(type))
20225 goto pattern_and_enum;
20226 /*
20227 * "length", "minLength" and "maxLength" of list types.
20228 */
20229 ret = 0;
20230 for (facetLink = type->facetSet; facetLink != NULL;
20231 facetLink = facetLink->next) {
20232
20233 switch (facetLink->facet->type) {
20234 case XML_SCHEMA_FACET_LENGTH:
20235 case XML_SCHEMA_FACET_MINLENGTH:
20236 case XML_SCHEMA_FACET_MAXLENGTH:
20237 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
20238 value, length, NULL);
20239 break;
20240 default:
20241 continue;
20242 }
20243 if (ret < 0) {
20244 AERROR_INT("xmlSchemaValidateFacets",
20245 "validating against a list type facet");
20246 return (-1);
20247 } else if (ret > 0) {
20248 if (fireErrors)
20249 xmlSchemaFacetErr(actxt, ret, node,
20250 value, length, type, facetLink->facet, NULL, NULL, NULL);
20251 else
20252 return (ret);
20253 if (error == 0)
20254 error = ret;
20255 }
20256 ret = 0;
20257 }
20258
20259pattern_and_enum:
20260 if (error >= 0) {
20261 int found = 0;
20262 /*
20263 * Process enumerations. Facet values are in the value space
20264 * of the defining type's base type. This seems to be a bug in the
20265 * XML Schema 1.0 spec. Use the whitespace type of the base type.
20266 * Only the first set of enumerations in the ancestor-or-self axis
20267 * is used for validation.
20268 */
20269 ret = 0;
20270 tmpType = type;
20271 do {
20272 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
20273 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
20274 continue;
20275 found = 1;
20276 ret = xmlSchemaAreValuesEqual(facet->val, val);
20277 if (ret == 1)
20278 break;
20279 else if (ret < 0) {
20280 AERROR_INT("xmlSchemaValidateFacets",
20281 "validating against an enumeration facet");
20282 return (-1);
20283 }
20284 }
20285 if (ret != 0)
20286 break;
20287 tmpType = tmpType->baseType;
20288 } while ((tmpType != NULL) &&
20289 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20290 if (found && (ret == 0)) {
20291 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
20292 if (fireErrors) {
20293 xmlSchemaFacetErr(actxt, ret, node,
20294 value, 0, type, NULL, NULL, NULL, NULL);
20295 } else
20296 return (ret);
20297 if (error == 0)
20298 error = ret;
20299 }
20300 }
20301
20302 if (error >= 0) {
20303 int found;
20304 /*
20305 * Process patters. Pattern facets are ORed at type level
20306 * and ANDed if derived. Walk the base type axis.
20307 */
20308 tmpType = type;
20309 facet = NULL;
20310 do {
20311 found = 0;
20312 for (facetLink = tmpType->facetSet; facetLink != NULL;
20313 facetLink = facetLink->next) {
20314 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
20315 continue;
20316 found = 1;
20317 /*
20318 * NOTE that for patterns, @value needs to be the
20319 * normalized vaule.
20320 */
20321 ret = xmlRegexpExec(facetLink->facet->regexp, value);
20322 if (ret == 1)
20323 break;
20324 else if (ret < 0) {
20325 AERROR_INT("xmlSchemaValidateFacets",
20326 "validating against a pattern facet");
20327 return (-1);
20328 } else {
20329 /*
20330 * Save the last non-validating facet.
20331 */
20332 facet = facetLink->facet;
20333 }
20334 }
20335 if (found && (ret != 1)) {
20336 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
20337 if (fireErrors) {
20338 xmlSchemaFacetErr(actxt, ret, node,
20339 value, 0, type, facet, NULL, NULL, NULL);
20340 } else
20341 return (ret);
20342 if (error == 0)
20343 error = ret;
20344 break;
20345 }
20346 tmpType = tmpType->baseType;
20347 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20348 }
20349
20350 return (error);
20351}
20352
20353static xmlChar *
20354xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
20355 const xmlChar *value)
20356{
20357 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
20358 case XML_SCHEMA_WHITESPACE_COLLAPSE:
20359 return (xmlSchemaCollapseString(value));
20360 case XML_SCHEMA_WHITESPACE_REPLACE:
20361 return (xmlSchemaWhiteSpaceReplace(value));
20362 default:
20363 return (NULL);
20364 }
20365}
20366
20367static int
20368xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
20369 const xmlChar *value,
20370 xmlSchemaValPtr *val,
20371 int valNeeded)
20372{
20373 int ret;
20374 const xmlChar *nsName;
20375 xmlChar *local, *prefix = NULL;
20376
20377 ret = xmlValidateQName(value, 1);
20378 if (ret != 0) {
20379 if (ret == -1) {
20380 VERROR_INT("xmlSchemaValidateQName",
20381 "calling xmlValidateQName()");
20382 return (-1);
20383 }
20384 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
20385 }
20386 /*
20387 * NOTE: xmlSplitQName2 will always return a duplicated
20388 * strings.
20389 */
20390 local = xmlSplitQName2(value, &prefix);
20391 if (local == NULL)
20392 local = xmlStrdup(value);
20393 /*
20394 * OPTIMIZE TODO: Use flags for:
20395 * - is there any namespace binding?
20396 * - is there a default namespace?
20397 */
20398 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20399
20400 if (prefix != NULL) {
20401 xmlFree(prefix);
20402 /*
20403 * A namespace must be found if the prefix is
20404 * NOT NULL.
20405 */
20406 if (nsName == NULL) {
20407 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20408 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, ret, NULL,
20409 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20410 "The QName value '%s' has no "
20411 "corresponding namespace declaration in "
20412 "scope", value, NULL);
20413 if (local != NULL)
20414 xmlFree(local);
20415 return (ret);
20416 }
20417 }
20418 if (valNeeded && val) {
20419 if (nsName != NULL)
20420 *val = xmlSchemaNewQNameValue(
20421 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
20422 else
20423 *val = xmlSchemaNewQNameValue(NULL,
20424 BAD_CAST local);
20425 } else
20426 xmlFree(local);
20427 return (0);
20428}
20429
20430/*
20431* cvc-simple-type
20432*/
20433static int
20434xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
20435 xmlNodePtr node,
20436 xmlSchemaTypePtr type,
20437 const xmlChar *value,
20438 xmlSchemaValPtr *retVal,
20439 int fireErrors,
20440 int normalize,
20441 int isNormalized)
20442{
20443 int ret = 0, valNeeded = (retVal) ? 1 : 0;
20444 xmlSchemaValPtr val = NULL;
20445 xmlSchemaWhitespaceValueType ws;
20446 xmlChar *normValue = NULL;
20447
20448#define NORMALIZE(atype) \
20449 if ((! isNormalized) && \
20450 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
20451 normValue = xmlSchemaNormalizeValue(atype, value); \
20452 if (normValue != NULL) \
20453 value = normValue; \
20454 isNormalized = 1; \
20455 }
20456
20457 if ((retVal != NULL) && (*retVal != NULL)) {
20458 xmlSchemaFreeValue(*retVal);
20459 *retVal = NULL;
20460 }
20461 /*
20462 * 3.14.4 Simple Type Definition Validation Rules
20463 * Validation Rule: String Valid
20464 */
20465 /*
20466 * 1 It is schema-valid with respect to that definition as defined
20467 * by Datatype Valid in [XML Schemas: Datatypes].
20468 */
20469 /*
20470 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
20471 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
20472 * the string must be a ·declared entity name·.
20473 */
20474 /*
20475 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
20476 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
20477 * then every whitespace-delimited substring of the string must be a ·declared
20478 * entity name·.
20479 */
20480 /*
20481 * 2.3 otherwise no further condition applies.
20482 */
20483 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
20484 valNeeded = 1;
20485 if (IS_ANY_SIMPLE_TYPE(type) || VARIETY_ATOMIC(type)) {
20486 xmlSchemaTypePtr biType; /* The built-in type. */
20487 /*
20488 * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match·
20489 * a literal in the ·lexical space· of {base type definition}"
20490 */
20491 /*
20492 * Whitespace-normalize.
20493 */
20494 NORMALIZE(type);
20495 if (type->type != XML_SCHEMA_TYPE_BASIC) {
20496 /*
20497 * Get the built-in type.
20498 */
20499 biType = type->baseType;
20500 while ((biType != NULL) &&
20501 (biType->type != XML_SCHEMA_TYPE_BASIC))
20502 biType = biType->baseType;
20503
20504 if (biType == NULL) {
20505 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20506 "could not get the built-in type");
20507 goto internal_error;
20508 }
20509 } else
20510 biType = type;
20511 /*
20512 * NOTATIONs need to be processed here, since they need
20513 * to lookup in the hashtable of NOTATION declarations of the schema.
20514 */
20515 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
20516 switch (biType->builtInType) {
20517 case XML_SCHEMAS_NOTATION:
20518 ret = xmlSchemaValidateNotation(
20519 (xmlSchemaValidCtxtPtr) actxt,
20520 ((xmlSchemaValidCtxtPtr) actxt)->schema,
20521 NULL, value, &val, valNeeded);
20522 break;
20523 case XML_SCHEMAS_QNAME:
20524 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
20525 value, &val, valNeeded);
20526 break;
20527 default:
20528 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20529 if (valNeeded)
20530 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20531 value, &val, NULL);
20532 else
20533 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20534 value, NULL, NULL);
20535 break;
20536 }
20537 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
20538 switch (biType->builtInType) {
20539 case XML_SCHEMAS_NOTATION:
20540 ret = xmlSchemaValidateNotation(NULL,
20541 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
20542 value, &val, valNeeded);
20543 break;
20544 default:
20545 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20546 if (valNeeded)
20547 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20548 value, &val, node);
20549 else
20550 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20551 value, NULL, node);
20552 break;
20553 }
20554 } else {
20555 /*
20556 * Validation via a public API is not implemented yet.
20557 */
20558 TODO
20559 goto internal_error;
20560 }
20561 if (ret != 0) {
20562 if (ret < 0) {
20563 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20564 "validating against a built-in type");
20565 goto internal_error;
20566 }
20567 if (VARIETY_LIST(type))
20568 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20569 else
20570 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20571 }
20572 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20573 /*
20574 * Check facets.
20575 */
20576 ret = xmlSchemaValidateFacets(actxt, node, type,
20577 (xmlSchemaValType) biType->builtInType, value, val,
20578 0, fireErrors);
20579 if (ret != 0) {
20580 if (ret < 0) {
20581 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20582 "validating facets of atomic simple type");
20583 goto internal_error;
20584 }
20585 if (VARIETY_LIST(type))
20586 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20587 else
20588 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20589 }
20590 }
20591 if (fireErrors && (ret > 0))
20592 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20593 } else if (VARIETY_LIST(type)) {
20594
20595 xmlSchemaTypePtr itemType;
20596 const xmlChar *cur, *end;
20597 xmlChar *tmpValue = NULL;
20598 unsigned long len = 0;
20599 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
20600 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
20601 * of white space separated tokens, each of which ·match·es a literal
20602 * in the ·lexical space· of {item type definition}
20603 */
20604 /*
20605 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
20606 * the list type has an enum or pattern facet.
20607 */
20608 NORMALIZE(type);
20609 /*
20610 * VAL TODO: Optimize validation of empty values.
20611 * VAL TODO: We do not have computed values for lists.
20612 */
20613 itemType = GET_LIST_ITEM_TYPE(type);
20614 if (value == NULL)
20615 value = BAD_CAST "";
20616 cur = value;
20617 do {
20618 while (IS_BLANK_CH(*cur))
20619 cur++;
20620 end = cur;
20621 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
20622 end++;
20623 if (end == cur)
20624 break;
20625 tmpValue = xmlStrndup(cur, end - cur);
20626 len++;
20627
20628 if (valNeeded)
20629 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20630 tmpValue, &curVal, fireErrors, 0, 1);
20631 else
20632 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20633 tmpValue, NULL, fireErrors, 0, 1);
20634 FREE_AND_NULL(tmpValue);
20635 if (curVal != NULL) {
20636 /*
20637 * Add to list of computed values.
20638 */
20639 if (val == NULL)
20640 val = curVal;
20641 else
20642 xmlSchemaValueAppend(prevVal, curVal);
20643 prevVal = curVal;
20644 curVal = NULL;
20645 }
20646 if (ret != 0) {
20647 if (ret < 0) {
20648 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20649 "validating an item of list simple type");
20650 goto internal_error;
20651 }
20652 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20653 break;
20654 }
20655 cur = end;
20656 } while (*cur != 0);
20657 FREE_AND_NULL(tmpValue);
20658 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20659 /*
20660 * Apply facets (pattern, enumeration).
20661 */
20662 ret = xmlSchemaValidateFacets(actxt, node, type,
20663 XML_SCHEMAS_UNKNOWN, value, val,
20664 len, fireErrors);
20665 if (ret != 0) {
20666 if (ret < 0) {
20667 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20668 "validating facets of list simple type");
20669 goto internal_error;
20670 }
20671 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20672 }
20673 }
20674 if (fireErrors && (ret > 0)) {
20675 /*
20676 * Report the normalized value.
20677 */
20678 normalize = 1;
20679 NORMALIZE(type);
20680 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20681 }
20682 } else if (VARIETY_UNION(type)) {
20683 xmlSchemaTypeLinkPtr memberLink;
20684 /*
20685 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
20686 * not apply directly; however, the normalization behavior of ·union·
20687 * types is controlled by the value of whiteSpace on that one of the
20688 * ·memberTypes· against which the ·union· is successfully validated.
20689 *
20690 * This means that the value is normalized by the first validating
20691 * member type, then the facets of the union type are applied. This
20692 * needs changing of the value!
20693 */
20694
20695 /*
20696 * 1.2.3 if {variety} is ·union· then the string must ·match· a
20697 * literal in the ·lexical space· of at least one member of
20698 * {member type definitions}
20699 */
20700 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
20701 if (memberLink == NULL) {
20702 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20703 "union simple type has no member types");
20704 goto internal_error;
20705 }
20706 /*
20707 * Always normalize union type values, since we currently
20708 * cannot store the whitespace information with the value
20709 * itself; otherwise a later value-comparison would be
20710 * not possible.
20711 */
20712 while (memberLink != NULL) {
20713 if (valNeeded)
20714 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20715 memberLink->type, value, &val, 0, 1, 0);
20716 else
20717 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20718 memberLink->type, value, NULL, 0, 1, 0);
20719 if (ret <= 0)
20720 break;
20721 memberLink = memberLink->next;
20722 }
20723 if (ret != 0) {
20724 if (ret < 0) {
20725 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20726 "validating members of union simple type");
20727 goto internal_error;
20728 }
20729 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20730 }
20731 /*
20732 * Apply facets (pattern, enumeration).
20733 */
20734 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20735 /*
20736 * The normalization behavior of ·union· types is controlled by
20737 * the value of whiteSpace on that one of the ·memberTypes·
20738 * against which the ·union· is successfully validated.
20739 */
20740 NORMALIZE(memberLink->type);
20741 ret = xmlSchemaValidateFacets(actxt, node, type,
20742 XML_SCHEMAS_UNKNOWN, value, val,
20743 0, fireErrors);
20744 if (ret != 0) {
20745 if (ret < 0) {
20746 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20747 "validating facets of union simple type");
20748 goto internal_error;
20749 }
20750 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20751 }
20752 }
20753 if (fireErrors && (ret > 0))
20754 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20755 }
20756
20757 if (normValue != NULL)
20758 xmlFree(normValue);
20759 if (ret == 0) {
20760 if (retVal != NULL)
20761 *retVal = val;
20762 else if (val != NULL)
20763 xmlSchemaFreeValue(val);
20764 } else if (val != NULL)
20765 xmlSchemaFreeValue(val);
20766 return (ret);
20767internal_error:
20768 if (normValue != NULL)
20769 xmlFree(normValue);
20770 if (val != NULL)
20771 xmlSchemaFreeValue(val);
20772 return (-1);
20773}
20774
20775static int
20776xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
20777 const xmlChar *value,
20778 const xmlChar **nsName,
20779 const xmlChar **localName)
20780{
20781 int ret = 0;
20782
20783 if ((nsName == NULL) || (localName == NULL))
20784 return (-1);
20785 *nsName = NULL;
20786 *localName = NULL;
20787
20788 ret = xmlValidateQName(value, 1);
20789 if (ret == -1)
20790 return (-1);
20791 if (ret > 0) {
20792 xmlSchemaSimpleTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
20793 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20794 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
20795 return (1);
20796 }
20797 {
20798 xmlChar *local = NULL;
20799 xmlChar *prefix;
20800
20801 /*
20802 * NOTE: xmlSplitQName2 will return a duplicated
20803 * string.
20804 */
20805 local = xmlSplitQName2(value, &prefix);
20806 VAL_CREATE_DICT;
20807 if (local == NULL)
20808 *localName = xmlDictLookup(vctxt->dict, value, -1);
20809 else {
20810 *localName = xmlDictLookup(vctxt->dict, local, -1);
20811 xmlFree(local);
20812 }
20813
20814 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20815
20816 if (prefix != NULL) {
20817 xmlFree(prefix);
20818 /*
20819 * A namespace must be found if the prefix is NOT NULL.
20820 */
20821 if (*nsName == NULL) {
20822 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20823 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20824 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20825 "The QName value '%s' has no "
20826 "corresponding namespace declaration in scope",
20827 value, NULL);
20828 return (2);
20829 }
20830 }
20831 }
20832 return (0);
20833}
20834
20835static int
20836xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
20837 xmlSchemaAttrInfoPtr iattr,
20838 xmlSchemaTypePtr *localType,
20839 xmlSchemaElementPtr elemDecl)
20840{
20841 int ret = 0;
20842 /*
20843 * cvc-elt (3.3.4) : (4)
20844 * AND
20845 * Schema-Validity Assessment (Element) (cvc-assess-elt)
20846 * (1.2.1.2.1) - (1.2.1.2.4)
20847 * Handle 'xsi:type'.
20848 */
20849 if (localType == NULL)
20850 return (-1);
20851 *localType = NULL;
20852 if (iattr == NULL)
20853 return (0);
20854 else {
20855 const xmlChar *nsName = NULL, *local = NULL;
20856 /*
20857 * TODO: We should report a *warning* that the type was overriden
20858 * by the instance.
20859 */
20860 ACTIVATE_ATTRIBUTE(iattr);
20861 /*
20862 * (cvc-elt) (3.3.4) : (4.1)
20863 * (cvc-assess-elt) (1.2.1.2.2)
20864 */
20865 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
20866 &nsName, &local);
20867 if (ret != 0) {
20868 if (ret < 0) {
20869 VERROR_INT("xmlSchemaValidateElementByDeclaration",
20870 "calling xmlSchemaQNameExpand() to validate the "
20871 "attribute 'xsi:type'");
20872 goto internal_error;
20873 }
20874 goto exit;
20875 }
20876 /*
20877 * (cvc-elt) (3.3.4) : (4.2)
20878 * (cvc-assess-elt) (1.2.1.2.3)
20879 */
20880 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
20881 if (*localType == NULL) {
20882 xmlChar *str = NULL;
20883
20884 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20885 XML_SCHEMAV_CVC_ELT_4_2, NULL,
20886 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20887 "The QName value '%s' of the xsi:type attribute does not "
20888 "resolve to a type definition",
20889 xmlSchemaFormatQName(&str, nsName, local), NULL);
20890 FREE_AND_NULL(str);
20891 ret = vctxt->err;
20892 goto exit;
20893 }
20894 if (elemDecl != NULL) {
20895 int set = 0;
20896
20897 /*
20898 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
20899 * "The ·local type definition· must be validly
20900 * derived from the {type definition} given the union of
20901 * the {disallowed substitutions} and the {type definition}'s
20902 * {prohibited substitutions}, as defined in
20903 * Type Derivation OK (Complex) (§3.4.6)
20904 * (if it is a complex type definition),
20905 * or given {disallowed substitutions} as defined in Type
20906 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
20907 * definition)."
20908 *
20909 * {disallowed substitutions}: the "block" on the element decl.
20910 * {prohibited substitutions}: the "block" on the type def.
20911 */
20912 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
20913 (elemDecl->subtypes->flags &
20914 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
20915 set |= SUBSET_EXTENSION;
20916
20917 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
20918 (elemDecl->subtypes->flags &
20919 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
20920 set |= SUBSET_RESTRICTION;
20921
20922 if (xmlSchemaCheckCOSDerivedOK(*localType,
20923 elemDecl->subtypes, set) != 0) {
20924 xmlChar *str = NULL;
20925
20926 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20927 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
20928 "The type definition '%s', specified by xsi:type, is "
20929 "blocked or not validly derived from the type definition "
20930 "of the element declaration",
20931 xmlSchemaFormatQName(&str,
20932 (*localType)->targetNamespace,
20933 (*localType)->name),
20934 NULL);
20935 FREE_AND_NULL(str);
20936 ret = vctxt->err;
20937 *localType = NULL;
20938 }
20939 }
20940 }
20941exit:
20942 ACTIVATE_ELEM;
20943 return (ret);
20944internal_error:
20945 ACTIVATE_ELEM;
20946 return (-1);
20947}
20948
20949static int
20950xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
20951{
20952 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
20953 xmlSchemaTypePtr actualType = ELEM_TYPE(elemDecl);
20954
20955 /*
20956 * cvc-elt (3.3.4) : 1
20957 */
20958 if (elemDecl == NULL) {
20959 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
20960 "No matching declaration available");
20961 return (vctxt->err);
20962 }
20963 /*
20964 * cvc-elt (3.3.4) : 2
20965 */
20966 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
20967 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
20968 "The element declaration is abstract");
20969 return (vctxt->err);
20970 }
20971 if (actualType == NULL) {
20972 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
20973 "The type definition is absent");
20974 return (XML_SCHEMAV_CVC_TYPE_1);
20975 }
20976 if (vctxt->nbAttrInfos != 0) {
20977 int ret;
20978 xmlSchemaAttrInfoPtr iattr;
20979 /*
20980 * cvc-elt (3.3.4) : 3
20981 * Handle 'xsi:nil'.
20982 */
20983 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
20984 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
20985 if (iattr) {
20986 ACTIVATE_ATTRIBUTE(iattr);
20987 /*
20988 * Validate the value.
20989 */
20990 ret = xmlSchemaVCheckCVCSimpleType(
20991 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
20992 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
20993 iattr->value, &(iattr->val), 1, 0, 0);
20994 ACTIVATE_ELEM;
20995 if (ret < 0) {
20996 VERROR_INT("xmlSchemaValidateElemDecl",
20997 "calling xmlSchemaVCheckCVCSimpleType() to "
20998 "validate the attribute 'xsi:nil'");
20999 return (-1);
21000 }
21001 if (ret == 0) {
21002 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
21003 /*
21004 * cvc-elt (3.3.4) : 3.1
21005 */
21006 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
21007 "The element is not 'nillable'");
21008 /* Does not return an error on purpose. */
21009 } else {
21010 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
21011 /*
21012 * cvc-elt (3.3.4) : 3.2.2
21013 */
21014 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
21015 (elemDecl->value != NULL)) {
21016 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
21017 "The element cannot be 'nilled' because "
21018 "there is a fixed value constraint defined "
21019 "for it");
21020 /* Does not return an error on purpose. */
21021 } else
21022 vctxt->inode->flags |=
21023 XML_SCHEMA_ELEM_INFO_NILLED;
21024 }
21025 }
21026 }
21027 }
21028 /*
21029 * cvc-elt (3.3.4) : 4
21030 * Handle 'xsi:type'.
21031 */
21032 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21033 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21034 if (iattr) {
21035 xmlSchemaTypePtr localType = NULL;
21036
21037 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
21038 elemDecl);
21039 if (ret != 0) {
21040 if (ret == -1) {
21041 VERROR_INT("xmlSchemaValidateElemDecl",
21042 "calling xmlSchemaProcessXSIType() to "
21043 "process the attribute 'xsi:type'");
21044 return (-1);
21045 }
21046 /* Does not return an error on purpose. */
21047 }
21048 if (localType != NULL) {
21049 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
21050 actualType = localType;
21051 }
21052 }
21053 }
21054 /*
21055 * IDC: Register identity-constraint XPath matchers.
21056 */
21057 if ((elemDecl->idcs != NULL) &&
21058 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
21059 return (-1);
21060 /*
21061 * No actual type definition.
21062 */
21063 if (actualType == NULL) {
21064 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21065 "The type definition is absent");
21066 return (XML_SCHEMAV_CVC_TYPE_1);
21067 }
21068 /*
21069 * Remember the actual type definition.
21070 */
21071 vctxt->inode->typeDef = actualType;
21072
21073 return (0);
21074}
21075
21076static int
21077xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
21078{
21079 xmlSchemaAttrInfoPtr iattr;
21080 int ret = 0, i;
21081
21082 /*
21083 * SPEC cvc-type (3.1.1)
21084 * "The attributes of must be empty, excepting those whose namespace
21085 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
21086 * whose local name is one of type, nil, schemaLocation or
21087 * noNamespaceSchemaLocation."
21088 */
21089 if (vctxt->nbAttrInfos == 0)
21090 return (0);
21091 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21092 iattr = vctxt->attrInfos[i];
21093 if (! iattr->metaType) {
21094 ACTIVATE_ATTRIBUTE(iattr)
21095 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21096 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
21097 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
21098 }
21099 }
21100 ACTIVATE_ELEM
21101 return (ret);
21102}
21103
21104/*
21105* Cleanup currently used attribute infos.
21106*/
21107static void
21108xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
21109{
21110 int i;
21111 xmlSchemaAttrInfoPtr attr;
21112
21113 if (vctxt->nbAttrInfos == 0)
21114 return;
21115 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21116 attr = vctxt->attrInfos[i];
21117 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
21118 if (attr->localName != NULL)
21119 xmlFree((xmlChar *) attr->localName);
21120 if (attr->nsName != NULL)
21121 xmlFree((xmlChar *) attr->nsName);
21122 }
21123 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
21124 if (attr->value != NULL)
21125 xmlFree((xmlChar *) attr->value);
21126 }
21127 if (attr->val != NULL) {
21128 xmlSchemaFreeValue(attr->val);
21129 attr->val = NULL;
21130 }
21131 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
21132 }
21133 vctxt->nbAttrInfos = 0;
21134}
21135
21136/*
21137* 3.4.4 Complex Type Definition Validation Rules
21138* Element Locally Valid (Complex Type) (cvc-complex-type)
21139* 3.2.4 Attribute Declaration Validation Rules
21140* Validation Rule: Attribute Locally Valid (cvc-attribute)
21141* Attribute Locally Valid (Use) (cvc-au)
21142*
21143* Only "assessed" attribute information items will be visible to
21144* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
21145*/
21146static int
21147xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
21148{
21149 xmlSchemaTypePtr type = vctxt->inode->typeDef;
21150 xmlSchemaAttributeLinkPtr attrUseLink;
21151 xmlSchemaAttributePtr attrUse = NULL, attrDecl = NULL;
21152 xmlSchemaAttrInfoPtr attr, tmpAttr;
21153 int i, found, nbAttrs;
21154 int xpathRes = 0, res, wildIDs = 0, fixed;
21155
21156 /*
21157 * SPEC (cvc-attribute)
21158 * (1) "The declaration must not be ·absent· (see Missing
21159 * Sub-components (§5.3) for how this can fail to be
21160 * the case)."
21161 * (2) "Its {type definition} must not be absent."
21162 *
21163 * NOTE (1) + (2): This is not handled here, since we currently do not
21164 * allow validation against schemas which have missing sub-components.
21165 *
21166 * SPEC (cvc-complex-type)
21167 * (3) "For each attribute information item in the element information
21168 * item's [attributes] excepting those whose [namespace name] is
21169 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
21170 * [local name] is one of type, nil, schemaLocation or
21171 * noNamespaceSchemaLocation, the appropriate case among the following
21172 * must be true:
21173 *
21174 */
21175 nbAttrs = vctxt->nbAttrInfos;
21176 for (attrUseLink = type->attributeUses; attrUseLink != NULL;
21177 attrUseLink = attrUseLink->next) {
21178
21179 found = 0;
21180 attrUse = attrUseLink->attr;
21181 /*
21182 * VAL TODO: Implement a real "attribute use" component.
21183 */
21184 if (attrUse->refDecl != NULL)
21185 attrDecl = attrUse->refDecl;
21186 else
21187 attrDecl = attrUse;
21188 for (i = 0; i < nbAttrs; i++) {
21189 attr = vctxt->attrInfos[i];
21190 /*
21191 * SPEC (cvc-complex-type) (3)
21192 * Skip meta attributes.
21193 */
21194 if (attr->metaType)
21195 continue;
21196 if (attr->localName[0] != attrDecl->name[0])
21197 continue;
21198 if (!xmlStrEqual(attr->localName, attrDecl->name))
21199 continue;
21200 if (!xmlStrEqual(attr->nsName, attrDecl->targetNamespace))
21201 continue;
21202 found = 1;
21203 /*
21204 * SPEC (cvc-complex-type)
21205 * (3.1) "If there is among the {attribute uses} an attribute
21206 * use with an {attribute declaration} whose {name} matches
21207 * the attribute information item's [local name] and whose
21208 * {target namespace} is identical to the attribute information
21209 * item's [namespace name] (where an ·absent· {target namespace}
21210 * is taken to be identical to a [namespace name] with no value),
21211 * then the attribute information must be ·valid· with respect
21212 * to that attribute use as per Attribute Locally Valid (Use)
21213 * (§3.5.4). In this case the {attribute declaration} of that
21214 * attribute use is the ·context-determined declaration· for the
21215 * attribute information item with respect to Schema-Validity
21216 * Assessment (Attribute) (§3.2.4) and
21217 * Assessment Outcome (Attribute) (§3.2.5).
21218 */
21219 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21220 attr->use = attrUse;
21221 /*
21222 * Context-determined declaration.
21223 */
21224 attr->decl = attrDecl;
21225 attr->typeDef = attrDecl->subtypes;
21226 break;
21227 }
21228
21229 if (found)
21230 continue;
21231
21232 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
21233 /*
21234 * Handle non-existent, required attributes.
21235 *
21236 * SPEC (cvc-complex-type)
21237 * (4) "The {attribute declaration} of each attribute use in
21238 * the {attribute uses} whose {required} is true matches one
21239 * of the attribute information items in the element information
21240 * item's [attributes] as per clause 3.1 above."
21241 */
21242 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21243 if (tmpAttr == NULL) {
21244 VERROR_INT(
21245 "xmlSchemaVAttributesComplex",
21246 "calling xmlSchemaGetFreshAttrInfo()");
21247 return (-1);
21248 }
21249 tmpAttr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
21250 tmpAttr->use = attrUse;
21251 tmpAttr->decl = attrDecl;
21252 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
21253 ((attrUse->defValue != NULL) ||
21254 (attrDecl->defValue != NULL))) {
21255 /*
21256 * Handle non-existent, optional, default/fixed attributes.
21257 */
21258 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21259 if (tmpAttr == NULL) {
21260 VERROR_INT(
21261 "xmlSchemaVAttributesComplex",
21262 "calling xmlSchemaGetFreshAttrInfo()");
21263 return (-1);
21264 }
21265 tmpAttr->state = XML_SCHEMAS_ATTR_DEFAULT;
21266 tmpAttr->use = attrUse;
21267 tmpAttr->decl = attrDecl;
21268 tmpAttr->typeDef = attrDecl->subtypes;
21269 tmpAttr->localName = attrDecl->name;
21270 tmpAttr->nsName = attrDecl->targetNamespace;
21271 }
21272 }
21273 if (vctxt->nbAttrInfos == 0)
21274 return (0);
21275 /*
21276 * Validate against the wildcard.
21277 */
21278 if (type->attributeWildcard != NULL) {
21279 /*
21280 * SPEC (cvc-complex-type)
21281 * (3.2.1) "There must be an {attribute wildcard}."
21282 */
21283 for (i = 0; i < nbAttrs; i++) {
21284 attr = vctxt->attrInfos[i];
21285 /*
21286 * SPEC (cvc-complex-type) (3)
21287 * Skip meta attributes.
21288 */
21289 if (attr->state != XML_SCHEMAS_ATTR_UNKNOWN)
21290 continue;
21291 /*
21292 * SPEC (cvc-complex-type)
21293 * (3.2.2) "The attribute information item must be ·valid· with
21294 * respect to it as defined in Item Valid (Wildcard) (§3.10.4)."
21295 *
21296 * SPEC Item Valid (Wildcard) (cvc-wildcard)
21297 * "... its [namespace name] must be ·valid· with respect to
21298 * the wildcard constraint, as defined in Wildcard allows
21299 * Namespace Name (§3.10.4)."
21300 */
21301 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
21302 attr->nsName)) {
21303 /*
21304 * Handle processContents.
21305 *
21306 * SPEC (cvc-wildcard):
21307 * processContents | context-determined declaration:
21308 * "strict" "mustFind"
21309 * "lax" "none"
21310 * "skip" "skip"
21311 */
21312 if (type->attributeWildcard->processContents ==
21313 XML_SCHEMAS_ANY_SKIP) {
21314 /*
21315 * context-determined declaration = "skip"
21316 *
21317 * SPEC PSVI Assessment Outcome (Attribute)
21318 * [validity] = "notKnown"
21319 * [validation attempted] = "none"
21320 */
21321 attr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
21322 continue;
21323 }
21324 /*
21325 * Find an attribute declaration.
21326 */
21327 attr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
21328 attr->localName, attr->nsName);
21329 if (attr->decl != NULL) {
21330 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21331 /*
21332 * SPEC (cvc-complex-type)
21333 * (5) "Let [Definition:] the wild IDs be the set of
21334 * all attribute information item to which clause 3.2
21335 * applied and whose ·validation· resulted in a
21336 * ·context-determined declaration· of mustFind or no
21337 * ·context-determined declaration· at all, and whose
21338 * [local name] and [namespace name] resolve (as
21339 * defined by QName resolution (Instance) (§3.15.4)) to
21340 * an attribute declaration whose {type definition} is
21341 * or is derived from ID. Then all of the following
21342 * must be true:"
21343 */
21344 attr->typeDef = attr->decl->subtypes;
21345 if (xmlSchemaIsDerivedFromBuiltInType(
21346 attr->typeDef, XML_SCHEMAS_ID)) {
21347 /*
21348 * SPEC (5.1) "There must be no more than one
21349 * item in ·wild IDs·."
21350 */
21351 if (wildIDs != 0) {
21352 /* VAL TODO */
21353 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
21354 TODO
21355 continue;
21356 }
21357 wildIDs++;
21358 /*
21359 * SPEC (cvc-complex-type)
21360 * (5.2) "If ·wild IDs· is non-empty, there must not
21361 * be any attribute uses among the {attribute uses}
21362 * whose {attribute declaration}'s {type definition}
21363 * is or is derived from ID."
21364 */
21365 for (attrUseLink = type->attributeUses;
21366 attrUseLink != NULL;
21367 attrUseLink = attrUseLink->next) {
21368 if (xmlSchemaIsDerivedFromBuiltInType(
21369 attrUseLink->attr->subtypes,
21370 XML_SCHEMAS_ID)) {
21371 /* VAL TODO */
21372 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
21373 TODO
21374 }
21375 }
21376 }
21377 } else if (type->attributeWildcard->processContents ==
21378 XML_SCHEMAS_ANY_LAX) {
21379 attr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
21380 /*
21381 * SPEC PSVI Assessment Outcome (Attribute)
21382 * [validity] = "notKnown"
21383 * [validation attempted] = "none"
21384 */
21385 } else {
21386 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
21387 }
21388 }
21389 }
21390 }
21391
21392
21393 if (vctxt->nbAttrInfos == 0)
21394 return (0);
21395
21396 /*
21397 * Validate values, create default attributes, evaluate IDCs.
21398 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021399 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21400 attr = vctxt->attrInfos[i];
21401 /*
21402 * VAL TODO: Note that we won't try to resolve IDCs to
21403 * "lax" and "skip" validated attributes. Check what to
21404 * do in this case.
21405 */
21406 if ((attr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
21407 (attr->state != XML_SCHEMAS_ATTR_DEFAULT))
21408 continue;
21409 /*
21410 * VAL TODO: What to do if the type definition is missing?
21411 */
21412 if (attr->typeDef == NULL) {
21413 attr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
21414 continue;
21415 }
21416
21417 ACTIVATE_ATTRIBUTE(attr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021418 fixed = 0;
21419 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021420
21421 if (vctxt->xpathStates != NULL) {
21422 /*
21423 * Evaluate IDCs.
21424 */
21425 xpathRes = xmlSchemaXPathEvaluate(vctxt,
21426 XML_ATTRIBUTE_NODE);
21427 if (xpathRes == -1) {
21428 VERROR_INT("xmlSchemaVAttributesComplex",
21429 "calling xmlSchemaXPathEvaluate()");
21430 goto internal_error;
21431 }
21432 }
21433
21434 if (attr->state == XML_SCHEMAS_ATTR_DEFAULT) {
21435 /*
21436 * Default/fixed attributes.
21437 */
21438 if (xpathRes) {
21439 if (attr->use->defValue == NULL) {
21440 attr->value = (xmlChar *) attr->use->defValue;
21441 attr->val = attr->use->defVal;
21442 } else {
21443 attr->value = (xmlChar *) attr->decl->defValue;
21444 attr->val = attr->decl->defVal;
21445 }
21446 /*
21447 * IDCs will consume the precomputed default value,
21448 * so we need to clone it.
21449 */
21450 if (attr->val == NULL) {
21451 VERROR_INT("xmlSchemaVAttributesComplex",
21452 "default/fixed value on an attribute use was "
21453 "not precomputed");
21454 goto internal_error;
21455 }
21456 attr->val = xmlSchemaCopyValue(attr->val);
21457 if (attr->val == NULL) {
21458 VERROR_INT("xmlSchemaVAttributesComplex",
21459 "calling xmlSchemaCopyValue()");
21460 goto internal_error;
21461 }
21462 }
21463 /*
21464 * PSVI: Add the default attribute to the current element.
21465 * VAL TODO: Should we use the *normalized* value? This currently
21466 * uses the *initial* value.
21467 */
21468 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
21469 (attr->node != NULL) && (attr->node->doc != NULL)) {
21470 xmlChar *normValue;
21471 const xmlChar *value;
21472
21473 value = attr->value;
21474 /*
21475 * Normalize the value.
21476 */
21477 normValue = xmlSchemaNormalizeValue(attr->typeDef,
21478 attr->value);
21479 if (normValue != NULL)
21480 value = BAD_CAST normValue;
21481
21482 if (attr->nsName == NULL) {
21483 if (xmlNewProp(attr->node->parent,
21484 attr->localName, value) == NULL) {
21485 VERROR_INT("xmlSchemaVAttributesComplex",
21486 "callling xmlNewProp()");
21487 if (normValue != NULL)
21488 xmlFree(normValue);
21489 goto internal_error;
21490 }
21491 } else {
21492 xmlNsPtr ns;
21493
21494 ns = xmlSearchNsByHref(attr->node->doc,
21495 attr->node->parent, attr->nsName);
21496 if (ns == NULL) {
21497 xmlChar prefix[12];
21498 int counter = 0;
21499
21500 /*
21501 * Create a namespace declaration on the validation
21502 * root node if no namespace declaration is in scope.
21503 */
21504 do {
21505 snprintf((char *) prefix, 12, "p%d", counter++);
21506 ns = xmlSearchNs(attr->node->doc,
21507 attr->node->parent, BAD_CAST prefix);
21508 if (counter > 1000) {
21509 VERROR_INT(
21510 "xmlSchemaVAttributesComplex",
21511 "could not compute a ns prefix for a "
21512 "default/fixed attribute");
21513 if (normValue != NULL)
21514 xmlFree(normValue);
21515 goto internal_error;
21516 }
21517 } while (ns != NULL);
21518 ns = xmlNewNs(vctxt->validationRoot,
21519 attr->nsName, BAD_CAST prefix);
21520 }
21521 xmlNewNsProp(attr->node->parent, ns,
21522 attr->localName, value);
21523 }
21524 if (normValue != NULL)
21525 xmlFree(normValue);
21526 }
21527 /*
21528 * Go directly to IDC evaluation.
21529 */
21530 goto eval_idcs;
21531 }
21532 /*
21533 * Validate the value.
21534 */
21535 if (vctxt->value != NULL) {
21536 /*
21537 * Free last computed value; just for safety reasons.
21538 */
21539 xmlSchemaFreeValue(vctxt->value);
21540 vctxt->value = NULL;
21541 }
21542 /*
21543 * Note that the attribute *use* can be unavailable, if
21544 * the attribute was a wild attribute.
21545 */
21546 if ((attr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
21547 ((attr->use != NULL) &&
21548 (attr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
21549 fixed = 1;
21550 else
21551 fixed = 0;
21552 /*
21553 * SPEC (cvc-attribute)
21554 * (3) "The item's ·normalized value· must be locally ·valid·
21555 * with respect to that {type definition} as per
21556 * String Valid (§3.14.4)."
21557 *
21558 * VAL TODO: Do we already have the
21559 * "normalized attribute value" here?
21560 */
21561 if (xpathRes || fixed) {
21562 attr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
21563 /*
21564 * Request a computed value.
21565 */
21566 res = xmlSchemaVCheckCVCSimpleType(
21567 (xmlSchemaAbstractCtxtPtr) vctxt,
21568 attr->node, attr->typeDef, attr->value, &(attr->val),
21569 1, 1, 0);
21570 } else {
21571 res = xmlSchemaVCheckCVCSimpleType(
21572 (xmlSchemaAbstractCtxtPtr) vctxt,
21573 attr->node, attr->typeDef, attr->value, NULL,
21574 1, 0, 0);
21575 }
21576
21577 if (res != 0) {
21578 if (res == -1) {
21579 VERROR_INT("xmlSchemaVAttributesComplex",
21580 "calling xmlSchemaStreamValidateSimpleTypeValue()");
21581 goto internal_error;
21582 }
21583 attr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
21584 /*
21585 * SPEC PSVI Assessment Outcome (Attribute)
21586 * [validity] = "invalid"
21587 */
21588 goto eval_idcs;
21589 }
21590
21591 if (fixed) {
21592 int ws;
21593 /*
21594 * SPEC Attribute Locally Valid (Use) (cvc-au)
21595 * "For an attribute information item to be·valid·
21596 * with respect to an attribute use its *normalized*
21597 * value· must match the *canonical* lexical
21598 * representation of the attribute use's {value
21599 * constraint}value, if it is present and fixed."
21600 *
21601 * VAL TODO: The requirement for the *canonical* value
21602 * will be removed in XML Schema 1.1.
21603 */
21604 /*
21605 * SPEC Attribute Locally Valid (cvc-attribute)
21606 * (4) "The item's *actual* value· must match the *value* of
21607 * the {value constraint}, if it is present and fixed."
21608 */
21609 ws = xmlSchemaGetWhiteSpaceFacetValue(attr->typeDef);
21610 if (attr->val == NULL) {
21611 /* VAL TODO: A value was not precomputed. */
21612 TODO
21613 goto eval_idcs;
21614 }
21615 if ((attr->use != NULL) &&
21616 (attr->use->defValue != NULL)) {
21617 if (attr->use->defVal == NULL) {
21618 /* VAL TODO: A default value was not precomputed. */
21619 TODO
21620 goto eval_idcs;
21621 }
21622 attr->vcValue = attr->use->defValue;
21623 /*
21624 if (xmlSchemaCompareValuesWhtsp(attr->val,
21625 (xmlSchemaWhitespaceValueType) ws,
21626 attr->use->defVal,
21627 (xmlSchemaWhitespaceValueType) ws) != 0) {
21628 */
21629 if (! xmlSchemaAreValuesEqual(attr->val, attr->use->defVal))
21630 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21631 } else {
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021632 if (attr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021633 /* VAL TODO: A default value was not precomputed. */
21634 TODO
21635 goto eval_idcs;
21636 }
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021637 attr->vcValue = attr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021638 /*
21639 if (xmlSchemaCompareValuesWhtsp(attr->val,
21640 (xmlSchemaWhitespaceValueType) ws,
21641 attrDecl->defVal,
21642 (xmlSchemaWhitespaceValueType) ws) != 0) {
21643 */
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021644 if (! xmlSchemaAreValuesEqual(attr->val, attr->decl->defVal))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021645 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21646 }
21647 /*
21648 * [validity] = "valid"
21649 */
21650 }
21651eval_idcs:
21652 /*
21653 * Evaluate IDCs.
21654 */
21655 if (xpathRes) {
21656 if (xmlSchemaXPathProcessHistory(vctxt,
21657 vctxt->depth +1) == -1) {
21658 VERROR_INT("xmlSchemaVAttributesComplex",
21659 "calling xmlSchemaXPathEvaluate()");
21660 goto internal_error;
21661 }
21662 }
21663 }
21664
21665 /*
21666 * Report errors.
21667 */
21668 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21669 attr = vctxt->attrInfos[i];
21670 if ((attr->state == XML_SCHEMAS_ATTR_META) ||
21671 (attr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
21672 (attr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
21673 (attr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
21674 continue;
21675 ACTIVATE_ATTRIBUTE(attr);
21676 switch (attr->state) {
21677 case XML_SCHEMAS_ATTR_ERR_MISSING: {
21678 xmlChar *str = NULL;
21679 ACTIVATE_ELEM;
21680 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21681 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
21682 "The attribute '%s' is required but missing",
21683 xmlSchemaFormatQName(&str,
21684 attr->decl->targetNamespace,
21685 attr->decl->name),
21686 NULL);
21687 FREE_AND_NULL(str)
21688 break;
21689 }
21690 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
21691 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
21692 "The type definition is absent");
21693 break;
21694 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
21695 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21696 XML_SCHEMAV_CVC_AU, NULL, NULL,
21697 "The value '%s' does not match the fixed "
21698 "value constraint '%s'",
21699 attr->value, attr->vcValue);
21700 break;
21701 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
21702 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
21703 "No matching global attribute declaration available, but "
21704 "demanded by the strict wildcard");
21705 break;
21706 case XML_SCHEMAS_ATTR_UNKNOWN:
21707 if (attr->metaType)
21708 break;
21709 /*
21710 * MAYBE VAL TODO: One might report different error messages
21711 * for the following errors.
21712 */
21713 if (type->attributeWildcard == NULL) {
21714 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21715 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr, NULL);
21716 } else {
21717 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21718 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr, NULL);
21719 }
21720 break;
21721 default:
21722 break;
21723 }
21724 }
21725
21726 ACTIVATE_ELEM;
21727 return (0);
21728internal_error:
21729 ACTIVATE_ELEM;
21730 return (-1);
21731}
21732
21733static int
21734xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
21735 int *skip)
21736{
21737 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
21738 /*
21739 * The namespace of the element was already identified to be
21740 * matching the wildcard.
21741 */
21742 if ((skip == NULL) || (wild == NULL) ||
21743 (wild->type != XML_SCHEMA_TYPE_ANY)) {
21744 VERROR_INT("xmlSchemaValidateElemWildcard",
21745 "bad arguments");
21746 return (-1);
21747 }
21748 *skip = 0;
21749 if (wild->negNsSet != NULL) {
21750 /*
21751 * URGENT VAL TODO: Fix the content model to reject
21752 * "##other" wildcards.
21753 */
21754 if (xmlSchemaCheckCVCWildcardNamespace(wild,
21755 vctxt->inode->nsName) != 0) {
21756 if ((wild->minOccurs == 1) && (wild->maxOccurs == 1)) {
21757 xmlSchemaNodeInfoPtr pinode = vctxt->elemInfos[vctxt->depth -1];
21758 /*
21759 * VAL TODO: Workaround possible *only* if minOccurs and
21760 * maxOccurs are 1.
21761 */
21762 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
21763 /* VAL TODO: error code? */
21764 XML_SCHEMAV_ELEMENT_CONTENT, NULL,
21765 (xmlSchemaTypePtr) wild,
21766 "This element is not accepted by the wildcard",
21767 0, 0, NULL);
21768 vctxt->skipDepth = vctxt->depth;
21769 if ((pinode->flags &
21770 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0)
21771 pinode->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
21772 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
21773 return (XML_SCHEMAV_ELEMENT_CONTENT);
21774 }
21775 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
21776 *skip = 1;
21777 return (0);
21778 }
21779 vctxt->inode->typeDef =
21780 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
21781 return (0);
21782 }
21783 }
21784 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
21785 /*
21786 * URGENT VAL TODO: Either we need to position the stream to the
21787 * next sibling, or walk the whole subtree.
21788 */
21789 *skip = 1;
21790 return (0);
21791 }
21792 {
21793 xmlSchemaElementPtr decl = NULL;
21794
21795 decl = xmlHashLookup3(vctxt->schema->elemDecl,
21796 vctxt->inode->localName, vctxt->inode->nsName,
21797 NULL);
21798 if (decl != NULL) {
21799 vctxt->inode->decl = decl;
21800 return (0);
21801 }
21802 }
21803 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
21804 /* VAL TODO: Change to proper error code. */
21805 VERROR(XML_SCHEMAV_CVC_ELT_1, (xmlSchemaTypePtr) wild,
21806 "No matching global element declaration available, but "
21807 "demanded by the strict wildcard");
21808 return (vctxt->err);
21809 }
21810 if (vctxt->nbAttrInfos != 0) {
21811 xmlSchemaAttrInfoPtr iattr;
21812 /*
21813 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21814 * (1.2.1.2.1) - (1.2.1.2.3 )
21815 *
21816 * Use the xsi:type attribute for the type definition.
21817 */
21818 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21819 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21820 if (iattr != NULL) {
21821 if (xmlSchemaProcessXSIType(vctxt, iattr,
21822 &(vctxt->inode->typeDef), NULL) == -1) {
21823 VERROR_INT("xmlSchemaValidateElemWildcard",
21824 "calling xmlSchemaProcessXSIType() to "
21825 "process the attribute 'xsi:nil'");
21826 return (-1);
21827 }
21828 /*
21829 * Don't return an error on purpose.
21830 */
21831 return (0);
21832 }
21833 }
21834 /*
21835 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21836 *
21837 * Fallback to "anyType".
21838 */
21839 vctxt->inode->typeDef =
21840 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
21841 return (0);
21842}
21843
21844/*
21845* xmlSchemaCheckCOSValidDefault:
21846*
21847* This will be called if: not nilled, no content and a default/fixed
21848* value is provided.
21849*/
21850
21851static int
21852xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
21853 const xmlChar *value,
21854 xmlSchemaValPtr *val)
21855{
21856 int ret = 0;
21857 xmlSchemaNodeInfoPtr inode = vctxt->inode;
21858
21859 /*
21860 * cos-valid-default:
21861 * Schema Component Constraint: Element Default Valid (Immediate)
21862 * For a string to be a valid default with respect to a type
21863 * definition the appropriate case among the following must be true:
21864 */
21865 if IS_COMPLEX_TYPE(inode->typeDef) {
21866 /*
21867 * Complex type.
21868 *
21869 * SPEC (2.1) "its {content type} must be a simple type definition
21870 * or mixed."
21871 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
21872 * type}'s particle must be ·emptiable· as defined by
21873 * Particle Emptiable (§3.9.6)."
21874 */
21875 if ((! HAS_SIMPLE_CONTENT(inode->typeDef)) &&
21876 ((! HAS_MIXED_CONTENT(inode->typeDef)) ||
21877 (! IS_PARTICLE_EMPTIABLE(inode->typeDef)))) {
21878 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
21879 /* NOTE that this covers (2.2.2) as well. */
21880 VERROR(ret, NULL,
21881 "For a string to be a valid default, the type definition "
21882 "must be a simple type or a complex type with simple content "
21883 "or mixed content and a particle emptiable");
21884 return(ret);
21885 }
21886 }
21887 /*
21888 * 1 If the type definition is a simple type definition, then the string
21889 * must be ·valid· with respect to that definition as defined by String
21890 * Valid (§3.14.4).
21891 *
21892 * AND
21893 *
21894 * 2.2.1 If the {content type} is a simple type definition, then the
21895 * string must be ·valid· with respect to that simple type definition
21896 * as defined by String Valid (§3.14.4).
21897 */
21898 if (IS_SIMPLE_TYPE(inode->typeDef)) {
21899
21900 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
21901 NULL, inode->typeDef, value, val, 1, 1, 0);
21902
21903 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
21904
21905 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
21906 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
21907 }
21908 if (ret < 0) {
21909 VERROR_INT("xmlSchemaCheckCOSValidDefault",
21910 "calling xmlSchemaVCheckCVCSimpleType()");
21911 }
21912 return (ret);
21913}
21914
21915static void
21916xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
21917 const xmlChar * name ATTRIBUTE_UNUSED,
21918 xmlSchemaElementPtr item,
21919 xmlSchemaNodeInfoPtr inode)
21920{
21921 inode->decl = item;
21922#ifdef DEBUG_CONTENT
21923 {
21924 xmlChar *str = NULL;
21925
21926 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
21927 xmlGenericError(xmlGenericErrorContext,
21928 "AUTOMATON callback for '%s' [declaration]\n",
21929 xmlSchemaFormatQName(&str,
21930 inode->localName, inode->nsName));
21931 } else {
21932 xmlGenericError(xmlGenericErrorContext,
21933 "AUTOMATON callback for '%s' [wildcard]\n",
21934 xmlSchemaFormatQName(&str,
21935 inode->localName, inode->nsName));
21936
21937 }
21938 FREE_AND_NULL(str)
21939 }
21940#endif
21941}
21942
21943static int
21944xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
21945{
21946 vctxt->depth++;
21947 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
21948 if (vctxt->inode == NULL) {
21949 VERROR_INT("xmlSchemaValidatorPushElem",
21950 "calling xmlSchemaGetFreshElemInfo()");
21951 return (-1);
21952 }
21953 vctxt->nbAttrInfos = 0;
21954 return (0);
21955}
21956
21957static int
21958xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
21959 xmlSchemaNodeInfoPtr inode,
21960 xmlSchemaTypePtr type,
21961 const xmlChar *value)
21962{
21963 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
21964 return (xmlSchemaVCheckCVCSimpleType(
21965 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
21966 type, value, &(inode->val), 1, 1, 0));
21967 else
21968 return (xmlSchemaVCheckCVCSimpleType(
21969 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
21970 type, value, NULL, 1, 0, 0));
21971}
21972
21973
21974
21975/*
21976* Process END of element.
21977*/
21978static int
21979xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
21980{
21981 int ret = 0;
21982 xmlSchemaNodeInfoPtr inode = vctxt->inode;
21983
21984 if (vctxt->nbAttrInfos != 0)
21985 xmlSchemaClearAttrInfos(vctxt);
21986 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
21987 /*
21988 * This element was not expected;
21989 * we will not validate child elements of broken parents.
21990 * Skip validation of all content of the parent.
21991 */
21992 vctxt->skipDepth = vctxt->depth -1;
21993 goto end_elem;
21994 }
21995 if ((inode->typeDef == NULL) ||
21996 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
21997 /*
21998 * The type definition might be missing if the element was
21999 * error prone.
22000 */
22001 goto end_elem;
22002 }
22003 /*
22004 * Check the content model.
22005 */
22006 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
22007 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
22008
22009 /*
22010 * Workaround for "anyType".
22011 */
22012 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
22013 goto character_content;
22014
22015 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
22016 xmlChar *values[10];
22017 int terminal, nbval = 10, nbneg;
22018
22019 if (inode->regexCtxt == NULL) {
22020 /*
22021 * Create the regex context.
22022 */
22023 inode->regexCtxt =
22024 xmlRegNewExecCtxt(inode->typeDef->contModel,
22025 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22026 vctxt);
22027 if (inode->regexCtxt == NULL) {
22028 VERROR_INT("xmlSchemaValidatorPopElem",
22029 "failed to create a regex context");
22030 goto internal_error;
22031 }
22032#ifdef DEBUG_AUTOMATA
22033 xmlGenericError(xmlGenericErrorContext,
22034 "AUTOMATON create on '%s'\n", inode->localName);
22035#endif
22036 }
22037 /*
22038 * Get hold of the still expected content, since a further
22039 * call to xmlRegExecPushString() will loose this information.
22040 */
22041 xmlRegExecNextValues(inode->regexCtxt,
22042 &nbval, &nbneg, &values[0], &terminal);
22043 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
22044 if (ret <= 0) {
22045 /*
22046 * Still missing something.
22047 */
22048 ret = 1;
22049 inode->flags |=
22050 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22051 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22052 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
22053 "Missing child element(s)",
22054 nbval, nbneg, values);
22055#ifdef DEBUG_AUTOMATA
22056 xmlGenericError(xmlGenericErrorContext,
22057 "AUTOMATON missing ERROR on '%s'\n",
22058 inode->localName);
22059#endif
22060 } else {
22061 /*
22062 * Content model is satisfied.
22063 */
22064 ret = 0;
22065#ifdef DEBUG_AUTOMATA
22066 xmlGenericError(xmlGenericErrorContext,
22067 "AUTOMATON succeeded on '%s'\n",
22068 inode->localName);
22069#endif
22070 }
22071
22072 }
22073 }
22074 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
22075 goto end_elem;
22076
22077character_content:
22078
22079 if (vctxt->value != NULL) {
22080 xmlSchemaFreeValue(vctxt->value);
22081 vctxt->value = NULL;
22082 }
22083 /*
22084 * Check character content.
22085 */
22086 if (inode->decl == NULL) {
22087 /*
22088 * Speedup if no declaration exists.
22089 */
22090 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22091 ret = xmlSchemaVCheckINodeDataType(vctxt,
22092 inode, inode->typeDef, inode->value);
22093 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22094 ret = xmlSchemaVCheckINodeDataType(vctxt,
22095 inode, inode->typeDef->contentTypeDef,
22096 inode->value);
22097 }
22098 if (ret < 0) {
22099 VERROR_INT("xmlSchemaValidatorPopElem",
22100 "calling xmlSchemaVCheckCVCSimpleType()");
22101 goto internal_error;
22102 }
22103 goto end_elem;
22104 }
22105 /*
22106 * cvc-elt (3.3.4) : 5
22107 * The appropriate case among the following must be true:
22108 */
22109 /*
22110 * cvc-elt (3.3.4) : 5.1
22111 * If the declaration has a {value constraint},
22112 * the item has neither element nor character [children] and
22113 * clause 3.2 has not applied, then all of the following must be true:
22114 */
22115 if ((inode->decl->value != NULL) &&
22116 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
22117 (! INODE_NILLED(inode))) {
22118 /*
22119 * cvc-elt (3.3.4) : 5.1.1
22120 * If the ·actual type definition· is a ·local type definition·
22121 * then the canonical lexical representation of the {value constraint}
22122 * value must be a valid default for the ·actual type definition· as
22123 * defined in Element Default Valid (Immediate) (§3.3.6).
22124 */
22125 /*
22126 * NOTE: 'local' above means types aquired by xsi:type.
22127 * NOTE: Although the *canonical* value is stated, it is not
22128 * relevant if canonical or not. Additionally XML Schema 1.1
22129 * will removed this requirement as well.
22130 */
22131 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
22132
22133 ret = xmlSchemaCheckCOSValidDefault(vctxt,
22134 inode->decl->value, &(inode->val));
22135 if (ret != 0) {
22136 if (ret < 0) {
22137 VERROR_INT("xmlSchemaValidatorPopElem",
22138 "calling xmlSchemaCheckCOSValidDefault()");
22139 goto internal_error;
22140 }
22141 goto end_elem;
22142 }
22143 /*
22144 * Stop here, to avoid redundant validation of the value
22145 * (see following).
22146 */
22147 goto default_psvi;
22148 }
22149 /*
22150 * cvc-elt (3.3.4) : 5.1.2
22151 * The element information item with the canonical lexical
22152 * representation of the {value constraint} value used as its
22153 * ·normalized value· must be ·valid· with respect to the
22154 * ·actual type definition· as defined by Element Locally Valid (Type)
22155 * (§3.3.4).
22156 */
22157 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22158 ret = xmlSchemaVCheckINodeDataType(vctxt,
22159 inode, inode->typeDef, inode->decl->value);
22160 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22161 ret = xmlSchemaVCheckINodeDataType(vctxt,
22162 inode, inode->typeDef->contentTypeDef,
22163 inode->decl->value);
22164 }
22165 if (ret != 0) {
22166 if (ret < 0) {
22167 VERROR_INT("xmlSchemaValidatorPopElem",
22168 "calling xmlSchemaVCheckCVCSimpleType()");
22169 goto internal_error;
22170 }
22171 goto end_elem;
22172 }
22173
22174default_psvi:
22175 /*
22176 * PSVI: Create a text node on the instance element.
22177 */
22178 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
22179 (inode->node != NULL)) {
22180 xmlNodePtr textChild;
22181 xmlChar *normValue;
22182 /*
22183 * VAL TODO: Normalize the value.
22184 */
22185 normValue = xmlSchemaNormalizeValue(inode->typeDef,
22186 inode->decl->value);
22187 if (normValue != NULL) {
22188 textChild = xmlNewText(BAD_CAST normValue);
22189 xmlFree(normValue);
22190 } else
22191 textChild = xmlNewText(inode->decl->value);
22192 if (textChild == NULL) {
22193 VERROR_INT("xmlSchemaValidatorPopElem",
22194 "calling xmlNewText()");
22195 goto internal_error;
22196 } else
22197 xmlAddChild(inode->node, textChild);
22198 }
22199
22200 } else if (! INODE_NILLED(inode)) {
22201 /*
22202 * 5.2.1 The element information item must be ·valid· with respect
22203 * to the ·actual type definition· as defined by Element Locally
22204 * Valid (Type) (§3.3.4).
22205 */
22206 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22207 /*
22208 * SPEC (cvc-type) (3.1)
22209 * "If the type definition is a simple type definition, ..."
22210 * (3.1.3) "If clause 3.2 of Element Locally Valid
22211 * (Element) (§3.3.4) did not apply, then the ·normalized value·
22212 * must be ·valid· with respect to the type definition as defined
22213 * by String Valid (§3.14.4).
22214 */
22215 ret = xmlSchemaVCheckINodeDataType(vctxt,
22216 inode, inode->typeDef, inode->value);
22217 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22218 /*
22219 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
22220 * definition, then the element information item must be
22221 * ·valid· with respect to the type definition as per
22222 * Element Locally Valid (Complex Type) (§3.4.4);"
22223 *
22224 * SPEC (cvc-complex-type) (2.2)
22225 * "If the {content type} is a simple type definition, ...
22226 * the ·normalized value· of the element information item is
22227 * ·valid· with respect to that simple type definition as
22228 * defined by String Valid (§3.14.4)."
22229 */
22230 ret = xmlSchemaVCheckINodeDataType(vctxt,
22231 inode, inode->typeDef->contentTypeDef, inode->value);
22232 }
22233 if (ret != 0) {
22234 if (ret < 0) {
22235 VERROR_INT("xmlSchemaValidatorPopElem",
22236 "calling xmlSchemaVCheckCVCSimpleType()");
22237 goto internal_error;
22238 }
22239 goto end_elem;
22240 }
22241 /*
22242 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
22243 * not applied, all of the following must be true:
22244 */
22245 if ((inode->decl->value != NULL) &&
22246 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
22247
22248 /*
22249 * TODO: We will need a computed value, when comparison is
22250 * done on computed values.
22251 */
22252 /*
22253 * 5.2.2.1 The element information item must have no element
22254 * information item [children].
22255 */
22256 if (inode->flags &
22257 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
22258 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
22259 VERROR(ret, NULL,
22260 "The content must not containt element nodes since "
22261 "there is a fixed value constraint");
22262 goto end_elem;
22263 } else {
22264 /*
22265 * 5.2.2.2 The appropriate case among the following must
22266 * be true:
22267 */
22268 if (HAS_MIXED_CONTENT(inode->typeDef)) {
22269 /*
22270 * 5.2.2.2.1 If the {content type} of the ·actual type
22271 * definition· is mixed, then the *initial value* of the
22272 * item must match the canonical lexical representation
22273 * of the {value constraint} value.
22274 *
22275 * ... the *initial value* of an element information
22276 * item is the string composed of, in order, the
22277 * [character code] of each character information item in
22278 * the [children] of that element information item.
22279 */
22280 if (! xmlStrEqual(inode->value, inode->decl->value)){
22281 /*
22282 * VAL TODO: Report invalid & expected values as well.
22283 * VAL TODO: Implement the canonical stuff.
22284 */
22285 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
22286 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22287 ret, NULL, NULL,
22288 "The initial value '%s' does not match the fixed "
22289 "value constraint '%s'",
22290 inode->value, inode->decl->value);
22291 goto end_elem;
22292 }
22293 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22294 /*
22295 * 5.2.2.2.2 If the {content type} of the ·actual type
22296 * definition· is a simple type definition, then the
22297 * *actual value* of the item must match the canonical
22298 * lexical representation of the {value constraint} value.
22299 */
22300 /*
22301 * VAL TODO: *actual value* is the normalized value, impl.
22302 * this.
22303 * VAL TODO: Report invalid & expected values as well.
22304 * VAL TODO: Implement a comparison with the computed values.
22305 */
22306 if (! xmlStrEqual(inode->value,
22307 inode->decl->value)) {
22308 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
22309 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22310 ret, NULL, NULL,
22311 "The actual value '%s' does not match the fixed "
22312 "value constraint '%s'",
22313 inode->value,
22314 inode->decl->value);
22315 goto end_elem;
22316 }
22317 }
22318 }
22319 }
22320 }
22321
22322end_elem:
22323 if (vctxt->depth < 0) {
22324 /* TODO: raise error? */
22325 return (0);
22326 }
22327 if (vctxt->depth == vctxt->skipDepth)
22328 vctxt->skipDepth = -1;
22329 /*
22330 * Evaluate the history of XPath state objects.
22331 */
22332 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
22333 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022334 /*
22335 * TODO: 6 The element information item must be ·valid· with respect to each of
22336 * the {identity-constraint definitions} as per Identity-constraint
22337 * Satisfied (§3.11.4).
22338 */
22339 /*
22340 * Validate IDC keyrefs.
22341 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022342 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
22343 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022344 /*
22345 * Merge/free the IDC table.
22346 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022347 if (inode->idcTable != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022348#ifdef DEBUG_IDC
22349 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022350 inode->nsName,
22351 inode->localName,
22352 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022353#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022354 if (vctxt->depth > 0) {
22355 /*
22356 * Merge the IDC node table with the table of the parent node.
22357 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022358 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
22359 goto internal_error;
22360 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022361 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022362 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022363 * Clear the current ielem.
22364 * VAL TODO: Don't free the PSVI IDC tables if they are
22365 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022366 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022367 xmlSchemaClearElemInfo(inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022368 /*
22369 * Skip further processing if we are on the validation root.
22370 */
22371 if (vctxt->depth == 0) {
22372 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022373 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022374 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022375 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022376 /*
22377 * Reset the bubbleDepth if needed.
22378 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022379 if (vctxt->aidcs != NULL) {
22380 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
22381 do {
22382 if (aidc->bubbleDepth == vctxt->depth) {
22383 /*
22384 * A bubbleDepth of a key/unique IDC matches the current
22385 * depth, this means that we are leaving the scope of the
22386 * top-most keyref IDC.
22387 */
22388 aidc->bubbleDepth = -1;
22389 }
22390 aidc = aidc->next;
22391 } while (aidc != NULL);
22392 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022393 vctxt->depth--;
22394 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022395 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022396 * VAL TODO: 7 If the element information item is the ·validation root·, it must be
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022397 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
22398 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022399 return (ret);
22400
22401internal_error:
22402 vctxt->err = -1;
22403 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022404}
22405
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022406/*
22407* 3.4.4 Complex Type Definition Validation Rules
22408* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
22409*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000022410static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022411xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000022412{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022413 xmlSchemaNodeInfoPtr pielem;
22414 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022415 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000022416
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022417 if (vctxt->depth <= 0) {
22418 VERROR_INT("xmlSchemaValidateChildElem",
22419 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022420 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022421 }
22422 pielem = vctxt->elemInfos[vctxt->depth -1];
22423 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
22424 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022425 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022426 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022427 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022428 if (INODE_NILLED(pielem)) {
22429 /*
22430 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
22431 */
22432 ACTIVATE_PARENT_ELEM;
22433 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
22434 VERROR(ret, NULL,
22435 "Neither character nor element content is allowed, "
22436 "because the element was 'nilled'");
22437 ACTIVATE_ELEM;
22438 goto unexpected_elem;
22439 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022440
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022441 ptype = pielem->typeDef;
22442
22443 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
22444 /*
22445 * Workaround for "anyType": we have currently no content model
22446 * assigned for "anyType", so handle it explicitely.
22447 * "anyType" has an unbounded, lax "any" wildcard.
22448 */
22449 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22450 vctxt->inode->localName,
22451 vctxt->inode->nsName);
22452
22453 if (vctxt->inode->decl == NULL) {
22454 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022455 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022456 * Process "xsi:type".
22457 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022458 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022459 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
22460 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
22461 if (iattr != NULL) {
22462 ret = xmlSchemaProcessXSIType(vctxt, iattr,
22463 &(vctxt->inode->typeDef), NULL);
22464 if (ret != 0) {
22465 if (ret == -1) {
22466 VERROR_INT("xmlSchemaValidateChildElem",
22467 "calling xmlSchemaProcessXSIType() to "
22468 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022469 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000022470 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022471 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000022472 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022473 } else {
22474 /*
22475 * Fallback to "anyType".
22476 *
22477 * SPEC (cvc-assess-elt)
22478 * "If the item cannot be ·strictly assessed·, [...]
22479 * an element information item's schema validity may be laxly
22480 * assessed if its ·context-determined declaration· is not
22481 * skip by ·validating· with respect to the ·ur-type
22482 * definition· as per Element Locally Valid (Type) (§3.3.4)."
22483 */
22484 vctxt->inode->typeDef =
22485 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022486 }
22487 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022488 return (0);
22489 }
22490
22491 switch (ptype->contentType) {
22492 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022493 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022494 * SPEC (2.1) "If the {content type} is empty, then the
22495 * element information item has no character or element
22496 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022497 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022498 ACTIVATE_PARENT_ELEM
22499 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
22500 VERROR(ret, NULL,
22501 "Element content is not allowed, "
22502 "because the content type is empty");
22503 ACTIVATE_ELEM
22504 goto unexpected_elem;
22505 break;
22506
22507 case XML_SCHEMA_CONTENT_MIXED:
22508 case XML_SCHEMA_CONTENT_ELEMENTS: {
22509 xmlRegExecCtxtPtr regexCtxt;
22510 xmlChar *values[10];
22511 int terminal, nbval = 10, nbneg;
22512
22513 /* VAL TODO: Optimized "anyType" validation.*/
22514
22515 if (ptype->contModel == NULL) {
22516 VERROR_INT("xmlSchemaValidateChildElem",
22517 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022518 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022519 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022520 /*
22521 * Safety belf for evaluation if the cont. model was already
22522 * examined to be invalid.
22523 */
22524 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
22525 VERROR_INT("xmlSchemaValidateChildElem",
22526 "validating elem, but elem content is already invalid");
22527 return (-1);
22528 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022529
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022530 regexCtxt = pielem->regexCtxt;
22531 if (regexCtxt == NULL) {
22532 /*
22533 * Create the regex context.
22534 */
22535 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
22536 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22537 vctxt);
22538 if (regexCtxt == NULL) {
22539 VERROR_INT("xmlSchemaValidateChildElem",
22540 "failed to create a regex context");
22541 return (-1);
22542 }
22543 pielem->regexCtxt = regexCtxt;
22544#ifdef DEBUG_AUTOMATA
22545 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
22546 pielem->localName);
22547#endif
22548 }
22549
22550 /*
22551 * SPEC (2.4) "If the {content type} is element-only or mixed,
22552 * then the sequence of the element information item's
22553 * element information item [children], if any, taken in
22554 * order, is ·valid· with respect to the {content type}'s
22555 * particle, as defined in Element Sequence Locally Valid
22556 * (Particle) (§3.9.4)."
22557 */
22558 ret = xmlRegExecPushString2(regexCtxt,
22559 vctxt->inode->localName,
22560 vctxt->inode->nsName,
22561 vctxt->inode);
22562#ifdef DEBUG_AUTOMATA
22563 if (ret < 0)
22564 xmlGenericError(xmlGenericErrorContext,
22565 "AUTOMATON push ERROR for '%s' on '%s'\n",
22566 vctxt->inode->localName, pielem->localName);
22567 else
22568 xmlGenericError(xmlGenericErrorContext,
22569 "AUTOMATON push OK for '%s' on '%s'\n",
22570 vctxt->inode->localName, pielem->localName);
22571#endif
22572 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
22573 VERROR_INT("xmlSchemaValidateChildElem",
22574 "calling xmlRegExecPushString2()");
22575 return (-1);
22576 }
22577 if (ret < 0) {
22578 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
22579 &values[0], &terminal);
22580 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22581 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
22582 "This element is not expected",
22583 nbval, nbneg, values);
22584 ret = vctxt->err;
22585 goto unexpected_elem;
22586 } else
22587 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022588 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022589 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022590 case XML_SCHEMA_CONTENT_SIMPLE:
22591 case XML_SCHEMA_CONTENT_BASIC:
22592 ACTIVATE_PARENT_ELEM
22593 if (IS_COMPLEX_TYPE(ptype)) {
22594 /*
22595 * SPEC (cvc-complex-type) (2.2)
22596 * "If the {content type} is a simple type definition, then
22597 * the element information item has no element information
22598 * item [children], ..."
22599 */
22600 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
22601 VERROR(ret, NULL, "Element content is not allowed, "
22602 "because the content type is a simple type definition");
22603 } else {
22604 /*
22605 * SPEC (cvc-type) (3.1.2) "The element information item must
22606 * have no element information item [children]."
22607 */
22608 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
22609 VERROR(ret, NULL, "Element content is not allowed, "
22610 "because the type definition is simple");
22611 }
22612 ACTIVATE_ELEM
22613 ret = vctxt->err;
22614 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022615 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022616
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022617 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022618 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022619 }
22620 return (ret);
22621unexpected_elem:
22622 /*
22623 * Pop this element and set the skipDepth to skip
22624 * all further content of the parent element.
22625 */
22626 vctxt->skipDepth = vctxt->depth;
22627 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
22628 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22629 return (ret);
22630}
22631
22632#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
22633#define XML_SCHEMA_PUSH_TEXT_CREATED 2
22634#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
22635
22636static int
22637xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
22638 int nodeType, const xmlChar *value, int len,
22639 int mode, int *consumed)
22640{
22641 /*
22642 * Unfortunately we have to duplicate the text sometimes.
22643 * OPTIMIZE: Maybe we could skip it, if:
22644 * 1. content type is simple
22645 * 2. whitespace is "collapse"
22646 * 3. it consists of whitespace only
22647 *
22648 * Process character content.
22649 */
22650 if (consumed != NULL)
22651 *consumed = 0;
22652 if (INODE_NILLED(vctxt->inode)) {
22653 /*
22654 * SPEC cvc-elt (3.3.4 - 3.2.1)
22655 * "The element information item must have no character or
22656 * element information item [children]."
22657 */
22658 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
22659 "Neither character nor element content is allowed "
22660 "because the element is 'nilled'");
22661 return (vctxt->err);
22662 }
22663 /*
22664 * SPEC (2.1) "If the {content type} is empty, then the
22665 * element information item has no character or element
22666 * information item [children]."
22667 */
22668 if (vctxt->inode->typeDef->contentType ==
22669 XML_SCHEMA_CONTENT_EMPTY) {
22670 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
22671 "Character content is not allowed, "
22672 "because the content type is empty");
22673 return (vctxt->err);
22674 }
22675
22676 if (vctxt->inode->typeDef->contentType ==
22677 XML_SCHEMA_CONTENT_ELEMENTS) {
22678 if ((nodeType != XML_TEXT_NODE) ||
22679 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
22680 /*
22681 * SPEC cvc-complex-type (2.3)
22682 * "If the {content type} is element-only, then the
22683 * element information item has no character information
22684 * item [children] other than those whose [character
22685 * code] is defined as a white space in [XML 1.0 (Second
22686 * Edition)]."
22687 */
22688 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
22689 "Character content other than whitespace is not allowed "
22690 "because the content type is 'element-only'");
22691 return (vctxt->err);
22692 }
22693 return (0);
22694 }
22695
22696 if ((value == NULL) || (value[0] == 0))
22697 return (0);
22698 /*
22699 * Save the value.
22700 * NOTE that even if the content type is *mixed*, we need the
22701 * *initial value* for default/fixed value constraints.
22702 */
22703 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
22704 ((vctxt->inode->decl == NULL) ||
22705 (vctxt->inode->decl->value == NULL)))
22706 return (0);
22707
22708 if (vctxt->inode->value == NULL) {
22709 /*
22710 * Set the value.
22711 */
22712 switch (mode) {
22713 case XML_SCHEMA_PUSH_TEXT_PERSIST:
22714 /*
22715 * When working on a tree.
22716 */
22717 vctxt->inode->value = value;
22718 break;
22719 case XML_SCHEMA_PUSH_TEXT_CREATED:
22720 /*
22721 * When working with the reader.
22722 * The value will be freed by the element info.
22723 */
22724 vctxt->inode->value = value;
22725 if (consumed != NULL)
22726 *consumed = 1;
22727 vctxt->inode->flags |=
22728 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22729 break;
22730 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
22731 /*
22732 * When working with SAX.
22733 * The value will be freed by the element info.
22734 */
22735 if (len != -1)
22736 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
22737 else
22738 vctxt->inode->value = BAD_CAST xmlStrdup(value);
22739 vctxt->inode->flags |=
22740 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22741 break;
22742 default:
22743 break;
22744 }
22745 } else {
22746 /*
22747 * Concat the value.
22748 */
22749 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
22750 vctxt->inode->value =
22751 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, -1);
22752 } else {
22753 vctxt->inode->value =
22754 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, -1);
22755 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22756 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022757 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022758
22759 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000022760}
22761
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022762static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022763xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022764{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022765 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000022766
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022767 if ((vctxt->skipDepth != -1) &&
22768 (vctxt->depth >= vctxt->skipDepth)) {
22769 VERROR_INT("xmlSchemaValidateElem",
22770 "in skip-state");
22771 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022772 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022773 if (vctxt->xsiAssemble) {
22774 if (xmlSchemaAssembleByXSI(vctxt) == -1)
22775 goto internal_error;
22776 }
22777 if (vctxt->depth > 0) {
22778 /*
22779 * Validate this element against the content model
22780 * of the parent.
22781 */
22782 ret = xmlSchemaValidateChildElem(vctxt);
22783 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022784 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022785 VERROR_INT("xmlSchemaValidateElem",
22786 "calling xmlSchemaStreamValidateChildElement()");
22787 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022788 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022789 goto exit;
22790 }
22791 if (vctxt->depth == vctxt->skipDepth)
22792 goto exit;
22793 if ((vctxt->inode->decl == NULL) &&
22794 (vctxt->inode->typeDef == NULL)) {
22795 VERROR_INT("xmlSchemaValidateElem",
22796 "the child element was valid but neither the "
22797 "declaration nor the type was set");
22798 goto internal_error;
22799 }
22800 } else {
22801 /*
22802 * Get the declaration of the validation root.
22803 */
22804 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22805 vctxt->inode->localName,
22806 vctxt->inode->nsName);
22807 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022808 ret = XML_SCHEMAV_CVC_ELT_1;
22809 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022810 "No matching global declaration available "
22811 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022812 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022813 }
22814 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022815
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022816 if (vctxt->inode->decl == NULL)
22817 goto type_validation;
22818
22819 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
22820 int skip;
22821 /*
22822 * Wildcards.
22823 */
22824 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
22825 if (ret != 0) {
22826 if (ret < 0) {
22827 VERROR_INT("xmlSchemaValidateElem",
22828 "calling xmlSchemaValidateElemWildcard()");
22829 goto internal_error;
22830 }
22831 goto exit;
22832 }
22833 if (skip) {
22834 vctxt->skipDepth = vctxt->depth;
22835 goto exit;
22836 }
22837 /*
22838 * The declaration might be set by the wildcard validation,
22839 * when the processContents is "lax" or "strict".
22840 */
22841 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
22842 /*
22843 * Clear the "decl" field to not confuse further processing.
22844 */
22845 vctxt->inode->decl = NULL;
22846 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022847 }
Daniel Veillard4255d502002-04-16 15:50:10 +000022848 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022849 /*
22850 * Validate against the declaration.
22851 */
22852 ret = xmlSchemaValidateElemDecl(vctxt);
22853 if (ret != 0) {
22854 if (ret < 0) {
22855 VERROR_INT("xmlSchemaValidateElem",
22856 "calling xmlSchemaValidateElemDecl()");
22857 goto internal_error;
22858 }
22859 goto exit;
22860 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022861 /*
22862 * Validate against the type definition.
22863 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022864type_validation:
22865
22866 if (vctxt->inode->typeDef == NULL) {
22867 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
22868 ret = XML_SCHEMAV_CVC_TYPE_1;
22869 VERROR(ret, NULL,
22870 "The type definition is absent");
22871 goto exit;
22872 }
22873 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
22874 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
22875 ret = XML_SCHEMAV_CVC_TYPE_2;
22876 VERROR(ret, NULL,
22877 "The type definition is abstract");
22878 goto exit;
22879 }
22880 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022881 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022882 * during validation against the declaration. This must be done
22883 * _before_ attribute validation.
22884 */
22885 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
22886 if (ret == -1) {
22887 VERROR_INT("xmlSchemaValidateElem",
22888 "calling xmlSchemaXPathEvaluate()");
22889 goto internal_error;
22890 }
22891 /*
22892 * Validate attributes.
22893 */
22894 if (IS_COMPLEX_TYPE(vctxt->inode->typeDef)) {
22895 if ((vctxt->nbAttrInfos != 0) ||
22896 (vctxt->inode->typeDef->attributeUses != NULL)) {
22897
22898 ret = xmlSchemaVAttributesComplex(vctxt);
22899 }
22900 } else if (vctxt->nbAttrInfos != 0) {
22901
22902 ret = xmlSchemaVAttributesSimple(vctxt);
22903 }
22904 /*
22905 * Clear registered attributes.
22906 */
22907 if (vctxt->nbAttrInfos != 0)
22908 xmlSchemaClearAttrInfos(vctxt);
22909 if (ret == -1) {
22910 VERROR_INT("xmlSchemaValidateElem",
22911 "calling attributes validation");
22912 goto internal_error;
22913 }
22914 /*
22915 * Don't return an error if attributes are invalid on purpose.
22916 */
22917 ret = 0;
22918
22919exit:
22920 if (ret != 0)
22921 vctxt->skipDepth = vctxt->depth;
22922 return (ret);
22923internal_error:
22924 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022925}
22926
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022927#ifdef XML_SCHEMA_READER_ENABLED
22928static int
22929xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000022930{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022931 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
22932 int depth, nodeType, ret = 0, consumed;
22933 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000022934
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022935 vctxt->depth = -1;
22936 ret = xmlTextReaderRead(vctxt->reader);
22937 /*
22938 * Move to the document element.
22939 */
22940 while (ret == 1) {
22941 nodeType = xmlTextReaderNodeType(vctxt->reader);
22942 if (nodeType == XML_ELEMENT_NODE)
22943 goto root_found;
22944 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022945 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022946 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022947
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022948root_found:
22949
22950 do {
22951 depth = xmlTextReaderDepth(vctxt->reader);
22952 nodeType = xmlTextReaderNodeType(vctxt->reader);
22953
22954 if (nodeType == XML_ELEMENT_NODE) {
22955
22956 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
22957 VERROR_INT("xmlSchemaVReaderWalk",
22958 "calling xmlSchemaValidatorPushElem()");
22959 goto internal_error;
22960 }
22961 ielem = vctxt->inode;
22962 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
22963 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
22964 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
22965 /*
22966 * Is the element empty?
22967 */
22968 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
22969 if (ret == -1) {
22970 VERROR_INT("xmlSchemaVReaderWalk",
22971 "calling xmlTextReaderIsEmptyElement()");
22972 goto internal_error;
22973 }
22974 if (ret) {
22975 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
22976 }
22977 /*
22978 * Register attributes.
22979 */
22980 vctxt->nbAttrInfos = 0;
22981 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
22982 if (ret == -1) {
22983 VERROR_INT("xmlSchemaVReaderWalk",
22984 "calling xmlTextReaderMoveToFirstAttribute()");
22985 goto internal_error;
22986 }
22987 if (ret == 1) {
22988 do {
22989 /*
22990 * VAL TODO: How do we know that the reader works on a
22991 * node tree, to be able to pass a node here?
22992 */
22993 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
22994 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
22995 xmlTextReaderNamespaceUri(vctxt->reader), 1,
22996 xmlTextReaderValue(vctxt->reader), 1) == -1) {
22997
22998 VERROR_INT("xmlSchemaVReaderWalk",
22999 "calling xmlSchemaValidatorPushAttribute()");
23000 goto internal_error;
23001 }
23002 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
23003 if (ret == -1) {
23004 VERROR_INT("xmlSchemaVReaderWalk",
23005 "calling xmlTextReaderMoveToFirstAttribute()");
23006 goto internal_error;
23007 }
23008 } while (ret == 1);
23009 /*
23010 * Back to element position.
23011 */
23012 ret = xmlTextReaderMoveToElement(vctxt->reader);
23013 if (ret == -1) {
23014 VERROR_INT("xmlSchemaVReaderWalk",
23015 "calling xmlTextReaderMoveToElement()");
23016 goto internal_error;
23017 }
23018 }
23019 /*
23020 * Validate the element.
23021 */
23022 ret= xmlSchemaValidateElem(vctxt);
23023 if (ret != 0) {
23024 if (ret == -1) {
23025 VERROR_INT("xmlSchemaVReaderWalk",
23026 "calling xmlSchemaValidateElem()");
23027 goto internal_error;
23028 }
23029 goto exit;
23030 }
23031 if (vctxt->depth == vctxt->skipDepth) {
23032 int curDepth;
23033 /*
23034 * Skip all content.
23035 */
23036 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
23037 ret = xmlTextReaderRead(vctxt->reader);
23038 curDepth = xmlTextReaderDepth(vctxt->reader);
23039 while ((ret == 1) && (curDepth != depth)) {
23040 ret = xmlTextReaderRead(vctxt->reader);
23041 curDepth = xmlTextReaderDepth(vctxt->reader);
23042 }
23043 if (ret < 0) {
23044 /*
23045 * VAL TODO: A reader error occured; what to do here?
23046 */
23047 ret = 1;
23048 goto exit;
23049 }
23050 }
23051 goto leave_elem;
23052 }
23053 /*
23054 * READER VAL TODO: Is an END_ELEM really never called
23055 * if the elem is empty?
23056 */
23057 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23058 goto leave_elem;
23059 } else if (nodeType == END_ELEM) {
23060 /*
23061 * Process END of element.
23062 */
23063leave_elem:
23064 ret = xmlSchemaValidatorPopElem(vctxt);
23065 if (ret != 0) {
23066 if (ret < 0) {
23067 VERROR_INT("xmlSchemaVReaderWalk",
23068 "calling xmlSchemaValidatorPopElem()");
23069 goto internal_error;
23070 }
23071 goto exit;
23072 }
23073 if (vctxt->depth >= 0)
23074 ielem = vctxt->inode;
23075 else
23076 ielem = NULL;
23077 } else if ((nodeType == XML_TEXT_NODE) ||
23078 (nodeType == XML_CDATA_SECTION_NODE) ||
23079 (nodeType == WHTSP) ||
23080 (nodeType == SIGN_WHTSP)) {
23081 /*
23082 * Process character content.
23083 */
23084 xmlChar *value;
23085
23086 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
23087 nodeType = XML_TEXT_NODE;
23088
23089 value = xmlTextReaderValue(vctxt->reader);
23090 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
23091 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
23092 if (! consumed)
23093 xmlFree(value);
23094 if (ret == -1) {
23095 VERROR_INT("xmlSchemaVReaderWalk",
23096 "calling xmlSchemaVPushText()");
23097 goto internal_error;
23098 }
23099 } else if ((nodeType == XML_ENTITY_NODE) ||
23100 (nodeType == XML_ENTITY_REF_NODE)) {
23101 /*
23102 * VAL TODO: What to do with entities?
23103 */
23104 TODO
23105 }
23106 /*
23107 * Read next node.
23108 */
23109 ret = xmlTextReaderRead(vctxt->reader);
23110 } while (ret == 1);
23111
23112exit:
23113 return (ret);
23114internal_error:
23115 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023116}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023117#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000023118
23119/************************************************************************
23120 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023121 * SAX validation handlers *
Daniel Veillard4255d502002-04-16 15:50:10 +000023122 * *
23123 ************************************************************************/
23124
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023125#ifdef XML_SCHEMA_SAX_ENABLED
23126/*
23127* Process text content.
23128*/
23129static void
23130xmlSchemaSAXHandleText(void *ctx,
23131 const xmlChar * ch,
23132 int len)
23133{
23134 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23135
23136 if (vctxt->depth < 0)
23137 return;
23138 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23139 return;
23140 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23141 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23142 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
23143 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23144 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23145 "calling xmlSchemaVPushText()");
23146 vctxt->err = -1;
23147 xmlStopParser(vctxt->parserCtxt);
23148 }
23149}
23150
23151/*
23152* Process CDATA content.
23153*/
23154static void
23155xmlSchemaSAXHandleCDataSection(void *ctx,
23156 const xmlChar * ch,
23157 int len)
23158{
23159 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23160
23161 if (vctxt->depth < 0)
23162 return;
23163 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23164 return;
23165 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23166 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23167 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
23168 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23169 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23170 "calling xmlSchemaVPushText()");
23171 vctxt->err = -1;
23172 xmlStopParser(vctxt->parserCtxt);
23173 }
23174}
23175
23176static void
23177xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
23178 const xmlChar * name ATTRIBUTE_UNUSED)
23179{
23180 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23181
23182 if (vctxt->depth < 0)
23183 return;
23184 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23185 return;
23186 /* SAX VAL TODO: What to do here? */
23187 TODO
23188}
23189
23190static void
23191xmlSchemaSAXHandleStartElementNs(void *ctx,
23192 const xmlChar * localname,
23193 const xmlChar * prefix ATTRIBUTE_UNUSED,
23194 const xmlChar * URI,
23195 int nb_namespaces,
23196 const xmlChar ** namespaces,
23197 int nb_attributes,
23198 int nb_defaulted ATTRIBUTE_UNUSED,
23199 const xmlChar ** attributes)
23200{
23201 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23202 int ret;
23203 xmlSchemaNodeInfoPtr ielem;
23204 int i, j;
23205
23206 /*
23207 * SAX VAL TODO: What to do with nb_defaulted?
23208 */
23209 /*
23210 * Skip elements if inside a "skip" wildcard.
23211 */
23212 if ((vctxt->skipDepth != -1) && (vctxt->depth > vctxt->skipDepth))
23213 return;
23214 /*
23215 * Push the element.
23216 */
23217 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23218 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23219 "calling xmlSchemaValidatorPushElem()");
23220 goto internal_error;
23221 }
23222 ielem = vctxt->inode;
23223 ielem->localName = localname;
23224 ielem->nsName = URI;
23225 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23226 /*
23227 * Register namespaces on the elem info.
23228 */
23229 if (nb_namespaces != 0) {
23230 /*
23231 * Although the parser builds its own namespace list,
23232 * we have no access to it, so we'll use an own one.
23233 */
23234 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
23235 /*
23236 * Store prefix and namespace name.
23237 */
23238 if (ielem->nsBindings == NULL) {
23239 ielem->nsBindings =
23240 (const xmlChar **) xmlMalloc(10 *
23241 sizeof(const xmlChar *));
23242 if (ielem->nsBindings == NULL) {
23243 xmlSchemaVErrMemory(vctxt,
23244 "allocating namespace bindings for SAX validation",
23245 NULL);
23246 goto internal_error;
23247 }
23248 ielem->nbNsBindings = 0;
23249 ielem->sizeNsBindings = 5;
23250 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
23251 ielem->sizeNsBindings *= 2;
23252 ielem->nsBindings =
23253 (const xmlChar **) xmlRealloc(
23254 (void *) ielem->nsBindings,
23255 ielem->nbNsBindings * 2 * sizeof(const xmlChar *));
23256 if (ielem->nsBindings == NULL) {
23257 xmlSchemaVErrMemory(vctxt,
23258 "re-allocating namespace bindings for SAX validation",
23259 NULL);
23260 goto internal_error;
23261 }
23262 }
23263
23264 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
23265 if (namespaces[j+1][0] == 0) {
23266 /*
23267 * Handle xmlns="".
23268 */
23269 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
23270 } else
23271 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
23272 namespaces[j+1];
23273 ielem->nbNsBindings++;
23274 }
23275 }
23276 /*
23277 * Register attributes.
23278 * SAX VAL TODO: We are not adding namespace declaration
23279 * attributes yet.
23280 */
23281 if (nb_attributes != 0) {
23282 xmlChar *value;
23283
23284 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
23285 /*
23286 * Duplicate the value.
23287 */
23288 value = xmlStrndup(attributes[j+3],
23289 attributes[j+4] - attributes[j+3]);
23290 ret = xmlSchemaValidatorPushAttribute(vctxt,
23291 NULL, attributes[j], attributes[j+2], 0,
23292 value, 1);
23293 if (ret == -1) {
23294 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23295 "calling xmlSchemaValidatorPushAttribute()");
23296 goto internal_error;
23297 }
23298 }
23299 }
23300 /*
23301 * Validate the element.
23302 */
23303 ret = xmlSchemaValidateElem(vctxt);
23304 if (ret != 0) {
23305 if (ret == -1) {
23306 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23307 "calling xmlSchemaValidateElem()");
23308 goto internal_error;
23309 }
23310 goto exit;
23311 }
23312
23313exit:
23314 return;
23315internal_error:
23316 vctxt->err = -1;
23317 xmlStopParser(vctxt->parserCtxt);
23318 return;
23319}
23320
23321static void
23322xmlSchemaSAXHandleEndElementNs(void *ctx,
23323 const xmlChar * localname ATTRIBUTE_UNUSED,
23324 const xmlChar * prefix ATTRIBUTE_UNUSED,
23325 const xmlChar * URI ATTRIBUTE_UNUSED)
23326{
23327 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23328 int res;
23329
23330 /*
23331 * Skip elements if inside a "skip" wildcard.
23332 */
23333 if (vctxt->skipDepth != -1) {
23334 if (vctxt->depth > vctxt->skipDepth) {
23335 vctxt->depth--;
23336 return;
23337 } else
23338 vctxt->skipDepth = -1;
23339 }
23340 /*
23341 * SAX VAL TODO: Just a temporary check.
23342 */
23343 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
23344 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
23345 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23346 "elem pop mismatch");
23347 }
23348 res = xmlSchemaValidatorPopElem(vctxt);
23349 if (res != 0) {
23350 if (res < 0) {
23351 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23352 "calling xmlSchemaValidatorPopElem()");
23353 goto internal_error;
23354 }
23355 goto exit;
23356 }
23357exit:
23358 return;
23359internal_error:
23360 vctxt->err = -1;
23361 xmlStopParser(vctxt->parserCtxt);
23362 return;
23363}
23364#endif
23365
Daniel Veillard4255d502002-04-16 15:50:10 +000023366/************************************************************************
23367 * *
23368 * Validation interfaces *
23369 * *
23370 ************************************************************************/
23371
23372/**
23373 * xmlSchemaNewValidCtxt:
23374 * @schema: a precompiled XML Schemas
23375 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023376 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000023377 *
23378 * Returns the validation context or NULL in case of error
23379 */
23380xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023381xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
23382{
Daniel Veillard4255d502002-04-16 15:50:10 +000023383 xmlSchemaValidCtxtPtr ret;
23384
23385 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
23386 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023387 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000023388 return (NULL);
23389 }
23390 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023391 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
23392 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000023393 return (ret);
23394}
23395
23396/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023397 * xmlSchemaClearValidCtxt:
23398 * @ctxt: the schema validation context
23399 *
23400 * Free the resources associated to the schema validation context;
23401 * leaves some fields alive intended for reuse of the context.
23402 */
23403static void
23404xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
23405{
23406 if (vctxt == NULL)
23407 return;
23408
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000023409 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023410 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023411 vctxt->doc = NULL;
23412 vctxt->reader = NULL;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023413 if (vctxt->value != NULL) {
23414 xmlSchemaFreeValue(vctxt->value);
23415 vctxt->value = NULL;
23416 }
23417 /*
23418 * Augmented IDC information.
23419 */
23420 if (vctxt->aidcs != NULL) {
23421 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
23422 do {
23423 next = cur->next;
23424 xmlFree(cur);
23425 cur = next;
23426 } while (cur != NULL);
23427 vctxt->aidcs = NULL;
23428 }
23429 if (vctxt->idcNodes != NULL) {
23430 int i;
23431 xmlSchemaPSVIIDCNodePtr item;
23432
23433 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023434 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023435 xmlFree(item->keys);
23436 xmlFree(item);
23437 }
23438 xmlFree(vctxt->idcNodes);
23439 vctxt->idcNodes = NULL;
23440 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023441 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023442 * Note that we won't delete the XPath state pool here.
23443 */
23444 if (vctxt->xpathStates != NULL) {
23445 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
23446 vctxt->xpathStates = NULL;
23447 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023448 /*
23449 * Attribute info.
23450 */
23451 if (vctxt->nbAttrInfos != 0) {
23452 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023453 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023454 /*
23455 * Element info.
23456 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023457 if (vctxt->elemInfos != NULL) {
23458 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023459 xmlSchemaNodeInfoPtr ei;
23460
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023461 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023462 ei = vctxt->elemInfos[i];
23463 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023464 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023465 xmlSchemaClearElemInfo(ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023466 }
23467 }
23468}
23469
23470/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023471 * xmlSchemaFreeValidCtxt:
23472 * @ctxt: the schema validation context
23473 *
23474 * Free the resources associated to the schema validation context
23475 */
23476void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023477xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
23478{
Daniel Veillard4255d502002-04-16 15:50:10 +000023479 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023480 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000023481 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023482 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023483 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023484 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023485 if (ctxt->idcNodes != NULL) {
23486 int i;
23487 xmlSchemaPSVIIDCNodePtr item;
23488
23489 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023490 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023491 xmlFree(item->keys);
23492 xmlFree(item);
23493 }
23494 xmlFree(ctxt->idcNodes);
23495 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023496 if (ctxt->idcKeys != NULL) {
23497 int i;
23498 for (i = 0; i < ctxt->nbIdcKeys; i++)
23499 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
23500 xmlFree(ctxt->idcKeys);
23501 }
23502
23503 if (ctxt->xpathStates != NULL)
23504 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
23505 if (ctxt->xpathStatePool != NULL)
23506 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
23507
23508 /*
23509 * Augmented IDC information.
23510 */
23511 if (ctxt->aidcs != NULL) {
23512 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
23513 do {
23514 next = cur->next;
23515 xmlFree(cur);
23516 cur = next;
23517 } while (cur != NULL);
23518 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023519 if (ctxt->attrInfos != NULL) {
23520 int i;
23521 xmlSchemaAttrInfoPtr attr;
23522
23523 /* Just a paranoid call to the cleanup. */
23524 if (ctxt->nbAttrInfos != 0)
23525 xmlSchemaClearAttrInfos(ctxt);
23526 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
23527 attr = ctxt->attrInfos[i];
23528 xmlFree(attr);
23529 }
23530 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023531 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023532 if (ctxt->elemInfos != NULL) {
23533 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023534 xmlSchemaNodeInfoPtr ei;
23535
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023536 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023537 ei = ctxt->elemInfos[i];
23538 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023539 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023540 xmlSchemaClearElemInfo(ei);
23541 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023542 }
23543 xmlFree(ctxt->elemInfos);
23544 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023545 if (ctxt->dict != NULL)
23546 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000023547 xmlFree(ctxt);
23548}
23549
23550/**
23551 * xmlSchemaSetValidErrors:
23552 * @ctxt: a schema validation context
23553 * @err: the error function
23554 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000023555 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000023556 *
William M. Brack2f2a6632004-08-20 23:09:47 +000023557 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000023558 */
23559void
23560xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023561 xmlSchemaValidityErrorFunc err,
23562 xmlSchemaValidityWarningFunc warn, void *ctx)
23563{
Daniel Veillard4255d502002-04-16 15:50:10 +000023564 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023565 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000023566 ctxt->error = err;
23567 ctxt->warning = warn;
23568 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023569 if (ctxt->pctxt != NULL)
23570 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000023571}
23572
23573/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000023574 * xmlSchemaGetValidErrors:
23575 * @ctxt: a XML-Schema validation context
23576 * @err: the error function result
23577 * @warn: the warning function result
23578 * @ctx: the functions context result
23579 *
23580 * Get the error and warning callback informations
23581 *
23582 * Returns -1 in case of error and 0 otherwise
23583 */
23584int
23585xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
23586 xmlSchemaValidityErrorFunc * err,
23587 xmlSchemaValidityWarningFunc * warn, void **ctx)
23588{
23589 if (ctxt == NULL)
23590 return (-1);
23591 if (err != NULL)
23592 *err = ctxt->error;
23593 if (warn != NULL)
23594 *warn = ctxt->warning;
23595 if (ctx != NULL)
23596 *ctx = ctxt->userData;
23597 return (0);
23598}
23599
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023600
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023601/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023602 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023603 * @ctxt: a schema validation context
23604 * @options: a combination of xmlSchemaValidOption
23605 *
23606 * Sets the options to be used during the validation.
23607 *
23608 * Returns 0 in case of success, -1 in case of an
23609 * API error.
23610 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023611int
23612xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
23613 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023614
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023615{
23616 int i;
23617
23618 if (ctxt == NULL)
23619 return (-1);
23620 /*
23621 * WARNING: Change the start value if adding to the
23622 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023623 * TODO: Is there an other, more easy to maintain,
23624 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023625 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023626 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023627 if (options & 1<<i)
23628 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023629 }
23630 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023631 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023632}
23633
23634/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023635 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023636 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023637 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023638 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023639 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023640 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023641 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023642int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023643xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023644
23645{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023646 if (ctxt == NULL)
23647 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023648 else
23649 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023650}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023651
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023652static int
23653xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
23654{
23655 xmlAttrPtr attr;
23656 int ret = 0;
23657 xmlSchemaNodeInfoPtr ielem = NULL;
23658 xmlNodePtr node, valRoot;
23659 const xmlChar *nsName;
23660
23661 /* DOC VAL TODO: Move this to the start function. */
23662 valRoot = xmlDocGetRootElement(vctxt->doc);
23663 if (valRoot == NULL) {
23664 /* VAL TODO: Error code? */
23665 VERROR(1, NULL, "The document has no document element");
23666 return (1);
23667 }
23668 vctxt->depth = -1;
23669 vctxt->validationRoot = valRoot;
23670 node = valRoot;
23671 while (node != NULL) {
23672 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23673 goto next_sibling;
23674 if (node->type == XML_ELEMENT_NODE) {
23675
23676 /*
23677 * Init the node-info.
23678 */
23679 if (xmlSchemaValidatorPushElem(vctxt) == -1)
23680 goto internal_error;
23681 ielem = vctxt->inode;
23682 ielem->node = node;
23683 ielem->localName = node->name;
23684 if (node->ns != NULL)
23685 ielem->nsName = node->ns->href;
23686 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23687 /*
23688 * Register attributes.
23689 * DOC VAL TODO: We do not register namespace declaration
23690 * attributes yet.
23691 */
23692 vctxt->nbAttrInfos = 0;
23693 if (node->properties != NULL) {
23694 attr = node->properties;
23695 do {
23696 if (attr->ns != NULL)
23697 nsName = attr->ns->href;
23698 else
23699 nsName = NULL;
23700 ret = xmlSchemaValidatorPushAttribute(vctxt,
23701 (xmlNodePtr) attr,
23702 attr->name, nsName, 0,
23703 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
23704 if (ret == -1) {
23705 VERROR_INT("xmlSchemaDocWalk",
23706 "calling xmlSchemaValidatorPushAttribute()");
23707 goto internal_error;
23708 }
23709 attr = attr->next;
23710 } while (attr);
23711 }
23712 /*
23713 * Validate the element.
23714 */
23715 ret = xmlSchemaValidateElem(vctxt);
23716 if (ret != 0) {
23717 if (ret == -1) {
23718 VERROR_INT("xmlSchemaDocWalk",
23719 "calling xmlSchemaValidateElem()");
23720 goto internal_error;
23721 }
23722 /*
23723 * Don't stop validation; just skip the content
23724 * of this element.
23725 */
23726 goto leave_node;
23727 }
23728 if ((vctxt->skipDepth != -1) &&
23729 (vctxt->depth >= vctxt->skipDepth))
23730 goto leave_node;
23731 } else if ((node->type == XML_TEXT_NODE) ||
23732 (node->type == XML_CDATA_SECTION_NODE)) {
23733 /*
23734 * Process character content.
23735 */
23736 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23737 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23738 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
23739 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
23740 if (ret < 0) {
23741 VERROR_INT("xmlSchemaVDocWalk",
23742 "calling xmlSchemaVPushText()");
23743 goto internal_error;
23744 }
23745 /*
23746 * DOC VAL TODO: Should we skip further validation of the
23747 * element content here?
23748 */
23749 } else if ((node->type == XML_ENTITY_NODE) ||
23750 (node->type == XML_ENTITY_REF_NODE)) {
23751 /*
23752 * DOC VAL TODO: What to do with entities?
23753 */
23754 TODO
23755 } else {
23756 goto leave_node;
23757 /*
23758 * DOC VAL TODO: XInclude nodes, etc.
23759 */
23760 }
23761 /*
23762 * Walk the doc.
23763 */
23764 if (node->children != NULL) {
23765 node = node->children;
23766 continue;
23767 }
23768leave_node:
23769 if (node->type == XML_ELEMENT_NODE) {
23770 /*
23771 * Leaving the scope of an element.
23772 */
23773 if (node != vctxt->inode->node) {
23774 VERROR_INT("xmlSchemaVDocWalk",
23775 "element position mismatch");
23776 goto internal_error;
23777 }
23778 ret = xmlSchemaValidatorPopElem(vctxt);
23779 if (ret != 0) {
23780 if (ret < 0) {
23781 VERROR_INT("xmlSchemaVDocWalk",
23782 "calling xmlSchemaValidatorPopElem()");
23783 goto internal_error;
23784 }
23785 }
23786 if (node == valRoot)
23787 goto exit;
23788 }
23789next_sibling:
23790 if (node->next != NULL)
23791 node = node->next;
23792 else {
23793 node = node->parent;
23794 goto leave_node;
23795 }
23796 }
23797
23798exit:
23799 return (ret);
23800internal_error:
23801 return (-1);
23802}
23803
23804static int
23805xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
23806{
23807 int ret = 0;
23808
23809 /*
23810 * Some initialization.
23811 */
23812 vctxt->err = 0;
23813 vctxt->nberrors = 0;
23814 vctxt->depth = -1;
23815 vctxt->skipDepth = -1;
23816 /*
23817 * Create a schema + parser if necessary.
23818 */
23819 if (vctxt->schema == NULL) {
23820
23821 if ((vctxt->pctxt == NULL) &&
23822 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
23823 return (-1);
23824
23825 vctxt->schema = xmlSchemaNewSchema(vctxt->pctxt);
23826 if (vctxt->schema == NULL) {
23827 VERROR_INT("xmlSchemaVStartValidation",
23828 "creating a schema");
23829 return (-1);
23830 }
23831 vctxt->xsiAssemble = 1;
23832 } else
23833 vctxt->xsiAssemble = 0;
23834 /*
23835 * Augment the IDC definitions.
23836 */
23837 if (vctxt->schema->idcDef != NULL) {
23838 xmlHashScan(vctxt->schema->idcDef,
23839 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
23840 }
23841 if (vctxt->doc != NULL) {
23842 /*
23843 * Tree validation.
23844 */
23845 ret = xmlSchemaVDocWalk(vctxt);
23846 } else if (vctxt->reader != NULL) {
23847 /*
23848 * XML Reader validation.
23849 */
23850#ifdef XML_SCHEMA_READER_ENABLED
23851 ret = xmlSchemaVReaderWalk(vctxt);
23852#endif
23853 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
23854 /*
23855 * SAX validation.
23856 */
23857 /* ret = xmlSAXUserParseFile(ctxt->sax, ctxt, uri); */
23858 ret = xmlParseDocument(vctxt->parserCtxt);
23859 } else {
23860 VERROR_INT("xmlSchemaVStartValidation",
23861 "no instance to validate");
23862 ret = -1;
23863 }
23864
23865 if (vctxt->xsiAssemble) {
23866 if (vctxt->schema != NULL) {
23867 xmlSchemaFree(vctxt->schema);
23868 vctxt->schema = NULL;
23869 }
23870 }
23871 xmlSchemaClearValidCtxt(vctxt);
23872 if (ret == 0)
23873 ret = vctxt->err;
23874 return (ret);
23875}
23876
23877/**
23878 * xmlSchemaValidateOneElement:
23879 * @ctxt: a schema validation context
23880 * @elem: an element node
23881 *
23882 * Validate a branch of a tree, starting with the given @elem.
23883 *
23884 * Returns 0 if the element and its subtree is valid, a positive error
23885 * code number otherwise and -1 in case of an internal or API error.
23886 */
23887int
23888xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
23889{
23890 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
23891 return (-1);
23892
23893 if (ctxt->schema == NULL)
23894 return (-1);
23895
23896 ctxt->doc = elem->doc;
23897 ctxt->node = elem;
23898 ctxt->validationRoot = elem;
23899 return(xmlSchemaVStart(ctxt));
23900}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023901
Daniel Veillard259f0df2004-08-18 09:13:18 +000023902/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023903 * xmlSchemaValidateDoc:
23904 * @ctxt: a schema validation context
23905 * @doc: a parsed document tree
23906 *
23907 * Validate a document tree in memory.
23908 *
23909 * Returns 0 if the document is schemas valid, a positive error code
23910 * number otherwise and -1 in case of internal or API error.
23911 */
23912int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023913xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
23914{
Daniel Veillard4255d502002-04-16 15:50:10 +000023915 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023916 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023917
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023918 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023919 ctxt->node = xmlDocGetRootElement(doc);
23920 if (ctxt->node == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023921 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023922 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
23923 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023924 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023925 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023926 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023927 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023928 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000023929}
23930
23931/**
23932 * xmlSchemaValidateStream:
23933 * @ctxt: a schema validation context
23934 * @input: the input to use for reading the data
23935 * @enc: an optional encoding information
23936 * @sax: a SAX handler for the resulting events
23937 * @user_data: the context to provide to the SAX handler.
23938 *
23939 * Validate a document tree in memory.
23940 *
23941 * Returns 0 if the document is schemas valid, a positive error code
23942 * number otherwise and -1 in case of internal or API error.
23943 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023944int
Daniel Veillard4255d502002-04-16 15:50:10 +000023945xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023946 xmlParserInputBufferPtr input, xmlCharEncoding enc,
23947 xmlSAXHandlerPtr sax, void *user_data)
23948{
Daniel Veillard4255d502002-04-16 15:50:10 +000023949 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023950 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023951 ctxt->input = input;
23952 ctxt->enc = enc;
23953 ctxt->sax = sax;
23954 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023955 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000023956}
23957
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000023958#ifdef XML_SCHEMA_SAX_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023959/**
23960 * xmlSchemaValidateFile:
23961 * @ctxt: a schema validation context
23962 * @uri: the URI of the instance
23963 *
23964 * Returns 0 if the document is valid, a positive error code
23965 * number otherwise and -1 in case of an internal or API error.
23966 */
23967int
23968xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000023969 const char * filename,
23970 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023971{
23972 int ret;
23973
23974 if ((ctxt == NULL) || (filename == NULL))
23975 return (-1);
23976
23977 ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
23978 if (ctxt->sax == NULL) {
23979 xmlSchemaVErrMemory(ctxt,
23980 "creating SAX handler", NULL);
23981 return (-1);
23982 }
23983 memset(ctxt->sax, 0, sizeof(xmlSAXHandler));
23984 ctxt->parserCtxt = xmlCreateFileParserCtxt(filename);
23985 if (ctxt->parserCtxt == NULL) {
23986 xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) ctxt,
23987 "xmlSchemaValidateFile", "creating a parser context");
23988 xmlFree(ctxt->sax);
23989 return (-1);
23990 }
23991#ifdef LIBXML_SAX1_ENABLED
23992 if (ctxt->parserCtxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
23993#endif /* LIBXML_SAX1_ENABLED */
23994 xmlFree(ctxt->parserCtxt->sax);
23995 /*
23996 * Init the SAX handler.
23997 */
23998 ctxt->sax->startElementNs = xmlSchemaSAXHandleStartElementNs;
23999 ctxt->sax->endElementNs = xmlSchemaSAXHandleEndElementNs;
24000 /*
24001 * Note that we use the same text-function for both, to prevent
24002 * the parser from testing for ignorable whitespace.
24003 */
24004 ctxt->sax->ignorableWhitespace = xmlSchemaSAXHandleText;
24005 ctxt->sax->characters = xmlSchemaSAXHandleText;
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024006
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024007 ctxt->sax->cdataBlock = xmlSchemaSAXHandleCDataSection;
24008 ctxt->sax->reference = xmlSchemaSAXHandleReference;
24009 ctxt->sax->initialized = XML_SAX2_MAGIC;
24010 /*
24011 * Init the parser context.
24012 */
24013 ctxt->parserCtxt->sax = ctxt->sax;
24014 ctxt->parserCtxt->sax2 = 1;
24015 ctxt->parserCtxt->userData = ctxt;
24016 /* VAL TODO: Set error handlers. */
24017
24018 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024019 ret = xmlSchemaVStart(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024020
24021 /*
24022 * URGENT VAL TODO: What to do with well-formedness errors?
24023 */
24024 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
24025 ret = ctxt->parserCtxt->errNo;
24026 if (ret == 0)
24027 /* URGENT VAL TODO: Error code? */
24028 ret = 1;
24029 xmlSchemaErr((xmlSchemaAbstractCtxtPtr) ctxt, ret, NULL,
24030 "The instance document '%s' is not well-formed",
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024031 BAD_CAST filename, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024032 }
24033 ctxt->parserCtxt->sax = NULL;
24034 xmlFreeParserCtxt(ctxt->parserCtxt);
24035 xmlFree(ctxt->sax);
24036 ctxt->sax = NULL;
24037
24038 return (ret);
24039}
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024040#endif /* XML_SCHEMA_SAX_ENABLED */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024041
24042#ifdef XML_SCHEMA_READER_ENABLED
24043int
24044xmlSchemaValidateReader(xmlSchemaValidCtxtPtr ctxt,
24045 xmlTextReaderPtr reader)
24046{
24047 if ((ctxt == NULL) || (reader == NULL))
24048 return (-1);
24049 ctxt->reader = reader;
24050 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
24051 return(xmlSchemaVStart(ctxt, NULL));
24052}
24053#endif /* XML_SCHEMA_READER_ENABLED */
24054
Daniel Veillard5d4644e2005-04-01 13:11:58 +000024055#define bottom_xmlschemas
24056#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000024057#endif /* LIBXML_SCHEMAS_ENABLED */