blob: 79d58a00fed4e4092adb9f2c5db5a8cae96ed73b [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 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020 * URGENT TODO:
21 * - For xsi-driven schema acquisition, augment the IDCs after every
22 * acquisition episode (xmlSchemaAugmentIDC).
23 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000024 * NOTES:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025 * - Elimated item creation for: <restriction>, <extension>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026 * <simpleContent>, <complexContent>, <list>, <union>
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000028 * PROBLEMS:
29 * - http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0337.html
30 * IDC XPath expression and chameleon includes: the targetNamespace is changed, so
31 * XPath will have trouble to resolve to this namespace, since not known.
32 *
33 *
34 * CONSTRAINTS:
35 *
36 * Schema Component Constraint:
37 * All Group Limited (cos-all-limited)
38 * Status: complete
39 * (1.2)
40 * In xmlSchemaGroupDefReferenceTermFixup() and
41 * (2)
42 * In xmlSchemaParseModelGroup()
43 * TODO: Actually this should go to component-level checks,
44 * but is done here due to performance. Move it to an other layer
45 * is schema construction via an API is implemented.
Daniel Veillardb0f397e2003-12-23 23:30:53 +000046 */
Daniel Veillard4255d502002-04-16 15:50:10 +000047#define IN_LIBXML
48#include "libxml.h"
49
50#ifdef LIBXML_SCHEMAS_ENABLED
51
52#include <string.h>
53#include <libxml/xmlmemory.h>
54#include <libxml/parser.h>
55#include <libxml/parserInternals.h>
56#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000057#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000058#include <libxml/xmlschemas.h>
59#include <libxml/schemasInternals.h>
60#include <libxml/xmlschemastypes.h>
61#include <libxml/xmlautomata.h>
62#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000063#include <libxml/dict.h>
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000064#include <libxml/encoding.h>
65#include <libxml/xmlIO.h>
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000066#ifdef LIBXML_PATTERN_ENABLED
67#include <libxml/pattern.h>
68#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000069#ifdef LIBXML_READER_ENABLED
70#include <libxml/xmlreader.h>
71#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000072
Daniel Veillarda84c0b32003-06-02 16:58:46 +000073/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000074
Daniel Veillard82bbbd42003-05-11 20:16:09 +000075/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000076
Daniel Veillard82bbbd42003-05-11 20:16:09 +000077/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000078
Daniel Veillard118aed72002-09-24 14:13:13 +000079/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000080
Daniel Veillard4255d502002-04-16 15:50:10 +000081/* #define DEBUG_AUTOMATA 1 */
82
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000083/* #define DEBUG_IDC */
84
85/* #define DEBUG_IDC_NODE_TABLE */
86
87#ifdef DEBUG_IDC
88 #ifndef DEBUG_IDC_NODE_TABLE
89 #define DEBUG_IDC_NODE_TABLE
90 #endif
91#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000092
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000093/* #define ENABLE_PARTICLE_RESTRICTION 1 */
94
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000095#define ENABLE_REDEFINE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000096
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000097/* #define ENABLE_NAMED_LOCALS */
98
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000099/* #define ENABLE_IDC_NODE_TABLES_TEST */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000100
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000101#define DUMP_CONTENT_MODEL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000102
103#ifdef LIBXML_READER_ENABLED
104/* #define XML_SCHEMA_READER_ENABLED */
105#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +0000106
Daniel Veillard4255d502002-04-16 15:50:10 +0000107#define UNBOUNDED (1 << 30)
108#define TODO \
109 xmlGenericError(xmlGenericErrorContext, \
110 "Unimplemented block at %s:%d\n", \
111 __FILE__, __LINE__);
112
William M. Brack2f2a6632004-08-20 23:09:47 +0000113#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +0000114
Daniel Veillard4255d502002-04-16 15:50:10 +0000115/*
116 * The XML Schemas namespaces
117 */
118static const xmlChar *xmlSchemaNs = (const xmlChar *)
119 "http://www.w3.org/2001/XMLSchema";
120
121static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
122 "http://www.w3.org/2001/XMLSchema-instance";
123
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000124static const xmlChar *xmlNamespaceNs = (const xmlChar *)
125 "http://www.w3.org/2000/xmlns/";
126
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000127/*
128* Come casting macros.
129*/
130#define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +0000131#define PCTXT_CAST (xmlSchemaParserCtxtPtr)
132#define VCTXT_CAST (xmlSchemaValidCtxtPtr)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000133#define WXS_BASIC_CAST (xmlSchemaBasicItemPtr)
134#define WXS_TREE_CAST (xmlSchemaTreeItemPtr)
135#define WXS_PTC_CAST (xmlSchemaParticlePtr)
136#define WXS_TYPE_CAST (xmlSchemaTypePtr)
137#define WXS_ELEM_CAST (xmlSchemaElementPtr)
138#define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr)
139#define WXS_ATTR_CAST (xmlSchemaAttributePtr)
140#define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr)
141#define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr)
142#define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr)
143#define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr)
144#define WXS_IDC_CAST (xmlSchemaIDCPtr)
145#define WXS_QNAME_CAST (xmlSchemaQNameRefPtr)
146#define WXS_LIST_CAST (xmlSchemaItemListPtr)
Daniel Veillardc0826a72004-08-10 14:17:33 +0000147
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000148/*
149* Macros to query common properties of components.
150*/
151#define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i))
Daniel Veillard4255d502002-04-16 15:50:10 +0000152
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000153#define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i))
154/*
155* Macros for element declarations.
156*/
157#define WXS_ELEM_TYPEDEF(e) (e)->subtypes
Daniel Veillardc0826a72004-08-10 14:17:33 +0000158
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000159#define WXS_SUBST_HEAD(item) (item)->refDecl
160/*
161* Macros for attribute declarations.
162*/
163#define WXS_ATTR_TYPEDEF(a) (a)->subtypes
164/*
165* Macros for attribute uses.
166*/
167#define WXS_ATTRUSE_DECL(au) WXS_ATTR_CAST (WXS_ATTR_USE_CAST (au))->attrDecl
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000168
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000169#define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000170
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000171#define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name
172
173#define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace
174/*
175* Macros for attribute groups.
176*/
177#define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)
178#define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)
179/*
180* Macros for particles.
181*/
182#define WXS_PARTICLE(p) WXS_PTC_CAST (p)
183
184#define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children
185
186#define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
187/*
188* Macros for model groups definitions.
189*/
190#define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
191/*
192* Macros for model groups.
193*/
194#define WXS_IS_MODEL_GROUP(i) \
195 (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
196 ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
197 ((i)->type == XML_SCHEMA_TYPE_ALL))
198
199#define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
200/*
201* Macros for schema buckets.
202*/
203#define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
204 ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
205
206#define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
207 ((t) == XML_SCHEMA_SCHEMA_IMPORT))
208
209#define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
210
211#define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
212/*
213* Macros for complex/simple types.
214*/
215#define WXS_IS_ANYTYPE(i) \
216 (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
217 ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
218
219#define WXS_IS_COMPLEX(i) \
220 (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
221 ((i)->builtInType == XML_SCHEMAS_ANYTYPE))
222
223#define WXS_IS_SIMPLE(item) \
224 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
225 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000226 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000227
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000228#define WXS_IS_ANY_SIMPLE_TYPE(i) \
229 (((i)->type == XML_SCHEMA_TYPE_BASIC) && \
230 ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000231
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000232#define WXS_IS_RESTRICTION(t) \
233 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000234
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000235#define WXS_IS_EXTENSION(t) \
236 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
237
238#define WXS_IS_TYPE_NOT_FIXED(i) \
239 (((i)->type != XML_SCHEMA_TYPE_BASIC) && \
240 (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
241
242#define WXS_IS_TYPE_NOT_FIXED_1(item) \
243 (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000244 (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000245/*
246* Macros for exclusively for complex types.
247*/
248#define WXS_HAS_COMPLEX_CONTENT(item) \
249 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
250 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000251 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
252
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000253#define WXS_HAS_SIMPLE_CONTENT(item) \
254 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000255 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
256
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000257#define WXS_HAS_MIXED_CONTENT(item) \
258 (item->contentType == XML_SCHEMA_CONTENT_MIXED)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000259
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000260#define WXS_EMPTIABLE(t) \
261 (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000262
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000263#define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000264
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000265#define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000266
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000267#define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
268/*
269* Macros for exclusively for simple types.
270*/
271#define WXS_LIST_ITEMTYPE(t) (t)->subtypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000272
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000273#define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000274
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000275#define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000276
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000277#define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
278/*
279* Misc parser context macros.
280*/
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000281#define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
282
283#define WXS_HAS_BUCKETS(ctx) \
284( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
285(WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
286
287#define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
288
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000289#define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000290
291#define WXS_SCHEMA(ctx) (ctx)->schema
292
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000293#define WXS_ADD_LOCAL(ctx, item) \
294 xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000295
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000296#define WXS_ADD_GLOBAL(ctx, item) \
297 xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000298
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000299#define WXS_ADD_PENDING(ctx, item) \
300 xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
301/*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000302* xmlSchemaItemList macros.
303*/
304#define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0))
305/*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000306* Misc macros.
307*/
308#define IS_SCHEMA(node, type) \
309 ((node != NULL) && (node->ns != NULL) && \
310 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
311 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000312
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000313#define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000314
315/*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000316* Since we put the default/fixed values into the dict, we can
317* use pointer comparison for those values.
318* REMOVED: (xmlStrEqual((v1), (v2)))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000319*/
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000320#define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000321
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000322#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000323
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000324#define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000325
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000326#define HFAILURE if (res == -1) goto exit_failure;
327
328#define HERROR if (res != 0) goto exit_error;
329
330#define HSTOP(ctx) if ((ctx)->stop) goto exit;
331/*
332* Some flags used for various schema constraints.
333*/
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000334#define SUBSET_RESTRICTION 1<<0
335#define SUBSET_EXTENSION 1<<1
336#define SUBSET_SUBSTITUTION 1<<2
337#define SUBSET_LIST 1<<3
338#define SUBSET_UNION 1<<4
339
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000340typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
341typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000342
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000343typedef struct _xmlSchemaItemList xmlSchemaItemList;
344typedef xmlSchemaItemList *xmlSchemaItemListPtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000345struct _xmlSchemaItemList {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000346 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000347 int nbItems; /* used for dynamic addition of schemata */
348 int sizeItems; /* used for dynamic addition of schemata */
349};
350
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000351#define XML_SCHEMA_CTXT_PARSER 1
352#define XML_SCHEMA_CTXT_VALIDATOR 2
353
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000354typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
355typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
356struct _xmlSchemaAbstractCtxt {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000357 int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000358};
359
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000360typedef struct _xmlSchemaBucket xmlSchemaBucket;
361typedef xmlSchemaBucket *xmlSchemaBucketPtr;
362
363#define XML_SCHEMA_SCHEMA_MAIN 0
364#define XML_SCHEMA_SCHEMA_IMPORT 1
365#define XML_SCHEMA_SCHEMA_INCLUDE 2
366#define XML_SCHEMA_SCHEMA_REDEFINE 3
367
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000368/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000369 * xmlSchemaSchemaRelation:
370 *
371 * Used to create a graph of schema relationships.
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000372 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000373typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
374typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
375struct _xmlSchemaSchemaRelation {
376 xmlSchemaSchemaRelationPtr next;
377 int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
378 const xmlChar *importNamespace;
379 xmlSchemaBucketPtr bucket;
380};
381
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000382#define XML_SCHEMA_BUCKET_MARKED 1<<0
383#define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1
384
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000385struct _xmlSchemaBucket {
386 int type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000387 int flags;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000388 const xmlChar *schemaLocation;
389 const xmlChar *origTargetNamespace;
390 const xmlChar *targetNamespace;
391 xmlDocPtr doc;
392 xmlSchemaSchemaRelationPtr relations;
393 int located;
394 int parsed;
395 int imported;
396 int preserveDoc;
397 xmlSchemaItemListPtr globals; /* Global components. */
398 xmlSchemaItemListPtr locals; /* Local components. */
399};
400
401/**
402 * xmlSchemaImport:
403 * (extends xmlSchemaBucket)
404 *
405 * Reflects a schema. Holds some information
406 * about the schema and its toplevel components. Duplicate
407 * toplevel components are not checked at this level.
408 */
409typedef struct _xmlSchemaImport xmlSchemaImport;
410typedef xmlSchemaImport *xmlSchemaImportPtr;
411struct _xmlSchemaImport {
412 int type; /* Main OR import OR include. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000413 int flags;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000414 const xmlChar *schemaLocation; /* The URI of the schema document. */
415 /* For chameleon includes, @origTargetNamespace will be NULL */
416 const xmlChar *origTargetNamespace;
417 /*
418 * For chameleon includes, @targetNamespace will be the
419 * targetNamespace of the including schema.
420 */
421 const xmlChar *targetNamespace;
422 xmlDocPtr doc; /* The schema node-tree. */
423 /* @relations will hold any included/imported/redefined schemas. */
424 xmlSchemaSchemaRelationPtr relations;
425 int located;
426 int parsed;
427 int imported;
428 int preserveDoc;
429 xmlSchemaItemListPtr globals;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000430 xmlSchemaItemListPtr locals;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000431 /* The imported schema. */
432 xmlSchemaPtr schema;
433};
434
435/*
436* (extends xmlSchemaBucket)
437*/
438typedef struct _xmlSchemaInclude xmlSchemaInclude;
439typedef xmlSchemaInclude *xmlSchemaIncludePtr;
440struct _xmlSchemaInclude {
441 int type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000442 int flags;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000443 const xmlChar *schemaLocation;
444 const xmlChar *origTargetNamespace;
445 const xmlChar *targetNamespace;
446 xmlDocPtr doc;
447 xmlSchemaSchemaRelationPtr relations;
448 int located;
449 int parsed;
450 int imported;
451 int preserveDoc;
452 xmlSchemaItemListPtr globals; /* Global components. */
453 xmlSchemaItemListPtr locals; /* Local components. */
454
455 /* The owning main or import schema bucket. */
456 xmlSchemaImportPtr ownerImport;
457};
458
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000459/**
460 * xmlSchemaBasicItem:
461 *
462 * The abstract base type for schema components.
463 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000464typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
465typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
466struct _xmlSchemaBasicItem {
467 xmlSchemaTypeType type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000468};
469
470/**
471 * xmlSchemaAnnotItem:
472 *
473 * The abstract base type for annotated schema components.
474 * (Extends xmlSchemaBasicItem)
475 */
476typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
477typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
478struct _xmlSchemaAnnotItem {
479 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000480 xmlSchemaAnnotPtr annot;
481};
482
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000483/**
484 * xmlSchemaTreeItem:
485 *
486 * The abstract base type for tree-like structured schema components.
487 * (Extends xmlSchemaAnnotItem)
488 */
489typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
490typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
491struct _xmlSchemaTreeItem {
492 xmlSchemaTypeType type;
493 xmlSchemaAnnotPtr annot;
494 xmlSchemaTreeItemPtr next;
495 xmlSchemaTreeItemPtr children;
496};
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000497
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000498
499#define XML_SCHEMA_ATTR_USE_FIXED 1<<0
500/**
501 * xmlSchemaAttributeUsePtr:
502 *
503 * The abstract base type for tree-like structured schema components.
504 * (Extends xmlSchemaTreeItem)
505 */
506typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
507typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
508struct _xmlSchemaAttributeUse {
509 xmlSchemaTypeType type;
510 xmlSchemaAnnotPtr annot;
511 xmlSchemaAttributeUsePtr next; /* The next attr. use. */
512 /*
513 * The attr. decl. OR a QName-ref. to an attr. decl. OR
514 * a QName-ref. to an attribute group definition.
515 */
516 xmlSchemaAttributePtr attrDecl;
517
518 int flags;
519 xmlNodePtr node;
520 int occurs; /* required, optional */
521 const xmlChar * defValue;
522 xmlSchemaValPtr defVal;
523};
524
525/**
526 * xmlSchemaAttributeUseProhibPtr:
527 *
528 * A helper component to reflect attribute prohibitions.
529 * (Extends xmlSchemaBasicItem)
530 */
531typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
532typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
533struct _xmlSchemaAttributeUseProhib {
534 xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
535 xmlNodePtr node;
536 const xmlChar *name;
537 const xmlChar *targetNamespace;
538 int isRef;
539};
540
541/**
542 * xmlSchemaRedef:
543 */
544typedef struct _xmlSchemaRedef xmlSchemaRedef;
545typedef xmlSchemaRedef *xmlSchemaRedefPtr;
546struct _xmlSchemaRedef {
547 xmlSchemaRedefPtr next;
548 xmlSchemaBasicItemPtr item; /* The redefining component. */
549 xmlSchemaBasicItemPtr reference; /* The referencing component. */
550 xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
551 const xmlChar *refName; /* The name of the to-be-redefined component. */
552 const xmlChar *refTargetNs; /* The target namespace of the
553 to-be-redefined comp. */
554 xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
555};
556
557/**
558 * xmlSchemaConstructionCtxt:
559 */
560typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
561typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
562struct _xmlSchemaConstructionCtxt {
563 xmlSchemaPtr mainSchema; /* The main schema. */
564 xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
565 xmlDictPtr dict;
566 xmlSchemaItemListPtr buckets; /* List of schema buckets. */
567 /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
568 xmlSchemaBucketPtr bucket; /* The current schema bucket */
569 xmlSchemaItemListPtr pending; /* All Components of all schemas that
570 need to be fixed. */
571 xmlHashTablePtr substGroups;
572 xmlSchemaRedefPtr redefs;
573 xmlSchemaRedefPtr lastRedef;
574};
575
576#define XML_SCHEMAS_PARSE_ERROR 1
577#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
578
579struct _xmlSchemaParserCtxt {
580 int type;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +0000581 void *errCtxt; /* user specific error context */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000582 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
583 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
584 xmlSchemaValidError err;
585 int nberrors;
586 xmlStructuredErrorFunc serror;
587
588 xmlSchemaConstructionCtxtPtr constructor;
589 int ownsConstructor; /* TODO: Move this to parser *flags*. */
590
591 /* xmlSchemaPtr topschema; */
592 /* xmlHashTablePtr namespaces; */
593
594 xmlSchemaPtr schema; /* The main schema in use */
595 int counter;
596
597 const xmlChar *URL;
598 xmlDocPtr doc;
599 int preserve; /* Whether the doc should be freed */
600
601 const char *buffer;
602 int size;
603
604 /*
605 * Used to build complex element content models
606 */
607 xmlAutomataPtr am;
608 xmlAutomataStatePtr start;
609 xmlAutomataStatePtr end;
610 xmlAutomataStatePtr state;
611
612 xmlDictPtr dict; /* dictionnary for interned string names */
613 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
614 int options;
615 xmlSchemaValidCtxtPtr vctxt;
616 int isS4S;
617 int isRedefine;
618 int xsiAssemble;
619 int stop; /* If the parser should stop; i.e. a critical error. */
620 const xmlChar *targetNamespace;
621 xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
622
623 xmlSchemaRedefPtr redef; /* Used for redefinitions. */
624 int redefCounter; /* Used for redefinitions. */
625 xmlSchemaItemListPtr attrProhibs;
626};
627
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000628/**
629 * xmlSchemaQNameRef:
630 *
631 * A component reference item (not a schema component)
632 * (Extends xmlSchemaBasicItem)
633 */
634typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
635typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
636struct _xmlSchemaQNameRef {
637 xmlSchemaTypeType type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000638 xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000639 xmlSchemaTypeType itemType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000640 const xmlChar *name;
641 const xmlChar *targetNamespace;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000642 xmlNodePtr node;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000643};
644
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000645/**
646 * xmlSchemaParticle:
647 *
648 * A particle component.
649 * (Extends xmlSchemaTreeItem)
650 */
651typedef struct _xmlSchemaParticle xmlSchemaParticle;
652typedef xmlSchemaParticle *xmlSchemaParticlePtr;
653struct _xmlSchemaParticle {
654 xmlSchemaTypeType type;
655 xmlSchemaAnnotPtr annot;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000656 xmlSchemaTreeItemPtr next; /* next particle */
657 xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
658 a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
659 etc.) */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000660 int minOccurs;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000661 int maxOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000662 xmlNodePtr node;
663};
664
665/**
666 * xmlSchemaModelGroup:
667 *
668 * A model group component.
669 * (Extends xmlSchemaTreeItem)
670 */
671typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
672typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
673struct _xmlSchemaModelGroup {
674 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
675 xmlSchemaAnnotPtr annot;
676 xmlSchemaTreeItemPtr next; /* not used */
677 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
678 xmlNodePtr node;
679};
680
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000681#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000682#define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000683/**
684 * xmlSchemaModelGroupDef:
685 *
686 * A model group definition component.
687 * (Extends xmlSchemaTreeItem)
688 */
689typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
690typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
691struct _xmlSchemaModelGroupDef {
692 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
693 xmlSchemaAnnotPtr annot;
694 xmlSchemaTreeItemPtr next; /* not used */
695 xmlSchemaTreeItemPtr children; /* the "model group" */
696 const xmlChar *name;
697 const xmlChar *targetNamespace;
698 xmlNodePtr node;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000699 int flags;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000700};
701
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000702typedef struct _xmlSchemaIDC xmlSchemaIDC;
703typedef xmlSchemaIDC *xmlSchemaIDCPtr;
704
705/**
706 * xmlSchemaIDCSelect:
707 *
708 * The identity-constraint "field" and "selector" item, holding the
709 * XPath expression.
710 */
711typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
712typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000713struct _xmlSchemaIDCSelect {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000714 xmlSchemaIDCSelectPtr next;
715 xmlSchemaIDCPtr idc;
716 int index; /* an index position if significant for IDC key-sequences */
717 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000718 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000719};
720
721/**
722 * xmlSchemaIDC:
723 *
724 * The identity-constraint definition component.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000725 * (Extends xmlSchemaAnnotItem)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000726 */
727
728struct _xmlSchemaIDC {
729 xmlSchemaTypeType type;
730 xmlSchemaAnnotPtr annot;
731 xmlSchemaIDCPtr next;
732 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000733 const xmlChar *name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000734 const xmlChar *targetNamespace;
735 xmlSchemaIDCSelectPtr selector;
736 xmlSchemaIDCSelectPtr fields;
737 int nbFields;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000738 xmlSchemaQNameRefPtr ref;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000739};
740
741/**
742 * xmlSchemaIDCAug:
743 *
744 * The augmented IDC information used for validation.
745 */
746typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
747typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
748struct _xmlSchemaIDCAug {
749 xmlSchemaIDCAugPtr next; /* next in a list */
750 xmlSchemaIDCPtr def; /* the IDC definition */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000751 int keyrefDepth; /* the lowest tree level to which IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000752 tables need to be bubbled upwards */
753};
754
755/**
756 * xmlSchemaPSVIIDCKeySequence:
757 *
758 * The key sequence of a node table item.
759 */
760typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
761typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
762struct _xmlSchemaPSVIIDCKey {
763 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000764 xmlSchemaValPtr val;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000765};
766
767/**
768 * xmlSchemaPSVIIDCNode:
769 *
770 * The node table item of a node table.
771 */
772typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
773typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
774struct _xmlSchemaPSVIIDCNode {
775 xmlNodePtr node;
776 xmlSchemaPSVIIDCKeyPtr *keys;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000777 int nodeLine;
778 int nodeQNameID;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000779
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000780};
781
782/**
783 * xmlSchemaPSVIIDCBinding:
784 *
785 * The identity-constraint binding item of the [identity-constraint table].
786 */
787typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
788typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
789struct _xmlSchemaPSVIIDCBinding {
790 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
791 xmlSchemaIDCPtr definition; /* the IDC definition */
792 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
793 int nbNodes; /* number of entries in the node table */
794 int sizeNodes; /* size of the node table */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000795 xmlSchemaItemListPtr dupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000796};
797
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000798
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000799#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
800#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
801
802#define XPATH_STATE_OBJ_MATCHES -2
803#define XPATH_STATE_OBJ_BLOCKED -3
804
805typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
806typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
807
808/**
809 * xmlSchemaIDCStateObj:
810 *
811 * The state object used to evaluate XPath expressions.
812 */
813typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
814typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
815struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000816 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000817 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000818 int depth; /* depth of creation */
819 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000820 int nbHistory;
821 int sizeHistory;
822 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
823 matcher */
824 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000825 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000826};
827
828#define IDC_MATCHER 0
829
830/**
831 * xmlSchemaIDCMatcher:
832 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000833 * Used to evaluate IDC selectors (and fields).
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000834 */
835struct _xmlSchemaIDCMatcher {
836 int type;
837 int depth; /* the tree depth at creation time */
838 xmlSchemaIDCMatcherPtr next; /* next in the list */
839 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000840 int idcType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000841 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
842 elements */
843 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000844 int targetDepth;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000845 xmlSchemaItemListPtr targets; /* list of target-node
846 (xmlSchemaPSVIIDCNodePtr) entries */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000847};
848
849/*
850* Element info flags.
851*/
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000852#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
853#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
854#define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
855#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
856
857#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
858#define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
859#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
860
861#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
862#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
863#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
864#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000865
866/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000867 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000868 *
869 * Holds information of an element node.
870 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000871struct _xmlSchemaNodeInfo {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000872 int nodeType;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000873 xmlNodePtr node;
874 int nodeLine;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000875 const xmlChar *localName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000876 const xmlChar *nsName;
877 const xmlChar *value;
878 xmlSchemaValPtr val; /* the pre-computed value if any */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000879 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000880
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000881 int flags; /* combination of node info flags */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000882
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000883 int valNeeded;
884 int normVal;
885
886 xmlSchemaElementPtr decl; /* the element/attribute declaration */
887 int depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000888 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
889 for the scope element*/
890 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
891 element */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000892 xmlRegExecCtxtPtr regexCtxt;
893
894 const xmlChar **nsBindings; /* Namespace bindings on this element */
895 int nbNsBindings;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000896 int sizeNsBindings;
897
898 int hasKeyrefs;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +0000899 int appliedXPath; /* Indicates that an XPath has been applied. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000900};
901
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000902#define XML_SCHEMAS_ATTR_UNKNOWN 1
903#define XML_SCHEMAS_ATTR_ASSESSED 2
904#define XML_SCHEMAS_ATTR_PROHIBITED 3
905#define XML_SCHEMAS_ATTR_ERR_MISSING 4
906#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
907#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
908#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
909#define XML_SCHEMAS_ATTR_DEFAULT 8
910#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
911#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
912#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
913#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
914#define XML_SCHEMAS_ATTR_WILD_SKIP 13
915#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
916#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
917#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
918#define XML_SCHEMAS_ATTR_META 17
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000919/*
920* @metaType values of xmlSchemaAttrInfo.
921*/
922#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
923#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
924#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
925#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
926#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000927
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000928typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
929typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
930struct _xmlSchemaAttrInfo {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000931 int nodeType;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000932 xmlNodePtr node;
933 int nodeLine;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000934 const xmlChar *localName;
935 const xmlChar *nsName;
936 const xmlChar *value;
937 xmlSchemaValPtr val; /* the pre-computed value if any */
938 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
939 int flags; /* combination of node info flags */
940
941 xmlSchemaAttributePtr decl; /* the attribute declaration */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000942 xmlSchemaAttributeUsePtr use; /* the attribute use */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000943 int state;
944 int metaType;
945 const xmlChar *vcValue; /* the value constraint value */
946 xmlSchemaNodeInfoPtr parent;
947};
948
949
950#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
Daniel Veillard4255d502002-04-16 15:50:10 +0000951/**
952 * xmlSchemaValidCtxt:
953 *
954 * A Schemas validation context
955 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000956struct _xmlSchemaValidCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000957 int type;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +0000958 void *errCtxt; /* user specific data block */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000959 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000960 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000961 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000962
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000963 xmlSchemaPtr schema; /* The schema in use */
964 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000965 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000966 xmlCharEncoding enc;
967 xmlSAXHandlerPtr sax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000968 xmlParserCtxtPtr parserCtxt;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000969 void *user_data; /* TODO: What is this for? */
Daniel Veillard4255d502002-04-16 15:50:10 +0000970
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000971 int err;
972 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000973
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000974 xmlNodePtr node;
975 xmlNodePtr cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000976 /* xmlSchemaTypePtr type; */
Daniel Veillard4255d502002-04-16 15:50:10 +0000977
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000978 xmlRegExecCtxtPtr regexp;
979 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000980
Daniel Veillardc0826a72004-08-10 14:17:33 +0000981 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000982 int options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000983 xmlNodePtr validationRoot;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000984 xmlSchemaParserCtxtPtr pctxt;
985 int xsiAssemble;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000986
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000987 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000988 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000989 int sizeElemInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000990 xmlSchemaNodeInfoPtr inode; /* the current element information */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000991
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000992 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
993
994 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
995 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000996
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000997 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
998 int nbIdcNodes;
999 int sizeIdcNodes;
1000
1001 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1002 int nbIdcKeys;
1003 int sizeIdcKeys;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001004
1005 int flags;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001006
1007 xmlDictPtr dict;
1008
Daniel Veillard39e5c892005-07-03 22:48:50 +00001009#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001010 xmlTextReaderPtr reader;
Daniel Veillard39e5c892005-07-03 22:48:50 +00001011#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001012
1013 xmlSchemaAttrInfoPtr *attrInfos;
1014 int nbAttrInfos;
1015 int sizeAttrInfos;
1016
1017 int skipDepth;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00001018 xmlSchemaItemListPtr nodeQNames;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00001019 int hasKeyrefs;
1020 int createIDCNodeTables;
1021 int psviExposeIDCNodeTables;
Daniel Veillard4255d502002-04-16 15:50:10 +00001022};
1023
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00001024/**
1025 * xmlSchemaSubstGroup:
1026 *
1027 *
1028 */
1029typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1030typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1031struct _xmlSchemaSubstGroup {
1032 xmlSchemaElementPtr head;
1033 xmlSchemaItemListPtr members;
1034};
1035
Daniel Veillard4255d502002-04-16 15:50:10 +00001036/************************************************************************
1037 * *
1038 * Some predeclarations *
1039 * *
1040 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001041
Daniel Veillardbd2904b2003-11-25 15:38:59 +00001042static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1043 xmlSchemaPtr schema,
1044 xmlNodePtr node);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00001045static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1046 xmlSchemaPtr schema,
1047 xmlNodePtr node);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001048static int
1049xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +00001050 xmlSchemaAbstractCtxtPtr ctxt);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001051static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +00001052xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1053static int
William M. Brack2f2a6632004-08-20 23:09:47 +00001054xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1055 xmlNodePtr node);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001056static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001057xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1058 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +00001059static void
1060xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001061static xmlSchemaWhitespaceValueType
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001062xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001063static xmlSchemaTreeItemPtr
1064xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1065 xmlNodePtr node, xmlSchemaTypeType type,
1066 int withParticle);
1067static const xmlChar *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001068xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001069static xmlSchemaTypeLinkPtr
1070xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001071static void
1072xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1073 const char *funcName,
1074 const char *message);
1075static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +00001076xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001077 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001078 xmlSchemaTypePtr baseType,
1079 int subset);
1080static void
1081xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001082 xmlSchemaParserCtxtPtr ctxt);
1083static void
1084xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001085static xmlSchemaQNameRefPtr
1086xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1087 xmlSchemaPtr schema,
1088 xmlNodePtr node);
William M. Brack87640d52004-04-17 14:58:15 +00001089
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001090/************************************************************************
1091 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001092 * Helper functions *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001093 * *
1094 ************************************************************************/
1095
1096/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001097 * xmlSchemaItemTypeToStr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001098 * @type: the type of the schema item
1099 *
1100 * Returns the component name of a schema item.
1101 */
1102static const xmlChar *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001103xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001104{
1105 switch (type) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001106 case XML_SCHEMA_TYPE_BASIC:
1107 return(BAD_CAST "simple type definition");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001108 case XML_SCHEMA_TYPE_SIMPLE:
1109 return(BAD_CAST "simple type definition");
1110 case XML_SCHEMA_TYPE_COMPLEX:
1111 return(BAD_CAST "complex type definition");
1112 case XML_SCHEMA_TYPE_ELEMENT:
1113 return(BAD_CAST "element declaration");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001114 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1115 return(BAD_CAST "attribute use");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001116 case XML_SCHEMA_TYPE_ATTRIBUTE:
1117 return(BAD_CAST "attribute declaration");
1118 case XML_SCHEMA_TYPE_GROUP:
1119 return(BAD_CAST "model group definition");
1120 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1121 return(BAD_CAST "attribute group definition");
1122 case XML_SCHEMA_TYPE_NOTATION:
1123 return(BAD_CAST "notation declaration");
1124 case XML_SCHEMA_TYPE_SEQUENCE:
1125 return(BAD_CAST "model group (sequence)");
1126 case XML_SCHEMA_TYPE_CHOICE:
1127 return(BAD_CAST "model group (choice)");
1128 case XML_SCHEMA_TYPE_ALL:
1129 return(BAD_CAST "model group (all)");
1130 case XML_SCHEMA_TYPE_PARTICLE:
1131 return(BAD_CAST "particle");
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001132 case XML_SCHEMA_TYPE_IDC_UNIQUE:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001133 return(BAD_CAST "unique identity-constraint");
1134 /* return(BAD_CAST "IDC (unique)"); */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001135 case XML_SCHEMA_TYPE_IDC_KEY:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001136 return(BAD_CAST "key identity-constraint");
1137 /* return(BAD_CAST "IDC (key)"); */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001138 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001139 return(BAD_CAST "keyref identity-constraint");
1140 /* return(BAD_CAST "IDC (keyref)"); */
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00001141 case XML_SCHEMA_TYPE_ANY:
1142 return(BAD_CAST "wildcard (any)");
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001143 case XML_SCHEMA_EXTRA_QNAMEREF:
1144 return(BAD_CAST "[helper component] QName reference");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001145 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1146 return(BAD_CAST "[helper component] attribute use prohibition");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001147 default:
1148 return(BAD_CAST "Not a schema component");
1149 }
1150}
1151
1152/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001153 * xmlSchemaGetComponentTypeStr:
1154 * @type: the type of the schema item
1155 *
1156 * Returns the component name of a schema item.
1157 */
1158static const xmlChar *
1159xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1160{
1161 switch (item->type) {
1162 case XML_SCHEMA_TYPE_BASIC:
1163 if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1164 return(BAD_CAST "complex type definition");
1165 else
1166 return(BAD_CAST "simple type definition");
1167 default:
1168 return(xmlSchemaItemTypeToStr(item->type));
1169 }
1170}
1171
1172/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001173 * xmlSchemaGetComponentNode:
1174 * @item: a schema component
1175 *
1176 * Returns node associated with the schema component.
1177 * NOTE that such a node need not be available; plus, a component's
1178 * node need not to reflect the component directly, since there is no
1179 * one-to-one relationship between the XML Schema representation and
1180 * the component representation.
1181 */
1182static xmlNodePtr
1183xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1184{
1185 switch (item->type) {
1186 case XML_SCHEMA_TYPE_ELEMENT:
1187 return (((xmlSchemaElementPtr) item)->node);
1188 case XML_SCHEMA_TYPE_ATTRIBUTE:
1189 return (((xmlSchemaAttributePtr) item)->node);
1190 case XML_SCHEMA_TYPE_COMPLEX:
1191 case XML_SCHEMA_TYPE_SIMPLE:
1192 return (((xmlSchemaTypePtr) item)->node);
1193 case XML_SCHEMA_TYPE_ANY:
1194 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1195 return (((xmlSchemaWildcardPtr) item)->node);
1196 case XML_SCHEMA_TYPE_PARTICLE:
1197 return (((xmlSchemaParticlePtr) item)->node);
1198 case XML_SCHEMA_TYPE_SEQUENCE:
1199 case XML_SCHEMA_TYPE_CHOICE:
1200 case XML_SCHEMA_TYPE_ALL:
1201 return (((xmlSchemaModelGroupPtr) item)->node);
1202 case XML_SCHEMA_TYPE_GROUP:
1203 return (((xmlSchemaModelGroupDefPtr) item)->node);
1204 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1205 return (((xmlSchemaAttributeGroupPtr) item)->node);
1206 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1207 case XML_SCHEMA_TYPE_IDC_KEY:
1208 case XML_SCHEMA_TYPE_IDC_KEYREF:
1209 return (((xmlSchemaIDCPtr) item)->node);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001210 case XML_SCHEMA_EXTRA_QNAMEREF:
1211 return(((xmlSchemaQNameRefPtr) item)->node);
1212 /* TODO: What to do with NOTATIONs?
1213 case XML_SCHEMA_TYPE_NOTATION:
1214 return (((xmlSchemaNotationPtr) item)->node);
1215 */
1216 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1217 return (((xmlSchemaAttributeUsePtr) item)->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001218 default:
1219 return (NULL);
1220 }
1221}
1222
1223#if 0
1224/**
1225 * xmlSchemaGetNextComponent:
1226 * @item: a schema component
1227 *
1228 * Returns the next sibling of the schema component.
1229 */
1230static xmlSchemaBasicItemPtr
1231xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1232{
1233 switch (item->type) {
1234 case XML_SCHEMA_TYPE_ELEMENT:
1235 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1236 case XML_SCHEMA_TYPE_ATTRIBUTE:
1237 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1238 case XML_SCHEMA_TYPE_COMPLEX:
1239 case XML_SCHEMA_TYPE_SIMPLE:
1240 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1241 case XML_SCHEMA_TYPE_ANY:
1242 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1243 return (NULL);
1244 case XML_SCHEMA_TYPE_PARTICLE:
1245 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1246 case XML_SCHEMA_TYPE_SEQUENCE:
1247 case XML_SCHEMA_TYPE_CHOICE:
1248 case XML_SCHEMA_TYPE_ALL:
1249 return (NULL);
1250 case XML_SCHEMA_TYPE_GROUP:
1251 return (NULL);
1252 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1253 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1254 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1255 case XML_SCHEMA_TYPE_IDC_KEY:
1256 case XML_SCHEMA_TYPE_IDC_KEYREF:
1257 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1258 default:
1259 return (NULL);
1260 }
1261}
1262#endif
1263
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001264
1265/**
1266 * xmlSchemaFormatQName:
1267 * @buf: the string buffer
1268 * @namespaceName: the namespace name
1269 * @localName: the local name
1270 *
1271 * Returns the given QName in the format "{namespaceName}localName" or
1272 * just "localName" if @namespaceName is NULL.
1273 *
1274 * Returns the localName if @namespaceName is NULL, a formatted
1275 * string otherwise.
1276 */
1277static const xmlChar*
1278xmlSchemaFormatQName(xmlChar **buf,
1279 const xmlChar *namespaceName,
1280 const xmlChar *localName)
1281{
1282 FREE_AND_NULL(*buf)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001283 if (namespaceName != NULL) {
1284 *buf = xmlStrdup(BAD_CAST "{");
1285 *buf = xmlStrcat(*buf, namespaceName);
1286 *buf = xmlStrcat(*buf, BAD_CAST "}");
1287 }
1288 if (localName != NULL) {
1289 if (namespaceName == NULL)
1290 return(localName);
1291 *buf = xmlStrcat(*buf, localName);
1292 } else {
1293 *buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
1294 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001295 return ((const xmlChar *) *buf);
1296}
1297
1298static const xmlChar*
1299xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1300{
1301 if (ns != NULL)
1302 return (xmlSchemaFormatQName(buf, ns->href, localName));
1303 else
1304 return (xmlSchemaFormatQName(buf, NULL, localName));
1305}
1306
1307static const xmlChar *
1308xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1309{
1310 switch (item->type) {
1311 case XML_SCHEMA_TYPE_ELEMENT:
1312 return (((xmlSchemaElementPtr) item)->name);
1313 case XML_SCHEMA_TYPE_ATTRIBUTE:
1314 return (((xmlSchemaAttributePtr) item)->name);
1315 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1316 return (((xmlSchemaAttributeGroupPtr) item)->name);
1317 case XML_SCHEMA_TYPE_BASIC:
1318 case XML_SCHEMA_TYPE_SIMPLE:
1319 case XML_SCHEMA_TYPE_COMPLEX:
1320 return (((xmlSchemaTypePtr) item)->name);
1321 case XML_SCHEMA_TYPE_GROUP:
1322 return (((xmlSchemaModelGroupDefPtr) item)->name);
1323 case XML_SCHEMA_TYPE_IDC_KEY:
1324 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1325 case XML_SCHEMA_TYPE_IDC_KEYREF:
1326 return (((xmlSchemaIDCPtr) item)->name);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001327 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1328 if (WXS_ATTRUSE_DECL(item) != NULL) {
1329 return(xmlSchemaGetComponentName(
1330 WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1331 } else
1332 return(NULL);
1333 case XML_SCHEMA_EXTRA_QNAMEREF:
1334 return (((xmlSchemaQNameRefPtr) item)->name);
1335 case XML_SCHEMA_TYPE_NOTATION:
1336 return (((xmlSchemaNotationPtr) item)->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001337 default:
1338 /*
1339 * Other components cannot have names.
1340 */
1341 break;
1342 }
1343 return (NULL);
1344}
1345
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001346#define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1347#define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1348/*
1349static const xmlChar *
1350xmlSchemaGetQNameRefName(void *ref)
1351{
1352 return(((xmlSchemaQNameRefPtr) ref)->name);
1353}
1354
1355static const xmlChar *
1356xmlSchemaGetQNameRefTargetNs(void *ref)
1357{
1358 return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1359}
1360*/
1361
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001362static const xmlChar *
1363xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1364{
1365 switch (item->type) {
1366 case XML_SCHEMA_TYPE_ELEMENT:
1367 return (((xmlSchemaElementPtr) item)->targetNamespace);
1368 case XML_SCHEMA_TYPE_ATTRIBUTE:
1369 return (((xmlSchemaAttributePtr) item)->targetNamespace);
1370 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1371 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1372 case XML_SCHEMA_TYPE_BASIC:
1373 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1374 case XML_SCHEMA_TYPE_SIMPLE:
1375 case XML_SCHEMA_TYPE_COMPLEX:
1376 return (((xmlSchemaTypePtr) item)->targetNamespace);
1377 case XML_SCHEMA_TYPE_GROUP:
1378 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1379 case XML_SCHEMA_TYPE_IDC_KEY:
1380 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1381 case XML_SCHEMA_TYPE_IDC_KEYREF:
1382 return (((xmlSchemaIDCPtr) item)->targetNamespace);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001383 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1384 if (WXS_ATTRUSE_DECL(item) != NULL) {
1385 return(xmlSchemaGetComponentTargetNs(
1386 WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1387 }
1388 /* TODO: Will returning NULL break something? */
1389 break;
1390 case XML_SCHEMA_EXTRA_QNAMEREF:
1391 return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1392 case XML_SCHEMA_TYPE_NOTATION:
1393 return (((xmlSchemaNotationPtr) item)->targetNamespace);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001394 default:
1395 /*
1396 * Other components cannot have names.
1397 */
1398 break;
1399 }
1400 return (NULL);
1401}
1402
1403static const xmlChar*
1404xmlSchemaGetComponentQName(xmlChar **buf,
1405 void *item)
1406{
1407 return (xmlSchemaFormatQName(buf,
1408 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1409 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1410}
1411
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001412static const xmlChar*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001413xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001414{
1415 xmlChar *str = NULL;
1416
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001417 *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001418 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001419 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1420 (xmlSchemaBasicItemPtr) item));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001421 *buf = xmlStrcat(*buf, BAD_CAST "'");
1422 FREE_AND_NULL(str);
1423 return(*buf);
1424}
1425
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001426static const xmlChar*
1427xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1428{
1429 return(xmlSchemaGetComponentDesignation(buf, idc));
1430}
1431
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001432/**
1433 * xmlSchemaWildcardPCToString:
1434 * @pc: the type of processContents
1435 *
1436 * Returns a string representation of the type of
1437 * processContents.
1438 */
1439static const xmlChar *
1440xmlSchemaWildcardPCToString(int pc)
1441{
1442 switch (pc) {
1443 case XML_SCHEMAS_ANY_SKIP:
1444 return (BAD_CAST "skip");
1445 case XML_SCHEMAS_ANY_LAX:
1446 return (BAD_CAST "lax");
1447 case XML_SCHEMAS_ANY_STRICT:
1448 return (BAD_CAST "strict");
1449 default:
1450 return (BAD_CAST "invalid process contents");
1451 }
1452}
1453
1454/**
1455 * xmlSchemaGetCanonValueWhtspExt:
1456 * @val: the precomputed value
1457 * @retValue: the returned value
1458 * @ws: the whitespace type of the value
1459 *
1460 * Get a the cononical representation of the value.
1461 * The caller has to free the returned retValue.
1462 *
1463 * Returns 0 if the value could be built and -1 in case of
1464 * API errors or if the value type is not supported yet.
1465 */
1466static int
1467xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1468 xmlSchemaWhitespaceValueType ws,
1469 xmlChar **retValue)
1470{
1471 int list;
1472 xmlSchemaValType valType;
1473 const xmlChar *value, *value2 = NULL;
1474
1475
1476 if ((retValue == NULL) || (val == NULL))
1477 return (-1);
1478 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1479 *retValue = NULL;
1480 do {
1481 value = NULL;
1482 valType = xmlSchemaGetValType(val);
1483 switch (valType) {
1484 case XML_SCHEMAS_STRING:
1485 case XML_SCHEMAS_NORMSTRING:
1486 case XML_SCHEMAS_ANYSIMPLETYPE:
1487 value = xmlSchemaValueGetAsString(val);
1488 if (value != NULL) {
1489 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1490 value2 = xmlSchemaCollapseString(value);
1491 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1492 value2 = xmlSchemaWhiteSpaceReplace(value);
1493 if (value2 != NULL)
1494 value = value2;
1495 }
1496 break;
1497 default:
1498 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1499 if (value2 != NULL)
1500 xmlFree((xmlChar *) value2);
1501 goto internal_error;
1502 }
1503 value = value2;
1504 }
1505 if (*retValue == NULL)
1506 if (value == NULL) {
1507 if (! list)
1508 *retValue = xmlStrdup(BAD_CAST "");
1509 } else
1510 *retValue = xmlStrdup(value);
1511 else if (value != NULL) {
1512 /* List. */
1513 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1514 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1515 }
1516 FREE_AND_NULL(value2)
1517 val = xmlSchemaValueGetNext(val);
1518 } while (val != NULL);
1519
1520 return (0);
1521internal_error:
1522 if (*retValue != NULL)
1523 xmlFree((xmlChar *) (*retValue));
1524 if (value2 != NULL)
1525 xmlFree((xmlChar *) value2);
1526 return (-1);
1527}
1528
1529/**
1530 * xmlSchemaFormatItemForReport:
1531 * @buf: the string buffer
1532 * @itemDes: the designation of the item
1533 * @itemName: the name of the item
1534 * @item: the item as an object
1535 * @itemNode: the node of the item
1536 * @local: the local name
1537 * @parsing: if the function is used during the parse
1538 *
1539 * Returns a representation of the given item used
1540 * for error reports.
1541 *
1542 * The following order is used to build the resulting
1543 * designation if the arguments are not NULL:
1544 * 1a. If itemDes not NULL -> itemDes
1545 * 1b. If (itemDes not NULL) and (itemName not NULL)
1546 * -> itemDes + itemName
1547 * 2. If the preceding was NULL and (item not NULL) -> item
1548 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1549 *
1550 * If the itemNode is an attribute node, the name of the attribute
1551 * will be appended to the result.
1552 *
1553 * Returns the formatted string and sets @buf to the resulting value.
1554 */
1555static xmlChar*
1556xmlSchemaFormatItemForReport(xmlChar **buf,
1557 const xmlChar *itemDes,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001558 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001559 xmlNodePtr itemNode)
1560{
1561 xmlChar *str = NULL;
1562 int named = 1;
1563
1564 if (*buf != NULL) {
1565 xmlFree(*buf);
1566 *buf = NULL;
1567 }
1568
1569 if (itemDes != NULL) {
1570 *buf = xmlStrdup(itemDes);
1571 } else if (item != NULL) {
1572 switch (item->type) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001573 case XML_SCHEMA_TYPE_BASIC: {
1574 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1575
1576 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001577 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001578 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001579 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001580 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001581 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1582 else
1583 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001584 *buf = xmlStrcat(*buf, type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001585 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001586 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001587 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001588 case XML_SCHEMA_TYPE_SIMPLE: {
1589 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1590
1591 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001592 *buf = xmlStrdup(BAD_CAST"");
1593 } else {
1594 *buf = xmlStrdup(BAD_CAST "local ");
1595 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001596 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001597 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001598 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001599 *buf = xmlStrcat(*buf, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001600 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001601 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1602 else
1603 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001604 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001605 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001606 *buf = xmlStrcat(*buf, type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001607 *buf = xmlStrcat(*buf, BAD_CAST "'");
1608 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001609 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001610 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001611 case XML_SCHEMA_TYPE_COMPLEX: {
1612 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1613
1614 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001615 *buf = xmlStrdup(BAD_CAST "");
1616 else
1617 *buf = xmlStrdup(BAD_CAST "local ");
1618 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001619 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001620 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001621 *buf = xmlStrcat(*buf, type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001622 *buf = xmlStrcat(*buf, BAD_CAST "'");
1623 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001624 }
1625 break;
1626 case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1627 xmlSchemaAttributeUsePtr ause;
1628
1629 ause = WXS_ATTR_USE_CAST item;
1630 *buf = xmlStrdup(BAD_CAST "attribute use ");
1631 if (WXS_ATTRUSE_DECL(ause) != NULL) {
1632 *buf = xmlStrcat(*buf, BAD_CAST "'");
1633 *buf = xmlStrcat(*buf,
1634 xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1635 FREE_AND_NULL(str)
1636 *buf = xmlStrcat(*buf, BAD_CAST "'");
1637 } else {
1638 *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1639 }
1640 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001641 break;
1642 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1643 xmlSchemaAttributePtr attr;
1644
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001645 attr = (xmlSchemaAttributePtr) item;
1646 *buf = xmlStrdup(BAD_CAST "attribute decl.");
1647 *buf = xmlStrcat(*buf, BAD_CAST " '");
1648 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1649 attr->targetNamespace, attr->name));
1650 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001651 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001652 }
1653 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001654 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1655 xmlSchemaGetComponentDesignation(buf, item);
1656 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001657 case XML_SCHEMA_TYPE_ELEMENT: {
1658 xmlSchemaElementPtr elem;
1659
1660 elem = (xmlSchemaElementPtr) item;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001661 *buf = xmlStrdup(BAD_CAST "element decl.");
1662 *buf = xmlStrcat(*buf, BAD_CAST " '");
1663 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1664 elem->targetNamespace, elem->name));
1665 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001666 }
1667 break;
1668 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1669 case XML_SCHEMA_TYPE_IDC_KEY:
1670 case XML_SCHEMA_TYPE_IDC_KEYREF:
1671 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1672 *buf = xmlStrdup(BAD_CAST "unique '");
1673 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1674 *buf = xmlStrdup(BAD_CAST "key '");
1675 else
1676 *buf = xmlStrdup(BAD_CAST "keyRef '");
1677 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1678 *buf = xmlStrcat(*buf, BAD_CAST "'");
1679 break;
1680 case XML_SCHEMA_TYPE_ANY:
1681 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1682 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1683 ((xmlSchemaWildcardPtr) item)->processContents));
1684 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1685 break;
1686 case XML_SCHEMA_FACET_MININCLUSIVE:
1687 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1688 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1689 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1690 case XML_SCHEMA_FACET_TOTALDIGITS:
1691 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1692 case XML_SCHEMA_FACET_PATTERN:
1693 case XML_SCHEMA_FACET_ENUMERATION:
1694 case XML_SCHEMA_FACET_WHITESPACE:
1695 case XML_SCHEMA_FACET_LENGTH:
1696 case XML_SCHEMA_FACET_MAXLENGTH:
1697 case XML_SCHEMA_FACET_MINLENGTH:
1698 *buf = xmlStrdup(BAD_CAST "facet '");
1699 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1700 *buf = xmlStrcat(*buf, BAD_CAST "'");
1701 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001702 case XML_SCHEMA_TYPE_GROUP: {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001703 *buf = xmlStrdup(BAD_CAST "model group def.");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001704 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001705 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001706 *buf = xmlStrcat(*buf, BAD_CAST "'");
1707 FREE_AND_NULL(str)
1708 }
1709 break;
1710 case XML_SCHEMA_TYPE_SEQUENCE:
1711 case XML_SCHEMA_TYPE_CHOICE:
1712 case XML_SCHEMA_TYPE_ALL:
1713 case XML_SCHEMA_TYPE_PARTICLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001714 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1715 break;
1716 case XML_SCHEMA_TYPE_NOTATION: {
1717 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1718 *buf = xmlStrcat(*buf, BAD_CAST " '");
1719 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1720 *buf = xmlStrcat(*buf, BAD_CAST "'");
1721 FREE_AND_NULL(str);
1722 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001723 default:
1724 named = 0;
1725 }
1726 } else
1727 named = 0;
1728
1729 if ((named == 0) && (itemNode != NULL)) {
1730 xmlNodePtr elem;
1731
1732 if (itemNode->type == XML_ATTRIBUTE_NODE)
1733 elem = itemNode->parent;
1734 else
1735 elem = itemNode;
1736 *buf = xmlStrdup(BAD_CAST "Element '");
1737 if (elem->ns != NULL) {
1738 *buf = xmlStrcat(*buf,
1739 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1740 FREE_AND_NULL(str)
1741 } else
1742 *buf = xmlStrcat(*buf, elem->name);
1743 *buf = xmlStrcat(*buf, BAD_CAST "'");
1744
1745 }
1746 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1747 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1748 if (itemNode->ns != NULL) {
1749 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1750 itemNode->ns->href, itemNode->name));
1751 FREE_AND_NULL(str)
1752 } else
1753 *buf = xmlStrcat(*buf, itemNode->name);
1754 *buf = xmlStrcat(*buf, BAD_CAST "'");
1755 }
1756 FREE_AND_NULL(str)
1757
1758 return (*buf);
1759}
1760
1761/**
1762 * xmlSchemaFormatFacetEnumSet:
1763 * @buf: the string buffer
1764 * @type: the type holding the enumeration facets
1765 *
1766 * Builds a string consisting of all enumeration elements.
1767 *
1768 * Returns a string of all enumeration elements.
1769 */
1770static const xmlChar *
1771xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1772 xmlChar **buf, xmlSchemaTypePtr type)
1773{
1774 xmlSchemaFacetPtr facet;
1775 xmlSchemaWhitespaceValueType ws;
1776 xmlChar *value = NULL;
1777 int res;
1778
1779 if (*buf != NULL)
1780 xmlFree(*buf);
1781 *buf = NULL;
1782
1783 do {
1784 /*
1785 * Use the whitespace type of the base type.
1786 */
1787 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1788 for (facet = type->facets; facet != NULL; facet = facet->next) {
1789 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1790 continue;
1791 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1792 ws, &value);
1793 if (res == -1) {
1794 xmlSchemaInternalErr(actxt,
1795 "xmlSchemaFormatFacetEnumSet",
1796 "compute the canonical lexical representation");
1797 if (*buf != NULL)
1798 xmlFree(*buf);
1799 *buf = NULL;
1800 return (NULL);
1801 }
1802 if (*buf == NULL)
1803 *buf = xmlStrdup(BAD_CAST "'");
1804 else
1805 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1806 *buf = xmlStrcat(*buf, BAD_CAST value);
1807 *buf = xmlStrcat(*buf, BAD_CAST "'");
1808 if (value != NULL) {
1809 xmlFree((xmlChar *)value);
1810 value = NULL;
1811 }
1812 }
1813 type = type->baseType;
1814 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1815
1816 return ((const xmlChar *) *buf);
1817}
1818
1819/************************************************************************
1820 * *
1821 * Error functions *
1822 * *
1823 ************************************************************************/
1824
1825#if 0
1826static void
1827xmlSchemaErrMemory(const char *msg)
1828{
1829 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1830 msg);
1831}
1832#endif
1833
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001834static void
1835xmlSchemaPSimpleErr(const char *msg)
1836{
1837 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1838 msg);
1839}
1840
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001841/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001842 * xmlSchemaPErrMemory:
1843 * @node: a context node
1844 * @extra: extra informations
1845 *
1846 * Handle an out of memory condition
1847 */
1848static void
1849xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1850 const char *extra, xmlNodePtr node)
1851{
1852 if (ctxt != NULL)
1853 ctxt->nberrors++;
1854 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1855 extra);
1856}
1857
1858/**
1859 * xmlSchemaPErr:
1860 * @ctxt: the parsing context
1861 * @node: the context node
1862 * @error: the error code
1863 * @msg: the error message
1864 * @str1: extra data
1865 * @str2: extra data
1866 *
1867 * Handle a parser error
1868 */
1869static void
1870xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1871 const char *msg, const xmlChar * str1, const xmlChar * str2)
1872{
1873 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001874 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001875 void *data = NULL;
1876
1877 if (ctxt != NULL) {
1878 ctxt->nberrors++;
Kasimier T. Buchcik940ab0c2005-10-19 17:00:53 +00001879 ctxt->err = error;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001880 channel = ctxt->error;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00001881 data = ctxt->errCtxt;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001882 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001883 }
Daniel Veillard659e71e2003-10-10 14:10:40 +00001884 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001885 error, XML_ERR_ERROR, NULL, 0,
1886 (const char *) str1, (const char *) str2, NULL, 0, 0,
1887 msg, str1, str2);
1888}
1889
1890/**
1891 * xmlSchemaPErr2:
1892 * @ctxt: the parsing context
1893 * @node: the context node
1894 * @node: the current child
1895 * @error: the error code
1896 * @msg: the error message
1897 * @str1: extra data
1898 * @str2: extra data
1899 *
1900 * Handle a parser error
1901 */
1902static void
1903xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1904 xmlNodePtr child, int error,
1905 const char *msg, const xmlChar * str1, const xmlChar * str2)
1906{
1907 if (child != NULL)
1908 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1909 else
1910 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1911}
1912
Daniel Veillard01fa6152004-06-29 17:04:39 +00001913
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001914/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001915 * xmlSchemaPErrExt:
1916 * @ctxt: the parsing context
1917 * @node: the context node
1918 * @error: the error code
1919 * @strData1: extra data
1920 * @strData2: extra data
1921 * @strData3: extra data
1922 * @msg: the message
1923 * @str1: extra parameter for the message display
1924 * @str2: extra parameter for the message display
1925 * @str3: extra parameter for the message display
1926 * @str4: extra parameter for the message display
1927 * @str5: extra parameter for the message display
1928 *
1929 * Handle a parser error
1930 */
1931static void
1932xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1933 const xmlChar * strData1, const xmlChar * strData2,
1934 const xmlChar * strData3, const char *msg, const xmlChar * str1,
1935 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1936 const xmlChar * str5)
1937{
1938
1939 xmlGenericErrorFunc channel = NULL;
1940 xmlStructuredErrorFunc schannel = NULL;
1941 void *data = NULL;
1942
1943 if (ctxt != NULL) {
1944 ctxt->nberrors++;
Kasimier T. Buchcik940ab0c2005-10-19 17:00:53 +00001945 ctxt->err = error;
Daniel Veillard3646d642004-06-02 19:19:14 +00001946 channel = ctxt->error;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00001947 data = ctxt->errCtxt;
Daniel Veillard3646d642004-06-02 19:19:14 +00001948 schannel = ctxt->serror;
1949 }
1950 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1951 error, XML_ERR_ERROR, NULL, 0,
1952 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +00001953 (const char *) strData3, 0, 0, msg, str1, str2,
1954 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +00001955}
Daniel Veillard01fa6152004-06-29 17:04:39 +00001956
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001957/************************************************************************
1958 * *
1959 * Allround error functions *
1960 * *
1961 ************************************************************************/
Daniel Veillard3646d642004-06-02 19:19:14 +00001962
1963/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001964 * xmlSchemaVTypeErrMemory:
1965 * @node: a context node
1966 * @extra: extra informations
1967 *
1968 * Handle an out of memory condition
1969 */
1970static void
1971xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1972 const char *extra, xmlNodePtr node)
1973{
1974 if (ctxt != NULL) {
1975 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001976 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001977 }
1978 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1979 extra);
1980}
1981
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001982static void
1983xmlSchemaPSimpleInternalErr(xmlNodePtr node,
1984 const char *msg, const xmlChar *str)
1985{
1986 __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
1987 msg, (const char *) str);
1988}
1989
1990#define WXS_ERROR_TYPE_ERROR 1
1991#define WXS_ERROR_TYPE_WARNING 2
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001992/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001993 * xmlSchemaErr3:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001994 * @ctxt: the validation context
1995 * @node: the context node
1996 * @error: the error code
1997 * @msg: the error message
1998 * @str1: extra data
1999 * @str2: extra data
2000 * @str3: extra data
2001 *
2002 * Handle a validation error
2003 */
2004static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002005xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002006 xmlErrorLevel errorLevel,
2007 int error, xmlNodePtr node, int line, const char *msg,
2008 const xmlChar *str1, const xmlChar *str2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002009 const xmlChar *str3, const xmlChar *str4)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002010{
Daniel Veillard659e71e2003-10-10 14:10:40 +00002011 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002012 xmlGenericErrorFunc channel = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002013 void *data = NULL;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002014
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002015 if (ctxt != NULL) {
2016 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2017 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
Daniel Veillard971771e2005-07-09 17:32:57 +00002018 const char *file = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002019 if (errorLevel != XML_ERR_WARNING) {
2020 vctxt->nberrors++;
2021 vctxt->err = error;
2022 channel = vctxt->error;
2023 } else {
2024 channel = vctxt->warning;
2025 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002026 schannel = vctxt->serror;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00002027 data = vctxt->errCtxt;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002028
2029 /*
2030 * Error node. If we specify a line number, then
2031 * do not channel any node to the error function.
2032 */
2033 if (line == 0) {
2034 if ((node == NULL) &&
2035 (vctxt->depth >= 0) &&
2036 (vctxt->inode != NULL)) {
2037 node = vctxt->inode->node;
2038 }
2039 /*
2040 * Get filename and line if no node-tree.
2041 */
2042 if ((node == NULL) &&
2043 (vctxt->parserCtxt != NULL) &&
2044 (vctxt->parserCtxt->input != NULL)) {
2045 file = vctxt->parserCtxt->input->filename;
2046 line = vctxt->parserCtxt->input->line;
2047 }
2048 } else {
2049 /*
2050 * Override the given node's (if any) position
2051 * and channel only the given line number.
2052 */
2053 node = NULL;
2054 /*
2055 * Get filename.
2056 */
2057 if (vctxt->doc != NULL)
2058 file = (const char *) vctxt->doc->URL;
2059 else if ((vctxt->parserCtxt != NULL) &&
2060 (vctxt->parserCtxt->input != NULL))
2061 file = vctxt->parserCtxt->input->filename;
2062 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002063 __xmlRaiseError(schannel, channel, data, ctxt,
2064 node, XML_FROM_SCHEMASV,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002065 error, errorLevel, file, line,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002066 (const char *) str1, (const char *) str2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002067 (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002068
2069 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2070 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002071 if (errorLevel != XML_ERR_WARNING) {
2072 pctxt->nberrors++;
2073 pctxt->err = error;
2074 channel = pctxt->error;
2075 } else {
2076 channel = pctxt->warning;
2077 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002078 schannel = pctxt->serror;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00002079 data = pctxt->errCtxt;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002080 __xmlRaiseError(schannel, channel, data, ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002081 node, XML_FROM_SCHEMASP, error,
2082 errorLevel, NULL, 0,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002083 (const char *) str1, (const char *) str2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002084 (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002085 } else {
2086 TODO
2087 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002088 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002089}
2090
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002091/**
2092 * xmlSchemaErr3:
2093 * @ctxt: the validation context
2094 * @node: the context node
2095 * @error: the error code
2096 * @msg: the error message
2097 * @str1: extra data
2098 * @str2: extra data
2099 * @str3: extra data
2100 *
2101 * Handle a validation error
2102 */
2103static void
2104xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2105 int error, xmlNodePtr node, const char *msg,
2106 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2107{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002108 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2109 msg, str1, str2, str3, NULL);
2110}
2111
2112static void
2113xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2114 int error, xmlNodePtr node, const char *msg,
2115 const xmlChar *str1, const xmlChar *str2,
2116 const xmlChar *str3, const xmlChar *str4)
2117{
2118 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2119 msg, str1, str2, str3, str4);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002120}
2121
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002122static void
2123xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2124 int error, xmlNodePtr node, const char *msg,
2125 const xmlChar *str1, const xmlChar *str2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002126{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002127 xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002128}
2129
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002130static xmlChar *
2131xmlSchemaFormatNodeForError(xmlChar ** msg,
2132 xmlSchemaAbstractCtxtPtr actxt,
2133 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002134{
2135 xmlChar *str = NULL;
2136
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002137 *msg = NULL;
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +00002138 if ((node != NULL) &&
2139 (node->type != XML_ELEMENT_NODE) &&
2140 (node->type != XML_ATTRIBUTE_NODE))
2141 {
2142 /*
2143 * Don't try to format other nodes than element and
2144 * attribute nodes.
2145 * Play save and return an empty string.
2146 */
2147 *msg = xmlStrdup(BAD_CAST "");
2148 return(*msg);
2149 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002150 if (node != NULL) {
2151 /*
2152 * Work on tree nodes.
2153 */
2154 if (node->type == XML_ATTRIBUTE_NODE) {
2155 xmlNodePtr elem = node->parent;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002156
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002157 *msg = xmlStrdup(BAD_CAST "Element '");
2158 if (elem->ns != NULL)
2159 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2160 elem->ns->href, elem->name));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002161 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002162 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2163 NULL, elem->name));
2164 FREE_AND_NULL(str);
2165 *msg = xmlStrcat(*msg, BAD_CAST "', ");
2166 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2167 } else {
2168 *msg = xmlStrdup(BAD_CAST "Element '");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002169 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002170 if (node->ns != NULL)
2171 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2172 node->ns->href, node->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002173 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002174 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2175 NULL, node->name));
2176 FREE_AND_NULL(str);
2177 *msg = xmlStrcat(*msg, BAD_CAST "': ");
2178 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2179 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2180 /*
2181 * Work on node infos.
2182 */
2183 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2184 xmlSchemaNodeInfoPtr ielem =
2185 vctxt->elemInfos[vctxt->depth];
2186
2187 *msg = xmlStrdup(BAD_CAST "Element '");
2188 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2189 ielem->nsName, ielem->localName));
2190 FREE_AND_NULL(str);
2191 *msg = xmlStrcat(*msg, BAD_CAST "', ");
2192 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2193 } else {
2194 *msg = xmlStrdup(BAD_CAST "Element '");
2195 }
2196 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2197 vctxt->inode->nsName, vctxt->inode->localName));
2198 FREE_AND_NULL(str);
2199 *msg = xmlStrcat(*msg, BAD_CAST "': ");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002200 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2201 /*
2202 * Hmm, no node while parsing?
2203 * Return an empty string, in case NULL will break something.
2204 */
2205 *msg = xmlStrdup(BAD_CAST "");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002206 } else {
2207 TODO
2208 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002209 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002210 /*
2211 * VAL TODO: The output of the given schema component is currently
2212 * disabled.
2213 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002214#if 0
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002215 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2216 *msg = xmlStrcat(*msg, BAD_CAST " [");
2217 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2218 NULL, type, NULL, 0));
2219 FREE_AND_NULL(str)
2220 *msg = xmlStrcat(*msg, BAD_CAST "]");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002221 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002222#endif
2223 return (*msg);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002224}
2225
Daniel Veillardc0826a72004-08-10 14:17:33 +00002226static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002227xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002228 const char *funcName,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002229 const char *message,
2230 const xmlChar *str1,
2231 const xmlChar *str2)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002232{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002233 xmlChar *msg = NULL;
2234
2235 msg = xmlStrdup(BAD_CAST "Internal error: ");
2236 msg = xmlStrcat(msg, BAD_CAST funcName);
2237 msg = xmlStrcat(msg, BAD_CAST ", ");
2238 msg = xmlStrcat(msg, BAD_CAST message);
2239 msg = xmlStrcat(msg, BAD_CAST ".\n");
2240
2241 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2242 xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002243 (const char *) msg, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002244
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002245 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002246 xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002247 (const char *) msg, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002248
2249 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002250}
2251
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002252static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002253xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2254 const char *funcName,
2255 const char *message)
2256{
2257 xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2258}
2259
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002260#if 0
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002261static void
2262xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2263 const char *funcName,
2264 const char *message,
2265 const xmlChar *str1,
2266 const xmlChar *str2)
2267{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002268 xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002269 str1, str2);
2270}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002271#endif
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002272
2273static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002274xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2275 xmlParserErrors error,
2276 xmlNodePtr node,
2277 xmlSchemaBasicItemPtr item,
2278 const char *message,
2279 const xmlChar *str1, const xmlChar *str2,
2280 const xmlChar *str3, const xmlChar *str4)
2281{
2282 xmlChar *msg = NULL;
2283
2284 if ((node == NULL) && (item != NULL) &&
2285 (actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2286 node = WXS_ITEM_NODE(item);
2287 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2288 msg = xmlStrcat(msg, BAD_CAST ": ");
2289 } else
2290 xmlSchemaFormatNodeForError(&msg, actxt, node);
2291 msg = xmlStrcat(msg, (const xmlChar *) message);
2292 msg = xmlStrcat(msg, BAD_CAST ".\n");
2293 xmlSchemaErr4(actxt, error, node,
2294 (const char *) msg, str1, str2, str3, str4);
2295 FREE_AND_NULL(msg)
2296}
2297
2298static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002299xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2300 xmlParserErrors error,
2301 xmlNodePtr node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002302 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002303 const char *message,
2304 const xmlChar *str1,
2305 const xmlChar *str2)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002306{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002307 xmlSchemaCustomErr4(actxt, error, node, item,
2308 message, str1, str2, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002309}
2310
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002311
2312
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002313static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002314xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2315 xmlParserErrors error,
2316 xmlNodePtr node,
2317 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2318 const char *message,
2319 const xmlChar *str1,
2320 const xmlChar *str2,
2321 const xmlChar *str3)
2322{
2323 xmlChar *msg = NULL;
2324
2325 xmlSchemaFormatNodeForError(&msg, actxt, node);
2326 msg = xmlStrcat(msg, (const xmlChar *) message);
2327 msg = xmlStrcat(msg, BAD_CAST ".\n");
2328
2329 /* URGENT TODO: Set the error code to something sane. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002330 xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2331 (const char *) msg, str1, str2, str3, NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002332
2333 FREE_AND_NULL(msg)
2334}
2335
2336
2337
2338static void
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002339xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2340 xmlParserErrors error,
2341 xmlSchemaPSVIIDCNodePtr idcNode,
2342 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2343 const char *message,
2344 const xmlChar *str1,
2345 const xmlChar *str2)
2346{
2347 xmlChar *msg = NULL, *qname = NULL;
2348
2349 msg = xmlStrdup(BAD_CAST "Element '%s': ");
2350 msg = xmlStrcat(msg, (const xmlChar *) message);
2351 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002352 xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002353 error, NULL, idcNode->nodeLine, (const char *) msg,
2354 xmlSchemaFormatQName(&qname,
2355 vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2356 vctxt->nodeQNames->items[idcNode->nodeQNameID]),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002357 str1, str2, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002358 FREE_AND_NULL(qname);
2359 FREE_AND_NULL(msg);
2360}
2361
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002362static int
2363xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2364 xmlNodePtr node)
2365{
2366 if (node != NULL)
2367 return (node->type);
2368 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2369 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2370 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2371 return (-1);
2372}
2373
2374static int
2375xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2376{
2377 switch (item->type) {
2378 case XML_SCHEMA_TYPE_COMPLEX:
2379 case XML_SCHEMA_TYPE_SIMPLE:
2380 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2381 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002382 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002383 case XML_SCHEMA_TYPE_GROUP:
2384 return (1);
2385 case XML_SCHEMA_TYPE_ELEMENT:
2386 if ( ((xmlSchemaElementPtr) item)->flags &
2387 XML_SCHEMAS_ELEM_GLOBAL)
2388 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002389 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002390 case XML_SCHEMA_TYPE_ATTRIBUTE:
2391 if ( ((xmlSchemaAttributePtr) item)->flags &
2392 XML_SCHEMAS_ATTR_GLOBAL)
2393 return(1);
2394 break;
2395 /* Note that attribute groups are always global. */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002396 default:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002397 return(1);
2398 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002399 return (0);
2400}
2401
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002402static void
2403xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2404 xmlParserErrors error,
2405 xmlNodePtr node,
2406 const xmlChar *value,
2407 xmlSchemaTypePtr type,
2408 int displayValue)
2409{
2410 xmlChar *msg = NULL;
2411
2412 xmlSchemaFormatNodeForError(&msg, actxt, node);
2413
2414 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2415 XML_ATTRIBUTE_NODE))
2416 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2417 else
2418 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2419 "value of ");
2420
2421 if (! xmlSchemaIsGlobalItem(type))
2422 msg = xmlStrcat(msg, BAD_CAST "the local ");
2423 else
2424 msg = xmlStrcat(msg, BAD_CAST "the ");
2425
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002426 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002427 msg = xmlStrcat(msg, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002428 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002429 msg = xmlStrcat(msg, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002430 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002431 msg = xmlStrcat(msg, BAD_CAST "union type");
2432
2433 if (xmlSchemaIsGlobalItem(type)) {
2434 xmlChar *str = NULL;
2435 msg = xmlStrcat(msg, BAD_CAST " '");
2436 if (type->builtInType != 0) {
2437 msg = xmlStrcat(msg, BAD_CAST "xs:");
2438 msg = xmlStrcat(msg, type->name);
2439 } else
2440 msg = xmlStrcat(msg,
2441 xmlSchemaFormatQName(&str,
2442 type->targetNamespace, type->name));
2443 msg = xmlStrcat(msg, BAD_CAST "'");
2444 FREE_AND_NULL(str);
2445 }
2446 msg = xmlStrcat(msg, BAD_CAST ".\n");
2447 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2448 XML_ATTRIBUTE_NODE))
2449 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2450 else
2451 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2452 FREE_AND_NULL(msg)
2453}
2454
Daniel Veillardc0826a72004-08-10 14:17:33 +00002455static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002456xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2457 xmlSchemaNodeInfoPtr ni,
2458 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002459{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002460 if (node != NULL) {
2461 if (node->ns != NULL)
2462 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2463 else
2464 return (xmlSchemaFormatQName(str, NULL, node->name));
2465 } else if (ni != NULL)
2466 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2467 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002468}
2469
Daniel Veillardc0826a72004-08-10 14:17:33 +00002470static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002471xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2472 xmlParserErrors error,
2473 xmlSchemaAttrInfoPtr ni,
2474 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002475{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002476 xmlChar *msg = NULL, *str = NULL;
2477
2478 xmlSchemaFormatNodeForError(&msg, actxt, node);
2479 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2480 xmlSchemaErr(actxt, error, node, (const char *) msg,
2481 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2482 NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002483 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002484 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002485}
2486
Daniel Veillardc0826a72004-08-10 14:17:33 +00002487static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002488xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2489 xmlParserErrors error,
2490 xmlNodePtr node,
2491 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002492 const char *message,
2493 int nbval,
2494 int nbneg,
2495 xmlChar **values)
2496{
2497 xmlChar *str = NULL, *msg = NULL;
2498 xmlChar *localName, *nsName;
2499 const xmlChar *cur, *end;
Daniel Veillard6a0baa02005-12-10 11:11:12 +00002500 int i;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002501
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002502 xmlSchemaFormatNodeForError(&msg, actxt, node);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002503 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002504 msg = xmlStrcat(msg, BAD_CAST ".");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002505 /*
2506 * Note that is does not make sense to report that we have a
2507 * wildcard here, since the wildcard might be unfolded into
2508 * multiple transitions.
2509 */
2510 if (nbval + nbneg > 0) {
2511 if (nbval + nbneg > 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002512 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002513 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002514 str = xmlStrdup(BAD_CAST " Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002515 nsName = NULL;
2516
2517 for (i = 0; i < nbval + nbneg; i++) {
2518 cur = values[i];
Daniel Veillard77005e62005-07-19 16:26:18 +00002519 if (cur == NULL)
2520 continue;
2521 if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2522 (cur[3] == ' ')) {
Daniel Veillard77005e62005-07-19 16:26:18 +00002523 cur += 4;
Daniel Veillard6e65e152005-08-09 11:09:52 +00002524 str = xmlStrcat(str, BAD_CAST "##other");
Daniel Veillard77005e62005-07-19 16:26:18 +00002525 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002526 /*
2527 * Get the local name.
2528 */
2529 localName = NULL;
2530
2531 end = cur;
2532 if (*end == '*') {
2533 localName = xmlStrdup(BAD_CAST "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00002534 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002535 } else {
2536 while ((*end != 0) && (*end != '|'))
2537 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002538 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002539 }
2540 if (*end != 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00002541 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002542 /*
2543 * Skip "*|*" if they come with negated expressions, since
2544 * they represent the same negated wildcard.
2545 */
2546 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2547 /*
2548 * Get the namespace name.
2549 */
2550 cur = end;
2551 if (*end == '*') {
2552 nsName = xmlStrdup(BAD_CAST "{*}");
2553 } else {
2554 while (*end != 0)
2555 end++;
2556
2557 if (i >= nbval)
2558 nsName = xmlStrdup(BAD_CAST "{##other:");
2559 else
2560 nsName = xmlStrdup(BAD_CAST "{");
2561
2562 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2563 nsName = xmlStrcat(nsName, BAD_CAST "}");
2564 }
2565 str = xmlStrcat(str, BAD_CAST nsName);
2566 FREE_AND_NULL(nsName)
2567 } else {
2568 FREE_AND_NULL(localName);
2569 continue;
2570 }
2571 }
2572 str = xmlStrcat(str, BAD_CAST localName);
2573 FREE_AND_NULL(localName);
2574
2575 if (i < nbval + nbneg -1)
2576 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00002577 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002578 str = xmlStrcat(str, BAD_CAST " ).\n");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002579 msg = xmlStrcat(msg, BAD_CAST str);
2580 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002581 } else
2582 msg = xmlStrcat(msg, BAD_CAST "\n");
2583 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002584 xmlFree(msg);
2585}
2586
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002587static void
2588xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2589 xmlParserErrors error,
2590 xmlNodePtr node,
2591 const xmlChar *value,
2592 unsigned long length,
2593 xmlSchemaTypePtr type,
2594 xmlSchemaFacetPtr facet,
2595 const char *message,
2596 const xmlChar *str1,
2597 const xmlChar *str2)
2598{
2599 xmlChar *str = NULL, *msg = NULL;
2600 xmlSchemaTypeType facetType;
2601 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2602
2603 xmlSchemaFormatNodeForError(&msg, actxt, node);
2604 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2605 facetType = XML_SCHEMA_FACET_ENUMERATION;
2606 /*
2607 * If enumerations are validated, one must not expect the
2608 * facet to be given.
2609 */
2610 } else
2611 facetType = facet->type;
2612 msg = xmlStrcat(msg, BAD_CAST "[");
2613 msg = xmlStrcat(msg, BAD_CAST "facet '");
2614 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2615 msg = xmlStrcat(msg, BAD_CAST "'] ");
2616 if (message == NULL) {
2617 /*
2618 * Use a default message.
2619 */
2620 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2621 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2622 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2623
2624 char len[25], actLen[25];
2625
2626 /* FIXME, TODO: What is the max expected string length of the
2627 * this value?
2628 */
2629 if (nodeType == XML_ATTRIBUTE_NODE)
2630 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2631 else
2632 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2633
2634 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2635 snprintf(actLen, 24, "%lu", length);
2636
2637 if (facetType == XML_SCHEMA_FACET_LENGTH)
2638 msg = xmlStrcat(msg,
2639 BAD_CAST "this differs from the allowed length of '%s'.\n");
2640 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2641 msg = xmlStrcat(msg,
2642 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2643 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2644 msg = xmlStrcat(msg,
2645 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2646
2647 if (nodeType == XML_ATTRIBUTE_NODE)
2648 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2649 value, (const xmlChar *) actLen, (const xmlChar *) len);
2650 else
2651 xmlSchemaErr(actxt, error, node, (const char *) msg,
2652 (const xmlChar *) actLen, (const xmlChar *) len);
2653
2654 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2655 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2656 "of the set {%s}.\n");
2657 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2658 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2659 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2660 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2661 "by the pattern '%s'.\n");
2662 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2663 facet->value);
2664 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2665 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2666 "minimum value allowed ('%s').\n");
2667 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2668 facet->value);
2669 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2670 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2671 "maximum value allowed ('%s').\n");
2672 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2673 facet->value);
2674 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00002675 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002676 "'%s'.\n");
2677 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2678 facet->value);
2679 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00002680 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002681 "'%s'.\n");
2682 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2683 facet->value);
2684 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2685 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2686 "digits than are allowed ('%s').\n");
2687 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2688 facet->value);
2689 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2690 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2691 "digits than are allowed ('%s').\n");
2692 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2693 facet->value);
2694 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2695 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2696 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2697 } else {
2698 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2699 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2700 }
2701 } else {
2702 msg = xmlStrcat(msg, (const xmlChar *) message);
2703 msg = xmlStrcat(msg, BAD_CAST ".\n");
2704 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2705 }
2706 FREE_AND_NULL(str)
2707 xmlFree(msg);
2708}
2709
2710#define VERROR(err, type, msg) \
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002711 xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002712
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002713#define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002714
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002715#define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2716#define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002717
2718#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2719
2720
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002721/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00002722 * xmlSchemaPMissingAttrErr:
2723 * @ctxt: the schema validation context
2724 * @ownerDes: the designation of the owner
2725 * @ownerName: the name of the owner
2726 * @ownerItem: the owner as a schema object
2727 * @ownerElem: the owner as an element node
2728 * @node: the parent element node of the missing attribute node
2729 * @type: the corresponding type of the attribute node
2730 *
2731 * Reports an illegal attribute.
2732 */
2733static void
2734xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002735 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002736 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002737 xmlNodePtr ownerElem,
2738 const char *name,
2739 const char *message)
2740{
2741 xmlChar *des = NULL;
2742
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002743 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2744
Daniel Veillardc0826a72004-08-10 14:17:33 +00002745 if (message != NULL)
2746 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002747 else
2748 xmlSchemaPErr(ctxt, ownerElem, error,
2749 "%s: The attribute '%s' is required but missing.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002750 BAD_CAST des, BAD_CAST name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002751 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002752}
2753
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002754
Daniel Veillardc0826a72004-08-10 14:17:33 +00002755/**
2756 * xmlSchemaPResCompAttrErr:
2757 * @ctxt: the schema validation context
2758 * @error: the error code
2759 * @ownerDes: the designation of the owner
2760 * @ownerItem: the owner as a schema object
2761 * @ownerElem: the owner as an element node
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002762 * @name: the name of the attribute holding the QName
Daniel Veillardc0826a72004-08-10 14:17:33 +00002763 * @refName: the referenced local name
2764 * @refURI: the referenced namespace URI
2765 * @message: optional message
2766 *
2767 * Used to report QName attribute values that failed to resolve
2768 * to schema components.
2769 */
2770static void
2771xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002772 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002773 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002774 xmlNodePtr ownerElem,
2775 const char *name,
2776 const xmlChar *refName,
2777 const xmlChar *refURI,
2778 xmlSchemaTypeType refType,
2779 const char *refTypeStr)
2780{
2781 xmlChar *des = NULL, *strA = NULL;
2782
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002783 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002784 if (refTypeStr == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002785 refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002786 xmlSchemaPErrExt(ctxt, ownerElem, error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002787 NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002788 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2789 "%s.\n", BAD_CAST des, BAD_CAST name,
2790 xmlSchemaFormatQName(&strA, refURI, refName),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002791 BAD_CAST refTypeStr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002792 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002793 FREE_AND_NULL(strA)
2794}
2795
William M. Brack2f2a6632004-08-20 23:09:47 +00002796/**
2797 * xmlSchemaPCustomAttrErr:
2798 * @ctxt: the schema parser context
2799 * @error: the error code
2800 * @ownerDes: the designation of the owner
2801 * @ownerItem: the owner as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002802 * @attr: the illegal attribute node
William M. Brack2f2a6632004-08-20 23:09:47 +00002803 *
2804 * Reports an illegal attribute during the parse.
2805 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002806static void
2807xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002808 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002809 xmlChar **ownerDes,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002810 xmlSchemaBasicItemPtr ownerItem,
William M. Brack2f2a6632004-08-20 23:09:47 +00002811 xmlAttrPtr attr,
2812 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002813{
2814 xmlChar *des = NULL;
2815
2816 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002817 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002818 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002819 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002820 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002821 } else
2822 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002823 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002824 "%s, attribute '%s': %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002825 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2826 if (ownerDes == NULL)
2827 FREE_AND_NULL(des);
2828}
2829
2830/**
2831 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002832 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002833 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002834 * @ownerDes: the designation of the attribute's owner
2835 * @ownerItem: the attribute's owner item
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002836 * @attr: the illegal attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00002837 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002838 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002839 */
2840static void
2841xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002842 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002843 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002844 xmlAttrPtr attr)
2845{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002846 xmlChar *strA = NULL, *strB = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002847
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002848 xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2849 xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2850 "%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2851 xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2852 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002853 FREE_AND_NULL(strA);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002854 FREE_AND_NULL(strB);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002855}
2856
William M. Brack2f2a6632004-08-20 23:09:47 +00002857/**
2858 * xmlSchemaPCustomErr:
2859 * @ctxt: the schema parser context
2860 * @error: the error code
2861 * @itemDes: the designation of the schema item
2862 * @item: the schema item
2863 * @itemElem: the node of the schema item
2864 * @message: the error message
2865 * @str1: an optional param for the error message
2866 * @str2: an optional param for the error message
2867 * @str3: an optional param for the error message
2868 *
2869 * Reports an error during parsing.
2870 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002871static void
2872xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002873 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002874 xmlSchemaBasicItemPtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002875 xmlNodePtr itemElem,
2876 const char *message,
2877 const xmlChar *str1,
2878 const xmlChar *str2,
2879 const xmlChar *str3)
2880{
2881 xmlChar *des = NULL, *msg = NULL;
2882
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002883 xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002884 msg = xmlStrdup(BAD_CAST "%s: ");
2885 msg = xmlStrcat(msg, (const xmlChar *) message);
2886 msg = xmlStrcat(msg, BAD_CAST ".\n");
2887 if ((itemElem == NULL) && (item != NULL))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002888 itemElem = WXS_ITEM_NODE(item);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002889 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002890 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002891 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002892 FREE_AND_NULL(msg);
2893}
2894
William M. Brack2f2a6632004-08-20 23:09:47 +00002895/**
2896 * xmlSchemaPCustomErr:
2897 * @ctxt: the schema parser context
2898 * @error: the error code
2899 * @itemDes: the designation of the schema item
2900 * @item: the schema item
2901 * @itemElem: the node of the schema item
2902 * @message: the error message
2903 * @str1: the optional param for the error message
2904 *
2905 * Reports an error during parsing.
2906 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002907static void
2908xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002909 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002910 xmlSchemaBasicItemPtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002911 xmlNodePtr itemElem,
2912 const char *message,
2913 const xmlChar *str1)
2914{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002915 xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002916 str1, NULL, NULL);
2917}
2918
William M. Brack2f2a6632004-08-20 23:09:47 +00002919/**
2920 * xmlSchemaPAttrUseErr:
2921 * @ctxt: the schema parser context
2922 * @error: the error code
2923 * @itemDes: the designation of the schema type
2924 * @item: the schema type
2925 * @itemElem: the node of the schema type
2926 * @attr: the invalid schema attribute
2927 * @message: the error message
2928 * @str1: the optional param for the error message
2929 *
2930 * Reports an attribute use error during parsing.
2931 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002932static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002933xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002934 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002935 xmlNodePtr node,
2936 xmlSchemaBasicItemPtr ownerItem,
2937 const xmlSchemaAttributeUsePtr attruse,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002938 const char *message,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002939 const xmlChar *str1, const xmlChar *str2,
2940 const xmlChar *str3,const xmlChar *str4)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002941{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002942 xmlChar *str = NULL, *msg = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002943
2944 xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
2945 msg = xmlStrcat(msg, BAD_CAST ", ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002946 msg = xmlStrcat(msg,
2947 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002948 WXS_BASIC_CAST attruse, NULL));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002949 FREE_AND_NULL(str);
2950 msg = xmlStrcat(msg, BAD_CAST ": ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002951 msg = xmlStrcat(msg, (const xmlChar *) message);
2952 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002953 xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
2954 (const char *) msg, str1, str2, str3, str4);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002955 xmlFree(msg);
2956}
2957
William M. Brack2f2a6632004-08-20 23:09:47 +00002958/**
2959 * xmlSchemaPIllegalFacetAtomicErr:
2960 * @ctxt: the schema parser context
2961 * @error: the error code
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002962 * @type: the schema type
2963 * @baseType: the base type of type
William M. Brack2f2a6632004-08-20 23:09:47 +00002964 * @facet: the illegal facet
2965 *
2966 * Reports an illegal facet for atomic simple types.
2967 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002968static void
2969xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002970 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002971 xmlSchemaTypePtr type,
2972 xmlSchemaTypePtr baseType,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002973 xmlSchemaFacetPtr facet)
2974{
2975 xmlChar *des = NULL, *strT = NULL;
2976
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002977 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
2978 xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002979 "%s: The facet '%s' is not allowed on types derived from the "
2980 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002981 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002982 xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002983 NULL, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002984 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002985 FREE_AND_NULL(strT);
2986}
2987
William M. Brack2f2a6632004-08-20 23:09:47 +00002988/**
2989 * xmlSchemaPIllegalFacetListUnionErr:
2990 * @ctxt: the schema parser context
2991 * @error: the error code
2992 * @itemDes: the designation of the schema item involved
2993 * @item: the schema item involved
2994 * @facet: the illegal facet
2995 *
2996 * Reports an illegal facet for <list> and <union>.
2997 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002998static void
2999xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003000 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003001 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003002 xmlSchemaFacetPtr facet)
3003{
3004 xmlChar *des = NULL, *strT = NULL;
3005
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003006 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3007 type->node);
3008 xmlSchemaPErr(ctxt, type->node, error,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003009 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00003010 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003011 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003012 FREE_AND_NULL(strT);
3013}
3014
3015/**
3016 * xmlSchemaPMutualExclAttrErr:
3017 * @ctxt: the schema validation context
3018 * @error: the error code
3019 * @elemDes: the designation of the parent element node
3020 * @attr: the bad attribute node
3021 * @type: the corresponding type of the attribute node
3022 *
3023 * Reports an illegal attribute.
3024 */
3025static void
3026xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3027 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003028 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003029 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003030 const char *name1,
3031 const char *name2)
3032{
3033 xmlChar *des = NULL;
3034
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003035 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003036 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003037 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003038 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003039 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003040}
3041
3042/**
3043 * xmlSchemaPSimpleTypeErr:
3044 * @ctxt: the schema validation context
3045 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00003046 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00003047 * @ownerDes: the designation of the owner
3048 * @ownerItem: the schema object if existent
3049 * @node: the validated node
3050 * @value: the validated value
3051 *
3052 * Reports a simple type validation error.
3053 * TODO: Should this report the value of an element as well?
3054 */
3055static void
3056xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3057 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003058 xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003059 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00003060 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003061 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003062 const xmlChar *value,
3063 const char *message,
3064 const xmlChar *str1,
3065 const xmlChar *str2)
3066{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003067 xmlChar *msg = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003068
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003069 xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003070 if (message == NULL) {
3071 /*
3072 * Use default messages.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003073 */
3074 if (type != NULL) {
3075 if (node->type == XML_ATTRIBUTE_NODE)
3076 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3077 else
3078 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3079 "valid value of ");
3080 if (! xmlSchemaIsGlobalItem(type))
3081 msg = xmlStrcat(msg, BAD_CAST "the local ");
3082 else
3083 msg = xmlStrcat(msg, BAD_CAST "the ");
3084
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003085 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003086 msg = xmlStrcat(msg, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003087 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003088 msg = xmlStrcat(msg, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003089 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003090 msg = xmlStrcat(msg, BAD_CAST "union type");
3091
3092 if (xmlSchemaIsGlobalItem(type)) {
3093 xmlChar *str = NULL;
3094 msg = xmlStrcat(msg, BAD_CAST " '");
3095 if (type->builtInType != 0) {
3096 msg = xmlStrcat(msg, BAD_CAST "xs:");
3097 msg = xmlStrcat(msg, type->name);
3098 } else
3099 msg = xmlStrcat(msg,
3100 xmlSchemaFormatQName(&str,
3101 type->targetNamespace, type->name));
3102 msg = xmlStrcat(msg, BAD_CAST "'.");
3103 FREE_AND_NULL(str);
3104 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003105 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003106 if (node->type == XML_ATTRIBUTE_NODE)
3107 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3108 else
3109 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3110 "valid.");
3111 }
3112 if (expected) {
3113 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3114 msg = xmlStrcat(msg, BAD_CAST expected);
3115 msg = xmlStrcat(msg, BAD_CAST "'.\n");
3116 } else
3117 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00003118 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003119 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3120 else
3121 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3122 } else {
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00003123 msg = xmlStrcat(msg, BAD_CAST message);
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00003124 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003125 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00003126 (const char*) msg, str1, str2, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003127 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003128 /* Cleanup. */
3129 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003130}
3131
William M. Brack2f2a6632004-08-20 23:09:47 +00003132/**
3133 * xmlSchemaPContentErr:
3134 * @ctxt: the schema parser context
3135 * @error: the error code
3136 * @onwerDes: the designation of the holder of the content
3137 * @ownerItem: the owner item of the holder of the content
3138 * @ownerElem: the node of the holder of the content
3139 * @child: the invalid child node
3140 * @message: the optional error message
3141 * @content: the optional string describing the correct content
3142 *
3143 * Reports an error concerning the content of a schema element.
3144 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00003145static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003146xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003147 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003148 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003149 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003150 xmlNodePtr child,
3151 const char *message,
3152 const char *content)
3153{
3154 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003155
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003156 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003157 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003158 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3159 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003160 BAD_CAST des, BAD_CAST message);
3161 else {
3162 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003163 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3164 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003165 BAD_CAST des, BAD_CAST content);
3166 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003167 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3168 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003169 BAD_CAST des, NULL);
3170 }
3171 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003172 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003173}
3174
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003175/************************************************************************
3176 * *
3177 * Streamable error functions *
3178 * *
3179 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00003180
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003181
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003182
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003183
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003184/************************************************************************
3185 * *
3186 * Validation helper functions *
3187 * *
3188 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003189
Daniel Veillardc0826a72004-08-10 14:17:33 +00003190
Daniel Veillard4255d502002-04-16 15:50:10 +00003191/************************************************************************
3192 * *
3193 * Allocation functions *
3194 * *
3195 ************************************************************************/
3196
3197/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003198 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00003199 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00003200 *
3201 * Allocate a new Schema structure.
3202 *
3203 * Returns the newly allocated structure or NULL in case or error
3204 */
3205static xmlSchemaPtr
3206xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3207{
3208 xmlSchemaPtr ret;
3209
3210 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3211 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003212 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003213 return (NULL);
3214 }
3215 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003216 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003217 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003218
3219 return (ret);
3220}
3221
3222/**
3223 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00003224 *
3225 * Allocate a new Facet structure.
3226 *
3227 * Returns the newly allocated structure or NULL in case or error
3228 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003229xmlSchemaFacetPtr
3230xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00003231{
3232 xmlSchemaFacetPtr ret;
3233
3234 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3235 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003236 return (NULL);
3237 }
3238 memset(ret, 0, sizeof(xmlSchemaFacet));
3239
3240 return (ret);
3241}
3242
3243/**
3244 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00003245 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00003246 * @node: a node
3247 *
3248 * Allocate a new annotation structure.
3249 *
3250 * Returns the newly allocated structure or NULL in case or error
3251 */
3252static xmlSchemaAnnotPtr
3253xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3254{
3255 xmlSchemaAnnotPtr ret;
3256
3257 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3258 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003259 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003260 return (NULL);
3261 }
3262 memset(ret, 0, sizeof(xmlSchemaAnnot));
3263 ret->content = node;
3264 return (ret);
3265}
3266
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003267static xmlSchemaItemListPtr
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003268xmlSchemaItemListCreate(void)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003269{
3270 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003271
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003272 ret = xmlMalloc(sizeof(xmlSchemaItemList));
3273 if (ret == NULL) {
3274 xmlSchemaPErrMemory(NULL,
3275 "allocating an item list structure", NULL);
3276 return (NULL);
3277 }
3278 memset(ret, 0, sizeof(xmlSchemaItemList));
3279 return (ret);
3280}
3281
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00003282static void
3283xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3284{
3285 if (list->items != NULL) {
3286 xmlFree(list->items);
3287 list->items = NULL;
3288 }
3289 list->nbItems = 0;
3290 list->sizeItems = 0;
3291}
3292
3293static int
3294xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3295{
3296 if (list->items == NULL) {
3297 list->items = (void **) xmlMalloc(
3298 20 * sizeof(void *));
3299 if (list->items == NULL) {
3300 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3301 return(-1);
3302 }
3303 list->sizeItems = 20;
3304 } else if (list->sizeItems <= list->nbItems) {
3305 list->sizeItems *= 2;
3306 list->items = (void **) xmlRealloc(list->items,
3307 list->sizeItems * sizeof(void *));
3308 if (list->items == NULL) {
3309 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3310 list->sizeItems = 0;
3311 return(-1);
3312 }
3313 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00003314 list->items[list->nbItems++] = item;
3315 return(0);
3316}
3317
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003318static int
3319xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3320 int initialSize,
3321 void *item)
3322{
3323 if (list->items == NULL) {
3324 if (initialSize <= 0)
3325 initialSize = 1;
3326 list->items = (void **) xmlMalloc(
3327 initialSize * sizeof(void *));
3328 if (list->items == NULL) {
3329 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3330 return(-1);
3331 }
3332 list->sizeItems = initialSize;
3333 } else if (list->sizeItems <= list->nbItems) {
3334 list->sizeItems *= 2;
3335 list->items = (void **) xmlRealloc(list->items,
3336 list->sizeItems * sizeof(void *));
3337 if (list->items == NULL) {
3338 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3339 list->sizeItems = 0;
3340 return(-1);
3341 }
3342 }
3343 list->items[list->nbItems++] = item;
3344 return(0);
3345}
3346
3347static int
3348xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3349{
3350 if (list->items == NULL) {
3351 list->items = (void **) xmlMalloc(
3352 20 * sizeof(void *));
3353 if (list->items == NULL) {
3354 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3355 return(-1);
3356 }
3357 list->sizeItems = 20;
3358 } else if (list->sizeItems <= list->nbItems) {
3359 list->sizeItems *= 2;
3360 list->items = (void **) xmlRealloc(list->items,
3361 list->sizeItems * sizeof(void *));
3362 if (list->items == NULL) {
3363 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3364 list->sizeItems = 0;
3365 return(-1);
3366 }
3367 }
3368 /*
3369 * Just append if the index is greater/equal than the item count.
3370 */
3371 if (idx >= list->nbItems) {
3372 list->items[list->nbItems++] = item;
3373 } else {
3374 int i;
3375 for (i = list->nbItems; i > idx; i--)
3376 list->items[i] = list->items[i-1];
3377 list->items[idx] = item;
3378 list->nbItems++;
3379 }
3380 return(0);
3381}
3382
3383#if 0 /* enable if ever needed */
3384static int
3385xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3386 int initialSize,
3387 void *item,
3388 int idx)
3389{
3390 if (list->items == NULL) {
3391 if (initialSize <= 0)
3392 initialSize = 1;
3393 list->items = (void **) xmlMalloc(
3394 initialSize * sizeof(void *));
3395 if (list->items == NULL) {
3396 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3397 return(-1);
3398 }
3399 list->sizeItems = initialSize;
3400 } else if (list->sizeItems <= list->nbItems) {
3401 list->sizeItems *= 2;
3402 list->items = (void **) xmlRealloc(list->items,
3403 list->sizeItems * sizeof(void *));
3404 if (list->items == NULL) {
3405 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3406 list->sizeItems = 0;
3407 return(-1);
3408 }
3409 }
3410 /*
3411 * Just append if the index is greater/equal than the item count.
3412 */
3413 if (idx >= list->nbItems) {
3414 list->items[list->nbItems++] = item;
3415 } else {
3416 int i;
3417 for (i = list->nbItems; i > idx; i--)
3418 list->items[i] = list->items[i-1];
3419 list->items[idx] = item;
3420 list->nbItems++;
3421 }
3422 return(0);
3423}
3424#endif
3425
3426static int
3427xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3428{
3429 int i;
3430 if ((list->items == NULL) || (idx >= list->nbItems)) {
3431 xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3432 "index error.\n");
3433 return(-1);
3434 }
3435
3436 if (list->nbItems == 1) {
3437 /* TODO: Really free the list? */
3438 xmlFree(list->items);
3439 list->items = NULL;
3440 list->nbItems = 0;
3441 list->sizeItems = 0;
3442 } else if (list->nbItems -1 == idx) {
3443 list->nbItems--;
3444 } else {
3445 for (i = idx; i < list->nbItems -1; i++)
3446 list->items[i] = list->items[i+1];
3447 list->nbItems--;
3448 }
3449 return(0);
3450}
3451
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003452/**
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003453 * xmlSchemaItemListFree:
3454 * @annot: a schema type structure
3455 *
3456 * Deallocate a annotation structure
3457 */
3458static void
3459xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3460{
3461 if (list == NULL)
3462 return;
3463 if (list->items != NULL)
3464 xmlFree(list->items);
3465 xmlFree(list);
3466}
3467
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003468static void
3469xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003470{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003471 if (bucket == NULL)
3472 return;
3473 if (bucket->globals != NULL) {
3474 xmlSchemaComponentListFree(bucket->globals);
3475 xmlSchemaItemListFree(bucket->globals);
3476 }
3477 if (bucket->locals != NULL) {
3478 xmlSchemaComponentListFree(bucket->locals);
3479 xmlSchemaItemListFree(bucket->locals);
3480 }
3481 if (bucket->relations != NULL) {
3482 xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3483 do {
3484 prev = cur;
3485 cur = cur->next;
3486 xmlFree(prev);
3487 } while (cur != NULL);
3488 }
3489 if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3490 xmlFreeDoc(bucket->doc);
3491 }
3492 if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003493 if (WXS_IMPBUCKET(bucket)->schema != NULL)
3494 xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003495 }
3496 xmlFree(bucket);
3497}
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003498
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003499static xmlSchemaBucketPtr
3500xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003501 int type, const xmlChar *targetNamespace)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003502{
3503 xmlSchemaBucketPtr ret;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003504 int size;
3505 xmlSchemaPtr mainSchema;
3506
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003507 if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003508 PERROR_INT("xmlSchemaBucketCreate",
3509 "no main schema on constructor");
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003510 return(NULL);
3511 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003512 mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003513 /* Create the schema bucket. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003514 if (WXS_IS_BUCKET_INCREDEF(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003515 size = sizeof(xmlSchemaInclude);
3516 else
3517 size = sizeof(xmlSchemaImport);
3518 ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3519 if (ret == NULL) {
3520 xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3521 return(NULL);
3522 }
3523 memset(ret, 0, size);
3524 ret->targetNamespace = targetNamespace;
3525 ret->type = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003526 ret->globals = xmlSchemaItemListCreate();
3527 if (ret->globals == NULL) {
3528 xmlFree(ret);
3529 return(NULL);
3530 }
3531 ret->locals = xmlSchemaItemListCreate();
3532 if (ret->locals == NULL) {
3533 xmlFree(ret);
3534 return(NULL);
3535 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003536 /*
3537 * The following will assure that only the first bucket is marked as
3538 * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3539 * For each following import buckets an xmlSchema will be created.
3540 */
3541 if (! WXS_HAS_BUCKETS(pctxt)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003542 if (WXS_IS_BUCKET_INCREDEF(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003543 PERROR_INT("xmlSchemaBucketCreate",
3544 "first bucket but it's an include or redefine");
3545 xmlSchemaBucketFree(ret);
3546 return(NULL);
3547 }
3548 /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3549 ret->type = XML_SCHEMA_SCHEMA_MAIN;
3550 /* Point to the *main* schema. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003551 WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3552 WXS_IMPBUCKET(ret)->schema = mainSchema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003553 } else {
3554 if (type == XML_SCHEMA_SCHEMA_MAIN) {
3555 PERROR_INT("xmlSchemaBucketCreate",
3556 "main bucket but it's not the first one");
3557 xmlSchemaBucketFree(ret);
3558 return(NULL);
3559 } else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3560 /*
3561 * Create a schema for imports.
3562 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003563 WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3564 if (WXS_IMPBUCKET(ret)->schema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003565 xmlSchemaBucketFree(ret);
3566 return(NULL);
3567 }
3568 }
3569 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003570 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003571 int res;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003572 /* Imports go into the "schemasImports" slot of the main *schema*. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003573 if (mainSchema->schemasImports == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003574 mainSchema->schemasImports = xmlHashCreateDict(5,
3575 WXS_CONSTRUCTOR(pctxt)->dict);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003576 if (mainSchema->schemasImports == NULL) {
3577 xmlSchemaBucketFree(ret);
3578 return(NULL);
3579 }
3580 }
3581 if (targetNamespace == NULL)
3582 res = xmlHashAddEntry(mainSchema->schemasImports,
3583 XML_SCHEMAS_NO_NAMESPACE, ret);
3584 else
3585 res = xmlHashAddEntry(mainSchema->schemasImports,
3586 targetNamespace, ret);
3587 if (res != 0) {
3588 PERROR_INT("xmlSchemaBucketCreate",
3589 "failed to add the schema bucket to the hash");
3590 xmlSchemaBucketFree(ret);
3591 return(NULL);
3592 }
3593 } else {
3594 /* Set the @ownerImport of an include bucket. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003595 if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3596 WXS_INCBUCKET(ret)->ownerImport =
3597 WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003598 else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003599 WXS_INCBUCKET(ret)->ownerImport =
3600 WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003601
3602 /* Includes got into the "includes" slot of the *main* schema. */
3603 if (mainSchema->includes == NULL) {
3604 mainSchema->includes = xmlSchemaItemListCreate();
3605 if (mainSchema->includes == NULL) {
3606 xmlSchemaBucketFree(ret);
3607 return(NULL);
3608 }
3609 }
3610 xmlSchemaItemListAdd(mainSchema->includes, ret);
3611 }
3612 /*
3613 * Add to list of all buckets; this is used for lookup
3614 * during schema construction time only.
3615 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003616 if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003617 return(NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003618 return(ret);
3619}
3620
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003621static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003622xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003623{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003624 if (*list == NULL) {
3625 *list = xmlSchemaItemListCreate();
3626 if (*list == NULL)
3627 return(-1);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003628 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003629 xmlSchemaItemListAddSize(*list, initialSize, item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003630 return(0);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003631}
3632
3633/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00003634 * xmlSchemaFreeAnnot:
3635 * @annot: a schema type structure
3636 *
3637 * Deallocate a annotation structure
3638 */
3639static void
3640xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3641{
3642 if (annot == NULL)
3643 return;
Kasimier T. Buchcik004b5462005-08-08 12:43:09 +00003644 if (annot->next == NULL) {
3645 xmlFree(annot);
3646 } else {
3647 xmlSchemaAnnotPtr prev;
3648
3649 do {
3650 prev = annot;
3651 annot = annot->next;
3652 xmlFree(prev);
3653 } while (annot != NULL);
3654 }
Daniel Veillardfdc91562002-07-01 21:52:03 +00003655}
3656
3657/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003658 * xmlSchemaFreeNotation:
3659 * @schema: a schema notation structure
3660 *
3661 * Deallocate a Schema Notation structure.
3662 */
3663static void
3664xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3665{
3666 if (nota == NULL)
3667 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003668 xmlFree(nota);
3669}
3670
3671/**
3672 * xmlSchemaFreeAttribute:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003673 * @attr: an attribute declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00003674 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003675 * Deallocates an attribute declaration structure.
Daniel Veillard4255d502002-04-16 15:50:10 +00003676 */
3677static void
3678xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3679{
3680 if (attr == NULL)
3681 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003682 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003683 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003684 if (attr->defVal != NULL)
3685 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003686 xmlFree(attr);
3687}
3688
3689/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003690 * xmlSchemaFreeAttributeUse:
3691 * @use: an attribute use
3692 *
3693 * Deallocates an attribute use structure.
3694 */
3695static void
3696xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3697{
3698 if (use == NULL)
3699 return;
3700 if (use->annot != NULL)
3701 xmlSchemaFreeAnnot(use->annot);
3702 if (use->defVal != NULL)
3703 xmlSchemaFreeValue(use->defVal);
3704 xmlFree(use);
3705}
3706
3707/**
3708 * xmlSchemaFreeAttributeUseProhib:
3709 * @prohib: an attribute use prohibition
3710 *
3711 * Deallocates an attribute use structure.
3712 */
3713static void
3714xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3715{
3716 if (prohib == NULL)
3717 return;
3718 xmlFree(prohib);
3719}
3720
3721/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003722 * xmlSchemaFreeWildcardNsSet:
3723 * set: a schema wildcard namespace
3724 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003725 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00003726 */
3727static void
3728xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3729{
3730 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003731
Daniel Veillard3646d642004-06-02 19:19:14 +00003732 while (set != NULL) {
3733 next = set->next;
3734 xmlFree(set);
3735 set = next;
3736 }
3737}
3738
3739/**
3740 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003741 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00003742 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003743 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00003744 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003745void
Daniel Veillard3646d642004-06-02 19:19:14 +00003746xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3747{
3748 if (wildcard == NULL)
3749 return;
3750 if (wildcard->annot != NULL)
3751 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003752 if (wildcard->nsSet != NULL)
3753 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3754 if (wildcard->negNsSet != NULL)
3755 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00003756 xmlFree(wildcard);
3757}
3758
3759/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003760 * xmlSchemaFreeAttributeGroup:
3761 * @schema: a schema attribute group structure
3762 *
3763 * Deallocate a Schema Attribute Group structure.
3764 */
3765static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003766xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
Daniel Veillard4255d502002-04-16 15:50:10 +00003767{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003768 if (attrGr == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00003769 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003770 if (attrGr->annot != NULL)
3771 xmlSchemaFreeAnnot(attrGr->annot);
3772 if (attrGr->attrUses != NULL)
3773 xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3774 xmlFree(attrGr);
Daniel Veillard3646d642004-06-02 19:19:14 +00003775}
3776
3777/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003778 * xmlSchemaFreeQNameRef:
3779 * @item: a QName reference structure
3780 *
3781 * Deallocatea a QName reference structure.
3782 */
3783static void
3784xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3785{
3786 xmlFree(item);
3787}
3788
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003789/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003790 * xmlSchemaFreeTypeLinkList:
3791 * @alink: a type link
3792 *
3793 * Deallocate a list of types.
3794 */
3795static void
3796xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3797{
3798 xmlSchemaTypeLinkPtr next;
3799
3800 while (link != NULL) {
3801 next = link->next;
3802 xmlFree(link);
3803 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003804 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003805}
3806
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003807static void
3808xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3809{
3810 xmlSchemaIDCStateObjPtr next;
3811 while (sto != NULL) {
3812 next = sto->next;
3813 if (sto->history != NULL)
3814 xmlFree(sto->history);
3815 if (sto->xpathCtxt != NULL)
3816 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3817 xmlFree(sto);
3818 sto = next;
3819 }
3820}
3821
3822/**
3823 * xmlSchemaFreeIDC:
3824 * @idc: a identity-constraint definition
3825 *
3826 * Deallocates an identity-constraint definition.
3827 */
3828static void
3829xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3830{
3831 xmlSchemaIDCSelectPtr cur, prev;
3832
3833 if (idcDef == NULL)
3834 return;
3835 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003836 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003837 /* Selector */
3838 if (idcDef->selector != NULL) {
3839 if (idcDef->selector->xpathComp != NULL)
3840 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3841 xmlFree(idcDef->selector);
3842 }
3843 /* Fields */
3844 if (idcDef->fields != NULL) {
3845 cur = idcDef->fields;
3846 do {
3847 prev = cur;
3848 cur = cur->next;
3849 if (prev->xpathComp != NULL)
3850 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003851 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003852 } while (cur != NULL);
3853 }
3854 xmlFree(idcDef);
3855}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003856
Daniel Veillard01fa6152004-06-29 17:04:39 +00003857/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003858 * xmlSchemaFreeElement:
3859 * @schema: a schema element structure
3860 *
3861 * Deallocate a Schema Element structure.
3862 */
3863static void
3864xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3865{
3866 if (elem == NULL)
3867 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003868 if (elem->annot != NULL)
3869 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003870 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003871 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003872 if (elem->defVal != NULL)
3873 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003874 xmlFree(elem);
3875}
3876
3877/**
3878 * xmlSchemaFreeFacet:
3879 * @facet: a schema facet structure
3880 *
3881 * Deallocate a Schema Facet structure.
3882 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003883void
Daniel Veillard4255d502002-04-16 15:50:10 +00003884xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3885{
3886 if (facet == NULL)
3887 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003888 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003889 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003890 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003891 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003892 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003893 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003894 xmlFree(facet);
3895}
3896
3897/**
3898 * xmlSchemaFreeType:
3899 * @type: a schema type structure
3900 *
3901 * Deallocate a Schema Type structure.
3902 */
3903void
3904xmlSchemaFreeType(xmlSchemaTypePtr type)
3905{
3906 if (type == NULL)
3907 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003908 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003909 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003910 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003911 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003912
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003913 facet = type->facets;
3914 while (facet != NULL) {
3915 next = facet->next;
3916 xmlSchemaFreeFacet(facet);
3917 facet = next;
3918 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003919 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003920 if (type->attrUses != NULL)
3921 xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003922 if (type->memberTypes != NULL)
3923 xmlSchemaFreeTypeLinkList(type->memberTypes);
3924 if (type->facetSet != NULL) {
3925 xmlSchemaFacetLinkPtr next, link;
3926
3927 link = type->facetSet;
3928 do {
3929 next = link->next;
3930 xmlFree(link);
3931 link = next;
3932 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003933 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003934 if (type->contModel != NULL)
3935 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003936 xmlFree(type);
3937}
3938
3939/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003940 * xmlSchemaFreeModelGroupDef:
3941 * @item: a schema model group definition
3942 *
3943 * Deallocates a schema model group definition.
3944 */
3945static void
3946xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3947{
3948 if (item->annot != NULL)
3949 xmlSchemaFreeAnnot(item->annot);
3950 xmlFree(item);
3951}
3952
3953/**
3954 * xmlSchemaFreeModelGroup:
3955 * @item: a schema model group
3956 *
3957 * Deallocates a schema model group structure.
3958 */
3959static void
3960xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3961{
3962 if (item->annot != NULL)
3963 xmlSchemaFreeAnnot(item->annot);
3964 xmlFree(item);
3965}
3966
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003967static void
3968xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
3969{
3970 if ((list == NULL) || (list->nbItems == 0))
3971 return;
3972 {
3973 xmlSchemaTreeItemPtr item;
3974 xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
3975 int i;
3976
3977 for (i = 0; i < list->nbItems; i++) {
3978 item = items[i];
3979 if (item == NULL)
3980 continue;
3981 switch (item->type) {
3982 case XML_SCHEMA_TYPE_SIMPLE:
3983 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003984 xmlSchemaFreeType((xmlSchemaTypePtr) item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003985 break;
3986 case XML_SCHEMA_TYPE_ATTRIBUTE:
3987 xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003988 break;
3989 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
3990 xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
3991 break;
3992 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
3993 xmlSchemaFreeAttributeUseProhib(
3994 (xmlSchemaAttributeUseProhibPtr) item);
3995 break;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003996 case XML_SCHEMA_TYPE_ELEMENT:
3997 xmlSchemaFreeElement((xmlSchemaElementPtr) item);
3998 break;
3999 case XML_SCHEMA_TYPE_PARTICLE:
4000 if (item->annot != NULL)
4001 xmlSchemaFreeAnnot(item->annot);
4002 xmlFree(item);
4003 break;
4004 case XML_SCHEMA_TYPE_SEQUENCE:
4005 case XML_SCHEMA_TYPE_CHOICE:
4006 case XML_SCHEMA_TYPE_ALL:
4007 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4008 break;
4009 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4010 xmlSchemaFreeAttributeGroup(
4011 (xmlSchemaAttributeGroupPtr) item);
4012 break;
4013 case XML_SCHEMA_TYPE_GROUP:
4014 xmlSchemaFreeModelGroupDef(
4015 (xmlSchemaModelGroupDefPtr) item);
4016 break;
4017 case XML_SCHEMA_TYPE_ANY:
4018 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4019 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4020 break;
4021 case XML_SCHEMA_TYPE_IDC_KEY:
4022 case XML_SCHEMA_TYPE_IDC_UNIQUE:
4023 case XML_SCHEMA_TYPE_IDC_KEYREF:
4024 xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4025 break;
4026 case XML_SCHEMA_TYPE_NOTATION:
4027 xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4028 break;
4029 case XML_SCHEMA_EXTRA_QNAMEREF:
4030 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4031 break;
4032 default: {
4033 /* TODO: This should never be hit. */
4034 xmlSchemaPSimpleInternalErr(NULL,
4035 "Internal error: xmlSchemaComponentListFree, "
4036 "unexpected component type '%s'\n",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004037 (const xmlChar *) WXS_ITEM_TYPE_NAME(item));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004038 }
4039 break;
4040 }
4041 }
4042 list->nbItems = 0;
4043 }
4044}
4045
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004046/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004047 * xmlSchemaFree:
4048 * @schema: a schema structure
4049 *
4050 * Deallocate a Schema structure.
4051 */
4052void
4053xmlSchemaFree(xmlSchemaPtr schema)
4054{
4055 if (schema == NULL)
4056 return;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004057 /* @volatiles is not used anymore :-/ */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004058 if (schema->volatiles != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004059 TODO
4060 /*
4061 * Note that those slots are not responsible for freeing
4062 * schema components anymore; this will now be done by
4063 * the schema buckets.
4064 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004065 if (schema->notaDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004066 xmlHashFree(schema->notaDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004067 if (schema->attrDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004068 xmlHashFree(schema->attrDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004069 if (schema->attrgrpDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004070 xmlHashFree(schema->attrgrpDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004071 if (schema->elemDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004072 xmlHashFree(schema->elemDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004073 if (schema->typeDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004074 xmlHashFree(schema->typeDecl, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004075 if (schema->groupDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004076 xmlHashFree(schema->groupDecl, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004077 if (schema->idcDef != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004078 xmlHashFree(schema->idcDef, NULL);
4079
Daniel Veillard1d913862003-11-21 00:28:39 +00004080 if (schema->schemasImports != NULL)
4081 xmlHashFree(schema->schemasImports,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004082 (xmlHashDeallocator) xmlSchemaBucketFree);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004083 if (schema->includes != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004084 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4085 int i;
4086 for (i = 0; i < list->nbItems; i++) {
4087 xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4088 }
4089 xmlSchemaItemListFree(list);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004090 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004091 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004092 xmlSchemaFreeAnnot(schema->annot);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004093 /* Never free the doc here, since this will be done by the buckets. */
4094
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004095 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004096 xmlFree(schema);
4097}
4098
4099/************************************************************************
4100 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00004101 * Debug functions *
4102 * *
4103 ************************************************************************/
4104
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00004105#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004106
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004107static void
4108xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4109
Daniel Veillard4255d502002-04-16 15:50:10 +00004110/**
4111 * xmlSchemaElementDump:
4112 * @elem: an element
4113 * @output: the file output
4114 *
4115 * Dump the element
4116 */
4117static void
4118xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004119 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004120 const xmlChar * namespace ATTRIBUTE_UNUSED,
4121 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00004122{
4123 if (elem == NULL)
4124 return;
4125
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004126
4127 fprintf(output, "Element");
4128 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4129 fprintf(output, " (global)");
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004130 fprintf(output, ": '%s' ", elem->name);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004131 if (namespace != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004132 fprintf(output, "ns '%s'", namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004133 fprintf(output, "\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004134#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004135 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004136 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004137 if (elem->maxOccurs >= UNBOUNDED)
4138 fprintf(output, "max: unbounded\n");
4139 else if (elem->maxOccurs != 1)
4140 fprintf(output, "max: %d\n", elem->maxOccurs);
4141 else
4142 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00004143 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004144#endif
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004145 /*
4146 * Misc other properties.
4147 */
4148 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4149 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4150 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004151 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004152 fprintf(output, " props: ");
4153 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4154 fprintf(output, "[fixed] ");
4155 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4156 fprintf(output, "[default] ");
4157 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4158 fprintf(output, "[abstract] ");
4159 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4160 fprintf(output, "[nillable] ");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004161 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00004162 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004163 /*
4164 * Default/fixed value.
4165 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004166 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004167 fprintf(output, " value: '%s'\n", elem->value);
4168 /*
4169 * Type.
4170 */
4171 if (elem->namedType != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004172 fprintf(output, " type: '%s' ", elem->namedType);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004173 if (elem->namedTypeNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004174 fprintf(output, "ns '%s'\n", elem->namedTypeNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004175 else
4176 fprintf(output, "\n");
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004177 } else if (elem->subtypes != NULL) {
4178 /*
4179 * Dump local types.
4180 */
4181 xmlSchemaTypeDump(elem->subtypes, output);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004182 }
4183 /*
4184 * Substitution group.
4185 */
4186 if (elem->substGroup != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004187 fprintf(output, " substitutionGroup: '%s' ", elem->substGroup);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004188 if (elem->substGroupNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004189 fprintf(output, "ns '%s'\n", elem->substGroupNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004190 else
4191 fprintf(output, "\n");
4192 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004193}
4194
4195/**
4196 * xmlSchemaAnnotDump:
4197 * @output: the file output
4198 * @annot: a annotation
4199 *
4200 * Dump the annotation
4201 */
4202static void
4203xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4204{
4205 xmlChar *content;
4206
4207 if (annot == NULL)
4208 return;
4209
4210 content = xmlNodeGetContent(annot->content);
4211 if (content != NULL) {
4212 fprintf(output, " Annot: %s\n", content);
4213 xmlFree(content);
4214 } else
4215 fprintf(output, " Annot: empty\n");
4216}
4217
4218/**
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004219 * xmlSchemaContentModelDump:
4220 * @particle: the schema particle
4221 * @output: the file output
4222 * @depth: the depth used for intentation
Daniel Veillard4255d502002-04-16 15:50:10 +00004223 *
4224 * Dump a SchemaType structure
4225 */
4226static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004227xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4228{
4229 xmlChar *str = NULL;
4230 xmlSchemaTreeItemPtr term;
4231 char shift[100];
4232 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004233
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004234 if (particle == NULL)
4235 return;
4236 for (i = 0;((i < depth) && (i < 25));i++)
4237 shift[2 * i] = shift[2 * i + 1] = ' ';
4238 shift[2 * i] = shift[2 * i + 1] = 0;
4239 fprintf(output, shift);
4240 if (particle->children == NULL) {
4241 fprintf(output, "MISSING particle term\n");
4242 return;
4243 }
4244 term = particle->children;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004245 if (term == NULL) {
4246 fprintf(output, "(NULL)");
4247 } else {
4248 switch (term->type) {
4249 case XML_SCHEMA_TYPE_ELEMENT:
4250 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4251 ((xmlSchemaElementPtr)term)->targetNamespace,
4252 ((xmlSchemaElementPtr)term)->name));
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004253 FREE_AND_NULL(str);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004254 break;
4255 case XML_SCHEMA_TYPE_SEQUENCE:
4256 fprintf(output, "SEQUENCE");
4257 break;
4258 case XML_SCHEMA_TYPE_CHOICE:
4259 fprintf(output, "CHOICE");
4260 break;
4261 case XML_SCHEMA_TYPE_ALL:
4262 fprintf(output, "ALL");
4263 break;
4264 case XML_SCHEMA_TYPE_ANY:
4265 fprintf(output, "ANY");
4266 break;
4267 default:
4268 fprintf(output, "UNKNOWN\n");
4269 return;
4270 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004271 }
4272 if (particle->minOccurs != 1)
4273 fprintf(output, " min: %d", particle->minOccurs);
4274 if (particle->maxOccurs >= UNBOUNDED)
4275 fprintf(output, " max: unbounded");
4276 else if (particle->maxOccurs != 1)
4277 fprintf(output, " max: %d", particle->maxOccurs);
4278 fprintf(output, "\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004279 if (term &&
4280 ((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4281 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4282 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4283 (term->children != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004284 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4285 output, depth +1);
4286 }
4287 if (particle->next != NULL)
4288 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4289 output, depth);
4290}
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004291
4292/**
4293 * xmlSchemaAttrUsesDump:
4294 * @uses: attribute uses list
4295 * @output: the file output
4296 *
4297 * Dumps a list of attribute use components.
4298 */
4299static void
4300xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4301{
4302 xmlSchemaAttributeUsePtr use;
4303 xmlSchemaAttributeUseProhibPtr prohib;
4304 xmlSchemaQNameRefPtr ref;
4305 const xmlChar *name, *tns;
4306 xmlChar *str = NULL;
4307 int i;
4308
4309 if ((uses == NULL) || (uses->nbItems == 0))
4310 return;
4311
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004312 fprintf(output, " attributes:\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004313 for (i = 0; i < uses->nbItems; i++) {
4314 use = uses->items[i];
4315 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4316 fprintf(output, " [prohibition] ");
4317 prohib = (xmlSchemaAttributeUseProhibPtr) use;
4318 name = prohib->name;
4319 tns = prohib->targetNamespace;
4320 } else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4321 fprintf(output, " [reference] ");
4322 ref = (xmlSchemaQNameRefPtr) use;
4323 name = ref->name;
4324 tns = ref->targetNamespace;
4325 } else {
4326 fprintf(output, " [use] ");
4327 name = WXS_ATTRUSE_DECL_NAME(use);
4328 tns = WXS_ATTRUSE_DECL_TNS(use);
4329 }
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004330 fprintf(output, "'%s'\n",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004331 (const char *) xmlSchemaFormatQName(&str, tns, name));
4332 FREE_AND_NULL(str);
4333 }
4334}
4335
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004336/**
4337 * xmlSchemaTypeDump:
4338 * @output: the file output
4339 * @type: a type structure
4340 *
4341 * Dump a SchemaType structure
4342 */
4343static void
Daniel Veillard4255d502002-04-16 15:50:10 +00004344xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4345{
4346 if (type == NULL) {
4347 fprintf(output, "Type: NULL\n");
4348 return;
4349 }
4350 fprintf(output, "Type: ");
4351 if (type->name != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004352 fprintf(output, "'%s' ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004353 else
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004354 fprintf(output, "(no name) ");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004355 if (type->targetNamespace != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004356 fprintf(output, "ns '%s' ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004357 switch (type->type) {
4358 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004359 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004360 break;
4361 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004362 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004363 break;
4364 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004365 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004366 break;
4367 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004368 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004369 break;
4370 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004371 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004372 break;
4373 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004374 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004375 break;
4376 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004377 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004378 break;
4379 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004380 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004381 break;
4382 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004383 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004384 break;
4385 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004386 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00004387 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004388 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004389 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004390 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004391 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004392 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004393 break;
4394 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004395 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004396 break;
4397 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004398 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004399 break;
4400 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004401 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004402 break;
4403 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004404 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004405 break;
4406 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004407 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004408 break;
4409 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004410 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004411 break;
4412 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004413 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004414 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00004415 }
4416 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004417 if (type->base != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004418 fprintf(output, " base type: '%s'", type->base);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004419 if (type->baseNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004420 fprintf(output, " ns '%s'\n", type->baseNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004421 else
4422 fprintf(output, "\n");
4423 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004424 if (type->attrUses != NULL)
4425 xmlSchemaAttrUsesDump(type->attrUses, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00004426 if (type->annot != NULL)
4427 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004428#ifdef DUMP_CONTENT_MODEL
4429 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4430 (type->subtypes != NULL)) {
4431 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4432 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004433 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004434#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004435}
4436
4437/**
4438 * xmlSchemaDump:
4439 * @output: the file output
4440 * @schema: a schema structure
4441 *
4442 * Dump a Schema structure.
4443 */
4444void
4445xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4446{
Daniel Veillardce682bc2004-11-05 17:22:25 +00004447 if (output == NULL)
4448 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004449 if (schema == NULL) {
4450 fprintf(output, "Schemas: NULL\n");
4451 return;
4452 }
4453 fprintf(output, "Schemas: ");
4454 if (schema->name != NULL)
4455 fprintf(output, "%s, ", schema->name);
4456 else
4457 fprintf(output, "no name, ");
4458 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00004459 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004460 else
4461 fprintf(output, "no target namespace");
4462 fprintf(output, "\n");
4463 if (schema->annot != NULL)
4464 xmlSchemaAnnotDump(output, schema->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00004465 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
4466 output);
4467 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004468 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00004469}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004470
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004471#ifdef DEBUG_IDC_NODE_TABLE
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004472/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004473 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004474 * @vctxt: the WXS validation context
4475 *
4476 * Displays the current IDC table for debug purposes.
4477 */
4478static void
4479xmlSchemaDebugDumpIDCTable(FILE * output,
4480 const xmlChar *namespaceName,
4481 const xmlChar *localName,
4482 xmlSchemaPSVIIDCBindingPtr bind)
4483{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004484 xmlChar *str = NULL;
4485 const xmlChar *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004486 xmlSchemaPSVIIDCNodePtr tab;
4487 xmlSchemaPSVIIDCKeyPtr key;
4488 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004489
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004490 fprintf(output, "IDC: TABLES on '%s'\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004491 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004492 FREE_AND_NULL(str)
4493
4494 if (bind == NULL)
4495 return;
4496 do {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004497 fprintf(output, "IDC: BINDING '%s' (%d)\n",
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004498 xmlSchemaGetComponentQName(&str,
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004499 bind->definition), bind->nbNodes);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004500 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004501 for (i = 0; i < bind->nbNodes; i++) {
4502 tab = bind->nodeTable[i];
4503 fprintf(output, " ( ");
4504 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004505 key = tab->keys[j];
4506 if ((key != NULL) && (key->val != NULL)) {
4507 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004508 if (res >= 0)
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004509 fprintf(output, "'%s' ", value);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004510 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004511 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004512 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004513 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004514 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004515 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004516 else
4517 fprintf(output, "(key missing), ");
4518 }
4519 fprintf(output, ")\n");
4520 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004521 if (bind->dupls && bind->dupls->nbItems) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004522 fprintf(output, "IDC: dupls (%d):\n", bind->dupls->nbItems);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004523 for (i = 0; i < bind->dupls->nbItems; i++) {
4524 tab = bind->dupls->items[i];
4525 fprintf(output, " ( ");
4526 for (j = 0; j < bind->definition->nbFields; j++) {
4527 key = tab->keys[j];
4528 if ((key != NULL) && (key->val != NULL)) {
4529 res = xmlSchemaGetCanonValue(key->val, &value);
4530 if (res >= 0)
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004531 fprintf(output, "'%s' ", value);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004532 else
4533 fprintf(output, "CANON-VALUE-FAILED ");
4534 if (res == 0)
4535 FREE_AND_NULL(value)
4536 } else if (key != NULL)
4537 fprintf(output, "(no val), ");
4538 else
4539 fprintf(output, "(key missing), ");
4540 }
4541 fprintf(output, ")\n");
4542 }
4543 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004544 bind = bind->next;
4545 } while (bind != NULL);
4546}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00004547#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00004548#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00004549
4550/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004551 * *
4552 * Utilities *
4553 * *
4554 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004555
Daniel Veillardc0826a72004-08-10 14:17:33 +00004556/**
4557 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004558 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00004559 * @name: the name of the attribute
4560 *
4561 * Seeks an attribute with a name of @name in
4562 * no namespace.
4563 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004564 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00004565 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004566static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004567xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00004568{
4569 xmlAttrPtr prop;
4570
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004571 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004572 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004573 prop = node->properties;
4574 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004575 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004576 return(prop);
4577 prop = prop->next;
4578 }
4579 return (NULL);
4580}
4581
4582/**
4583 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004584 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00004585 * @uri: the uri
4586 * @name: the name of the attribute
4587 *
4588 * Seeks an attribute with a local name of @name and
4589 * a namespace URI of @uri.
4590 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004591 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00004592 */
4593static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004594xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00004595{
4596 xmlAttrPtr prop;
4597
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004598 if ((node == NULL) || (name == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004599 return(NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004600 prop = node->properties;
4601 while (prop != NULL) {
4602 if ((prop->ns != NULL) &&
4603 xmlStrEqual(prop->name, BAD_CAST name) &&
4604 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00004605 return(prop);
4606 prop = prop->next;
4607 }
4608 return (NULL);
4609}
4610
4611static const xmlChar *
4612xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4613{
4614 xmlChar *val;
4615 const xmlChar *ret;
4616
4617 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004618 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00004619 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00004620 ret = xmlDictLookup(ctxt->dict, val, -1);
4621 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004622 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004623}
4624
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004625static const xmlChar *
4626xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4627{
4628 return((const xmlChar*) xmlNodeGetContent(node));
4629}
4630
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004631/**
4632 * xmlSchemaGetProp:
4633 * @ctxt: the parser context
4634 * @node: the node
4635 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004636 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004637 * Read a attribute value and internalize the string
4638 *
4639 * Returns the string or NULL if not present.
4640 */
4641static const xmlChar *
4642xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4643 const char *name)
4644{
4645 xmlChar *val;
4646 const xmlChar *ret;
4647
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004648 val = xmlGetNoNsProp(node, BAD_CAST name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004649 if (val == NULL)
4650 return(NULL);
4651 ret = xmlDictLookup(ctxt->dict, val, -1);
4652 xmlFree(val);
4653 return(ret);
4654}
4655
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004656/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00004657 * *
4658 * Parsing functions *
4659 * *
4660 ************************************************************************/
4661
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004662#define WXS_FIND_GLOBAL_ITEM(slot) \
4663 if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4664 ret = xmlHashLookup(schema->slot, name); \
4665 if (ret != NULL) goto exit; \
4666 } \
4667 if (xmlHashSize(schema->schemasImports) > 1) { \
4668 xmlSchemaImportPtr import; \
4669 if (nsName == NULL) \
4670 import = xmlHashLookup(schema->schemasImports, \
4671 XML_SCHEMAS_NO_NAMESPACE); \
4672 else \
4673 import = xmlHashLookup(schema->schemasImports, nsName); \
4674 if (import == NULL) \
4675 goto exit; \
4676 ret = xmlHashLookup(import->schema->slot, name); \
4677 }
4678
Daniel Veillard4255d502002-04-16 15:50:10 +00004679/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004680 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004681 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004682 * @name: the element name
4683 * @ns: the element namespace
4684 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004685 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004686 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004687 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004688 */
4689static xmlSchemaElementPtr
4690xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004691 const xmlChar * nsName)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004692{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004693 xmlSchemaElementPtr ret = NULL;
4694
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004695 if ((name == NULL) || (schema == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004696 return(NULL);
4697 if (schema != NULL) {
4698 WXS_FIND_GLOBAL_ITEM(elemDecl)
4699 }
4700exit:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004701#ifdef DEBUG
4702 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004703 if (nsName == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004704 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004705 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004706 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004707 nsName);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004708 }
4709#endif
4710 return (ret);
4711}
4712
4713/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004714 * xmlSchemaGetType:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004715 * @schema: the main schema
4716 * @name: the type's name
4717 * nsName: the type's namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004718 *
4719 * Lookup a type in the schemas or the predefined types
4720 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004721 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00004722 */
4723static xmlSchemaTypePtr
4724xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004725 const xmlChar * nsName)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004726{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004727 xmlSchemaTypePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004728
4729 if (name == NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004730 return (NULL);
4731 /* First try the built-in types. */
4732 if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4733 ret = xmlSchemaGetPredefinedType(name, nsName);
4734 if (ret != NULL)
4735 goto exit;
4736 /*
4737 * Note that we try the parsed schemas as well here
4738 * since one might have parsed the S4S, which contain more
4739 * than the built-in types.
4740 * TODO: Can we optimize this?
4741 */
4742 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004743 if (schema != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004744 WXS_FIND_GLOBAL_ITEM(typeDecl)
4745 }
4746exit:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004747
Daniel Veillard4255d502002-04-16 15:50:10 +00004748#ifdef DEBUG
4749 if (ret == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004750 if (nsName == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004751 fprintf(stderr, "Unable to lookup type %s", name);
4752 else
4753 fprintf(stderr, "Unable to lookup type %s:%s", name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004754 nsName);
Daniel Veillard4255d502002-04-16 15:50:10 +00004755 }
4756#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004757 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004758}
4759
Daniel Veillard3646d642004-06-02 19:19:14 +00004760/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004761 * xmlSchemaGetAttributeDecl:
4762 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004763 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004764 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004765 *
4766 * Lookup a an attribute in the schema or imported schemas
4767 *
4768 * Returns the attribute declaration or NULL if not found.
4769 */
4770static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004771xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004772 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004773{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004774 xmlSchemaAttributePtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004775
4776 if ((name == NULL) || (schema == NULL))
4777 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004778 if (schema != NULL) {
4779 WXS_FIND_GLOBAL_ITEM(attrDecl)
Daniel Veillard3646d642004-06-02 19:19:14 +00004780 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004781exit:
Daniel Veillard3646d642004-06-02 19:19:14 +00004782#ifdef DEBUG
4783 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004784 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004785 fprintf(stderr, "Unable to lookup attribute %s", name);
4786 else
4787 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004788 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004789 }
4790#endif
4791 return (ret);
4792}
4793
4794/**
4795 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004796 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004797 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004798 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004799 *
4800 * Lookup a an attribute group in the schema or imported schemas
4801 *
4802 * Returns the attribute group definition or NULL if not found.
4803 */
4804static xmlSchemaAttributeGroupPtr
4805xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004806 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004807{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004808 xmlSchemaAttributeGroupPtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004809
4810 if ((name == NULL) || (schema == NULL))
4811 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004812 if (schema != NULL) {
4813 WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4814 }
4815exit:
4816 /* TODO:
4817 if ((ret != NULL) && (ret->redef != NULL)) {
4818 * Return the last redefinition. *
4819 ret = ret->redef;
Daniel Veillard3646d642004-06-02 19:19:14 +00004820 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004821 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004822#ifdef DEBUG
4823 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004824 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004825 fprintf(stderr, "Unable to lookup attribute group %s", name);
4826 else
4827 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004828 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004829 }
4830#endif
4831 return (ret);
4832}
4833
4834/**
4835 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004836 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004837 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004838 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004839 *
4840 * Lookup a group in the schema or imported schemas
4841 *
4842 * Returns the group definition or NULL if not found.
4843 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004844static xmlSchemaModelGroupDefPtr
Daniel Veillard3646d642004-06-02 19:19:14 +00004845xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004846 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004847{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004848 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004849
4850 if ((name == NULL) || (schema == NULL))
4851 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004852 if (schema != NULL) {
4853 WXS_FIND_GLOBAL_ITEM(groupDecl)
Daniel Veillard3646d642004-06-02 19:19:14 +00004854 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004855exit:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004856
Daniel Veillard3646d642004-06-02 19:19:14 +00004857#ifdef DEBUG
4858 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004859 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004860 fprintf(stderr, "Unable to lookup group %s", name);
4861 else
4862 fprintf(stderr, "Unable to lookup group %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004863 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004864 }
4865#endif
4866 return (ret);
4867}
4868
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004869static xmlSchemaNotationPtr
4870xmlSchemaGetNotation(xmlSchemaPtr schema,
4871 const xmlChar *name,
4872 const xmlChar *nsName)
4873{
4874 xmlSchemaNotationPtr ret = NULL;
4875
4876 if ((name == NULL) || (schema == NULL))
4877 return (NULL);
4878 if (schema != NULL) {
4879 WXS_FIND_GLOBAL_ITEM(notaDecl)
4880 }
4881exit:
4882 return (ret);
4883}
4884
4885static xmlSchemaIDCPtr
4886xmlSchemaGetIDC(xmlSchemaPtr schema,
4887 const xmlChar *name,
4888 const xmlChar *nsName)
4889{
4890 xmlSchemaIDCPtr ret = NULL;
4891
4892 if ((name == NULL) || (schema == NULL))
4893 return (NULL);
4894 if (schema != NULL) {
4895 WXS_FIND_GLOBAL_ITEM(idcDef)
4896 }
4897exit:
4898 return (ret);
4899}
4900
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004901/**
4902 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004903 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004904 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004905 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004906 *
4907 * Lookup a group in the schema or imported schemas
4908 *
4909 * Returns the group definition or NULL if not found.
4910 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004911static xmlSchemaBasicItemPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004912xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4913 xmlSchemaTypeType itemType,
4914 const xmlChar *name,
4915 const xmlChar *targetNs)
4916{
4917 switch (itemType) {
4918 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004919 return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004920 name, targetNs));
4921 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004922 return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004923 name, targetNs));
4924 default:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004925 TODO
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004926 return (NULL);
4927 }
4928}
4929
Daniel Veillard4255d502002-04-16 15:50:10 +00004930/************************************************************************
4931 * *
4932 * Parsing functions *
4933 * *
4934 ************************************************************************/
4935
4936#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004937 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00004938
4939/**
4940 * xmlSchemaIsBlank:
4941 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004942 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00004943 *
4944 * Check if a string is ignorable
4945 *
4946 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4947 */
4948static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004949xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004950{
Daniel Veillard4255d502002-04-16 15:50:10 +00004951 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004952 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004953 if (len < 0) {
4954 while (*str != 0) {
4955 if (!(IS_BLANK_CH(*str)))
4956 return (0);
4957 str++;
4958 }
4959 } else while ((*str != 0) && (len != 0)) {
4960 if (!(IS_BLANK_CH(*str)))
4961 return (0);
4962 str++;
4963 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00004964 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004965
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004966 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004967}
4968
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004969#define WXS_COMP_NAME(c, t) ((t) (c))->name
4970#define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
4971/*
4972* xmlSchemaFindRedefCompInGraph:
4973* ATTENTION TODO: This uses pointer comp. for strings.
4974*/
4975static xmlSchemaBasicItemPtr
4976xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
4977 xmlSchemaTypeType type,
4978 const xmlChar *name,
4979 const xmlChar *nsName)
4980{
4981 xmlSchemaBasicItemPtr ret;
4982 int i;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004983
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004984 if ((bucket == NULL) || (name == NULL))
4985 return(NULL);
4986 if ((bucket->globals == NULL) ||
4987 (bucket->globals->nbItems == 0))
4988 goto subschemas;
4989 /*
4990 * Search in global components.
4991 */
4992 for (i = 0; i < bucket->globals->nbItems; i++) {
4993 ret = bucket->globals->items[i];
4994 if (ret->type == type) {
4995 switch (type) {
4996 case XML_SCHEMA_TYPE_COMPLEX:
4997 case XML_SCHEMA_TYPE_SIMPLE:
4998 if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
4999 (WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5000 nsName))
5001 {
5002 return(ret);
5003 }
5004 break;
5005 case XML_SCHEMA_TYPE_GROUP:
5006 if ((WXS_COMP_NAME(ret,
5007 xmlSchemaModelGroupDefPtr) == name) &&
5008 (WXS_COMP_TNS(ret,
5009 xmlSchemaModelGroupDefPtr) == nsName))
5010 {
5011 return(ret);
5012 }
5013 break;
5014 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5015 if ((WXS_COMP_NAME(ret,
5016 xmlSchemaAttributeGroupPtr) == name) &&
5017 (WXS_COMP_TNS(ret,
5018 xmlSchemaAttributeGroupPtr) == nsName))
5019 {
5020 return(ret);
5021 }
Kasimier T. Buchcik5d2998b2005-11-22 17:36:01 +00005022 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005023 default:
5024 /* Should not be hit. */
5025 return(NULL);
5026 }
5027 }
5028 }
5029subschemas:
5030 /*
5031 * Process imported/included schemas.
5032 */
5033 if (bucket->relations != NULL) {
5034 xmlSchemaSchemaRelationPtr rel = bucket->relations;
5035
5036 /*
5037 * TODO: Marking the bucket will not avoid multiple searches
5038 * in the same schema, but avoids at least circularity.
5039 */
5040 bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5041 do {
5042 if ((rel->bucket != NULL) &&
5043 ((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5044 ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5045 type, name, nsName);
5046 if (ret != NULL)
5047 return(ret);
5048 }
5049 rel = rel->next;
5050 } while (rel != NULL);
5051 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5052 }
5053 return(NULL);
5054}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005055
5056/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005057 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005058 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005059 * @schema: the schema being built
5060 * @name: the item name
5061 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005062 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00005063 * *WARNING* this interface is highly subject to change
5064 *
5065 * Returns the new struture or NULL in case of error
5066 */
5067static xmlSchemaNotationPtr
5068xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005069 const xmlChar *name, const xmlChar *nsName,
5070 xmlNodePtr node ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00005071{
5072 xmlSchemaNotationPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005073
5074 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5075 return (NULL);
5076
Daniel Veillard4255d502002-04-16 15:50:10 +00005077 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5078 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005079 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005080 return (NULL);
5081 }
5082 memset(ret, 0, sizeof(xmlSchemaNotation));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005083 ret->type = XML_SCHEMA_TYPE_NOTATION;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005084 ret->name = name;
5085 ret->targetNamespace = nsName;
5086 /* TODO: do we need the node to be set?
5087 * ret->node = node;*/
5088 WXS_ADD_GLOBAL(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005089 return (ret);
5090}
5091
Daniel Veillard4255d502002-04-16 15:50:10 +00005092/**
5093 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005094 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005095 * @schema: the schema being built
5096 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005097 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005098 *
5099 * Add an XML schema Attrribute declaration
5100 * *WARNING* this interface is highly subject to change
5101 *
5102 * Returns the new struture or NULL in case of error
5103 */
5104static xmlSchemaAttributePtr
5105xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005106 const xmlChar * name, const xmlChar * nsName,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005107 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005108{
5109 xmlSchemaAttributePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005110
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005111 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005112 return (NULL);
5113
5114 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5115 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005116 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005117 return (NULL);
5118 }
5119 memset(ret, 0, sizeof(xmlSchemaAttribute));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005120 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5121 ret->node = node;
5122 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005123 ret->targetNamespace = nsName;
5124
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005125 if (topLevel)
5126 WXS_ADD_GLOBAL(ctxt, ret);
5127 else
5128 WXS_ADD_LOCAL(ctxt, ret);
5129 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005130 return (ret);
5131}
5132
5133/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005134 * xmlSchemaAddAttributeUse:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005135 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005136 * @schema: the schema being built
5137 * @name: the item name
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005138 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005139 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005140 * Add an XML schema Attrribute declaration
5141 * *WARNING* this interface is highly subject to change
5142 *
5143 * Returns the new struture or NULL in case of error
5144 */
5145static xmlSchemaAttributeUsePtr
5146xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5147 xmlNodePtr node)
5148{
5149 xmlSchemaAttributeUsePtr ret = NULL;
5150
5151 if (pctxt == NULL)
5152 return (NULL);
5153
5154 ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5155 if (ret == NULL) {
5156 xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5157 return (NULL);
5158 }
5159 memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5160 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5161 ret->node = node;
5162
5163 WXS_ADD_LOCAL(pctxt, ret);
5164 return (ret);
5165}
5166
5167/*
5168* xmlSchemaAddRedef:
5169*
5170* Adds a redefinition information. This is used at a later stage to:
5171* resolve references to the redefined components and to check constraints.
5172*/
5173static xmlSchemaRedefPtr
5174xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5175 xmlSchemaBucketPtr targetBucket,
5176 void *item,
5177 const xmlChar *refName,
5178 const xmlChar *refTargetNs)
5179{
5180 xmlSchemaRedefPtr ret;
5181
5182 ret = (xmlSchemaRedefPtr)
5183 xmlMalloc(sizeof(xmlSchemaRedef));
5184 if (ret == NULL) {
5185 xmlSchemaPErrMemory(pctxt,
5186 "allocating redefinition info", NULL);
5187 return (NULL);
5188 }
5189 memset(ret, 0, sizeof(xmlSchemaRedef));
5190 ret->item = item;
5191 ret->targetBucket = targetBucket;
5192 ret->refName = refName;
5193 ret->refTargetNs = refTargetNs;
5194 if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5195 WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5196 else
5197 WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5198 WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5199
5200 return (ret);
5201}
5202
5203/**
5204 * xmlSchemaAddAttributeGroupDefinition:
5205 * @ctxt: a schema parser context
5206 * @schema: the schema being built
5207 * @name: the item name
5208 * @nsName: the target namespace
5209 * @node: the corresponding node
5210 *
5211 * Add an XML schema Attrribute Group definition.
Daniel Veillard4255d502002-04-16 15:50:10 +00005212 *
5213 * Returns the new struture or NULL in case of error
5214 */
5215static xmlSchemaAttributeGroupPtr
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005216xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5217 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5218 const xmlChar *name,
5219 const xmlChar *nsName,
5220 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005221{
5222 xmlSchemaAttributeGroupPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005223
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005224 if ((pctxt == NULL) || (name == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005225 return (NULL);
5226
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005227 ret = (xmlSchemaAttributeGroupPtr)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005228 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00005229 if (ret == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005230 xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005231 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005232 }
5233 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005234 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005235 ret->name = name;
5236 ret->targetNamespace = nsName;
5237 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005238
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005239 /* TODO: Remove the flag. */
5240 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5241 if (pctxt->isRedefine) {
5242 pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5243 ret, name, nsName);
5244 if (pctxt->redef == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005245 xmlFree(ret);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005246 return(NULL);
5247 }
5248 pctxt->redefCounter = 0;
5249 }
5250 WXS_ADD_GLOBAL(pctxt, ret);
5251 WXS_ADD_PENDING(pctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005252 return (ret);
5253}
5254
5255/**
5256 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005257 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005258 * @schema: the schema being built
5259 * @name: the type name
5260 * @namespace: the type namespace
5261 *
5262 * Add an XML schema Element declaration
5263 * *WARNING* this interface is highly subject to change
5264 *
5265 * Returns the new struture or NULL in case of error
5266 */
5267static xmlSchemaElementPtr
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005268xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005269 const xmlChar * name, const xmlChar * nsName,
William M. Brack2f2a6632004-08-20 23:09:47 +00005270 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005271{
5272 xmlSchemaElementPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005273
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005274 if ((ctxt == NULL) || (name == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005275 return (NULL);
5276
Daniel Veillard4255d502002-04-16 15:50:10 +00005277 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5278 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005279 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005280 return (NULL);
5281 }
5282 memset(ret, 0, sizeof(xmlSchemaElement));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005283 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5284 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005285 ret->targetNamespace = nsName;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005286 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005287
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005288 if (topLevel)
5289 WXS_ADD_GLOBAL(ctxt, ret);
5290 else
5291 WXS_ADD_LOCAL(ctxt, ret);
5292 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005293 return (ret);
5294}
5295
5296/**
5297 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00005298 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005299 * @schema: the schema being built
5300 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005301 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005302 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005303 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00005304 * *WARNING* this interface is highly subject to change
5305 *
5306 * Returns the new struture or NULL in case of error
5307 */
5308static xmlSchemaTypePtr
5309xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005310 xmlSchemaTypeType type,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00005311 const xmlChar * name, const xmlChar * nsName,
5312 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005313{
5314 xmlSchemaTypePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005315
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005316 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005317 return (NULL);
5318
5319 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5320 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005321 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005322 return (NULL);
5323 }
5324 memset(ret, 0, sizeof(xmlSchemaType));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005325 ret->type = type;
5326 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005327 ret->targetNamespace = nsName;
5328 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005329 if (topLevel) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005330 if (ctxt->isRedefine) {
5331 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5332 ret, name, nsName);
5333 if (ctxt->redef == NULL) {
5334 xmlFree(ret);
5335 return(NULL);
5336 }
5337 ctxt->redefCounter = 0;
5338 }
5339 WXS_ADD_GLOBAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005340 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005341 WXS_ADD_LOCAL(ctxt, ret);
5342 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005343 return (ret);
5344}
5345
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005346static xmlSchemaQNameRefPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005347xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005348 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005349 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005350 const xmlChar *refNs)
5351{
5352 xmlSchemaQNameRefPtr ret;
5353
5354 ret = (xmlSchemaQNameRefPtr)
5355 xmlMalloc(sizeof(xmlSchemaQNameRef));
5356 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005357 xmlSchemaPErrMemory(pctxt,
5358 "allocating QName reference item", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005359 return (NULL);
5360 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005361 ret->node = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005362 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5363 ret->name = refName;
5364 ret->targetNamespace = refNs;
5365 ret->item = NULL;
5366 ret->itemType = refType;
5367 /*
5368 * Store the reference item in the schema.
5369 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005370 WXS_ADD_LOCAL(pctxt, ret);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005371 return (ret);
5372}
5373
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005374static xmlSchemaAttributeUseProhibPtr
5375xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5376{
5377 xmlSchemaAttributeUseProhibPtr ret;
5378
5379 ret = (xmlSchemaAttributeUseProhibPtr)
5380 xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5381 if (ret == NULL) {
5382 xmlSchemaPErrMemory(pctxt,
5383 "allocating attribute use prohibition", NULL);
5384 return (NULL);
5385 }
5386 memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5387 ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5388 WXS_ADD_LOCAL(pctxt, ret);
5389 return (ret);
5390}
5391
5392
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005393/**
5394 * xmlSchemaAddModelGroup:
5395 * @ctxt: a schema parser context
5396 * @schema: the schema being built
5397 * @type: the "compositor" type of the model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005398 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005399 *
5400 * Adds a schema model group
5401 * *WARNING* this interface is highly subject to change
5402 *
5403 * Returns the new struture or NULL in case of error
5404 */
5405static xmlSchemaModelGroupPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005406xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5407 xmlSchemaPtr schema,
5408 xmlSchemaTypeType type,
5409 xmlNodePtr node)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005410{
5411 xmlSchemaModelGroupPtr ret = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005412
5413 if ((ctxt == NULL) || (schema == NULL))
5414 return (NULL);
5415
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005416 ret = (xmlSchemaModelGroupPtr)
5417 xmlMalloc(sizeof(xmlSchemaModelGroup));
5418 if (ret == NULL) {
5419 xmlSchemaPErrMemory(ctxt, "allocating model group component",
5420 NULL);
5421 return (NULL);
5422 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005423 memset(ret, 0, sizeof(xmlSchemaModelGroup));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005424 ret->type = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005425 ret->node = node;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005426 WXS_ADD_LOCAL(ctxt, ret);
5427 if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5428 (type == XML_SCHEMA_TYPE_CHOICE))
5429 WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005430 return (ret);
5431}
5432
5433
5434/**
5435 * xmlSchemaAddParticle:
5436 * @ctxt: a schema parser context
5437 * @schema: the schema being built
5438 * @node: the corresponding node in the schema doc
5439 * @min: the minOccurs
5440 * @max: the maxOccurs
5441 *
5442 * Adds an XML schema particle component.
5443 * *WARNING* this interface is highly subject to change
5444 *
5445 * Returns the new struture or NULL in case of error
5446 */
5447static xmlSchemaParticlePtr
5448xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5449 xmlNodePtr node, int min, int max)
5450{
5451 xmlSchemaParticlePtr ret = NULL;
5452 if ((ctxt == NULL) || (schema == NULL))
5453 return (NULL);
5454
5455#ifdef DEBUG
5456 fprintf(stderr, "Adding particle component\n");
5457#endif
5458 ret = (xmlSchemaParticlePtr)
5459 xmlMalloc(sizeof(xmlSchemaParticle));
5460 if (ret == NULL) {
5461 xmlSchemaPErrMemory(ctxt, "allocating particle component",
5462 NULL);
5463 return (NULL);
5464 }
5465 ret->type = XML_SCHEMA_TYPE_PARTICLE;
5466 ret->annot = NULL;
5467 ret->node = node;
5468 ret->minOccurs = min;
5469 ret->maxOccurs = max;
5470 ret->next = NULL;
5471 ret->children = NULL;
5472
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005473 WXS_ADD_LOCAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005474 /*
5475 * Note that addition to pending components will be done locally
5476 * to the specific parsing function, since the most particles
5477 * need not to be fixed up (i.e. the reference to be resolved).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005478 * REMOVED: WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005479 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005480 return (ret);
5481}
5482
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005483/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005484 * xmlSchemaAddModelGroupDefinition:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005485 * @ctxt: a schema validation context
5486 * @schema: the schema being built
5487 * @name: the group name
5488 *
5489 * Add an XML schema Group definition
5490 *
5491 * Returns the new struture or NULL in case of error
5492 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005493static xmlSchemaModelGroupDefPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005494xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5495 xmlSchemaPtr schema,
5496 const xmlChar *name,
5497 const xmlChar *nsName,
5498 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005499{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005500 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005501
5502 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5503 return (NULL);
5504
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005505 ret = (xmlSchemaModelGroupDefPtr)
5506 xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005507 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005508 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005509 return (NULL);
5510 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005511 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005512 ret->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005513 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005514 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005515 ret->targetNamespace = nsName;
5516
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005517 if (ctxt->isRedefine) {
5518 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5519 ret, name, nsName);
5520 if (ctxt->redef == NULL) {
5521 xmlFree(ret);
5522 return(NULL);
5523 }
5524 ctxt->redefCounter = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005525 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005526 WXS_ADD_GLOBAL(ctxt, ret);
5527 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005528 return (ret);
5529}
5530
Daniel Veillard3646d642004-06-02 19:19:14 +00005531/**
5532 * xmlSchemaNewWildcardNs:
5533 * @ctxt: a schema validation context
5534 *
5535 * Creates a new wildcard namespace constraint.
5536 *
5537 * Returns the new struture or NULL in case of error
5538 */
5539static xmlSchemaWildcardNsPtr
5540xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5541{
5542 xmlSchemaWildcardNsPtr ret;
5543
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005544 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005545 xmlMalloc(sizeof(xmlSchemaWildcardNs));
5546 if (ret == NULL) {
5547 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005548 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00005549 }
5550 ret->value = NULL;
5551 ret->next = NULL;
5552 return (ret);
5553}
5554
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005555static xmlSchemaIDCPtr
5556xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5557 const xmlChar *name, const xmlChar *nsName,
5558 int category, xmlNodePtr node)
5559{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005560 xmlSchemaIDCPtr ret = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005561
5562 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5563 return (NULL);
5564
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005565 ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5566 if (ret == NULL) {
5567 xmlSchemaPErrMemory(ctxt,
5568 "allocating an identity-constraint definition", NULL);
5569 return (NULL);
5570 }
5571 memset(ret, 0, sizeof(xmlSchemaIDC));
5572 /* The target namespace of the parent element declaration. */
5573 ret->targetNamespace = nsName;
5574 ret->name = name;
5575 ret->type = category;
5576 ret->node = node;
5577
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005578 WXS_ADD_GLOBAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005579 /*
5580 * Only keyrefs need to be fixup up.
5581 */
5582 if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005583 WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005584 return (ret);
5585}
5586
Daniel Veillard3646d642004-06-02 19:19:14 +00005587/**
5588 * xmlSchemaAddWildcard:
5589 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005590 * @schema: a schema
5591 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005592 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005593 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00005594 *
5595 * Returns the new struture or NULL in case of error
5596 */
5597static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005598xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5599 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00005600{
5601 xmlSchemaWildcardPtr ret = NULL;
5602
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005603 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00005604 return (NULL);
5605
5606 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5607 if (ret == NULL) {
5608 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5609 return (NULL);
5610 }
5611 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005612 ret->type = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005613 ret->node = node;
5614 WXS_ADD_LOCAL(ctxt, ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00005615 return (ret);
5616}
5617
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005618static void
5619xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5620{
5621 if (group == NULL)
5622 return;
5623 if (group->members != NULL)
5624 xmlSchemaItemListFree(group->members);
5625 xmlFree(group);
5626}
5627
5628static xmlSchemaSubstGroupPtr
5629xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5630 xmlSchemaElementPtr head)
5631{
5632 xmlSchemaSubstGroupPtr ret;
5633
5634 /* Init subst group hash. */
5635 if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5636 WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5637 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5638 return(NULL);
5639 }
5640 /* Create a new substitution group. */
5641 ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5642 if (ret == NULL) {
5643 xmlSchemaPErrMemory(NULL,
5644 "allocating a substitution group container", NULL);
5645 return(NULL);
5646 }
5647 memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5648 ret->head = head;
5649 /* Create list of members. */
5650 ret->members = xmlSchemaItemListCreate();
5651 if (ret->members == NULL) {
5652 xmlSchemaSubstGroupFree(ret);
5653 return(NULL);
5654 }
5655 /* Add subst group to hash. */
5656 if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5657 head->name, head->targetNamespace, ret) != 0) {
5658 PERROR_INT("xmlSchemaSubstGroupAdd",
5659 "failed to add a new substitution container");
5660 xmlSchemaSubstGroupFree(ret);
5661 return(NULL);
5662 }
5663 return(ret);
5664}
5665
5666static xmlSchemaSubstGroupPtr
5667xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5668 xmlSchemaElementPtr head)
5669{
5670 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5671 return(NULL);
5672 return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5673 head->name, head->targetNamespace));
5674
5675}
5676
5677/**
5678 * xmlSchemaAddElementSubstitutionMember:
5679 * @pctxt: a schema parser context
5680 * @head: the head of the substitution group
5681 * @member: the new member of the substitution group
5682 *
5683 * Allocate a new annotation structure.
5684 *
5685 * Returns the newly allocated structure or NULL in case or error
5686 */
5687static int
5688xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5689 xmlSchemaElementPtr head,
5690 xmlSchemaElementPtr member)
5691{
5692 xmlSchemaSubstGroupPtr substGroup = NULL;
5693
5694 if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5695 return (-1);
5696
5697 substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5698 if (substGroup == NULL)
5699 substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5700 if (substGroup == NULL)
5701 return(-1);
5702 if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5703 return(-1);
5704 return(0);
5705}
5706
Daniel Veillard4255d502002-04-16 15:50:10 +00005707/************************************************************************
5708 * *
5709 * Utilities for parsing *
5710 * *
5711 ************************************************************************/
5712
Daniel Veillard4255d502002-04-16 15:50:10 +00005713/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005714 * xmlSchemaPValAttrNodeQNameValue:
5715 * @ctxt: a schema parser context
5716 * @schema: the schema context
5717 * @ownerDes: the designation of the parent element
5718 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005719 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00005720 * @local: the resulting local part if found, the attribute value otherwise
5721 * @uri: the resulting namespace URI if found
5722 *
5723 * Extracts the local name and the URI of a QName value and validates it.
5724 * This one is intended to be used on attribute values that
5725 * should resolve to schema components.
5726 *
5727 * Returns 0, in case the QName is valid, a positive error code
5728 * if not valid and -1 if an internal error occurs.
5729 */
5730static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005731xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005732 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005733 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005734 xmlAttrPtr attr,
5735 const xmlChar *value,
5736 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005737 const xmlChar **local)
5738{
5739 const xmlChar *pref;
5740 xmlNsPtr ns;
5741 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005742
Daniel Veillardc0826a72004-08-10 14:17:33 +00005743 *uri = NULL;
5744 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005745 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005746 if (ret > 0) {
5747 xmlSchemaPSimpleTypeErr(ctxt,
5748 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5749 ownerItem, (xmlNodePtr) attr,
5750 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5751 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005752 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005753 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005754 } else if (ret < 0)
5755 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005756
5757 if (!strchr((char *) value, ':')) {
Daniel Veillard24505b02005-07-28 23:49:35 +00005758 ns = xmlSearchNs(attr->doc, attr->parent, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005759 if (ns)
5760 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5761 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005762 /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5763 * parser context. */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005764 /*
5765 * This one takes care of included schemas with no
5766 * target namespace.
5767 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005768 *uri = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005769 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005770 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005771 return (0);
5772 }
5773 /*
5774 * At this point xmlSplitQName3 has to return a local name.
5775 */
5776 *local = xmlSplitQName3(value, &len);
5777 *local = xmlDictLookup(ctxt->dict, *local, -1);
5778 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005779 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5780 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005781 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005782 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005783 ownerItem, (xmlNodePtr) attr,
5784 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5785 "The value '%s' of simple type 'xs:QName' has no "
5786 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005787 return (ctxt->err);
5788 } else {
5789 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005790 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005791 return (0);
5792}
5793
5794/**
5795 * xmlSchemaPValAttrNodeQName:
5796 * @ctxt: a schema parser context
5797 * @schema: the schema context
5798 * @ownerDes: the designation of the owner element
5799 * @ownerItem: the owner as a schema object
5800 * @attr: the attribute node
5801 * @local: the resulting local part if found, the attribute value otherwise
5802 * @uri: the resulting namespace URI if found
5803 *
5804 * Extracts and validates the QName of an attribute value.
5805 * This one is intended to be used on attribute values that
5806 * should resolve to schema components.
5807 *
5808 * Returns 0, in case the QName is valid, a positive error code
5809 * if not valid and -1 if an internal error occurs.
5810 */
5811static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005812xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005813 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005814 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005815 xmlAttrPtr attr,
5816 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005817 const xmlChar **local)
5818{
5819 const xmlChar *value;
5820
5821 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005822 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005823 ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005824}
5825
5826/**
5827 * xmlSchemaPValAttrQName:
5828 * @ctxt: a schema parser context
5829 * @schema: the schema context
5830 * @ownerDes: the designation of the parent element
5831 * @ownerItem: the owner as a schema object
5832 * @ownerElem: the parent node of the attribute
5833 * @name: the name of the attribute
5834 * @local: the resulting local part if found, the attribute value otherwise
5835 * @uri: the resulting namespace URI if found
5836 *
5837 * Extracts and validates the QName of an attribute value.
5838 *
5839 * Returns 0, in case the QName is valid, a positive error code
5840 * if not valid and -1 if an internal error occurs.
5841 */
5842static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005843xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5844 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005845 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005846 xmlNodePtr ownerElem,
5847 const char *name,
5848 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005849 const xmlChar **local)
5850{
5851 xmlAttrPtr attr;
5852
5853 attr = xmlSchemaGetPropNode(ownerElem, name);
5854 if (attr == NULL) {
5855 *local = NULL;
5856 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005857 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005858 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005859 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005860 ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005861}
5862
5863/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005864 * xmlSchemaPValAttrID:
5865 * @ctxt: a schema parser context
5866 * @schema: the schema context
5867 * @ownerDes: the designation of the parent element
5868 * @ownerItem: the owner as a schema object
5869 * @ownerElem: the parent node of the attribute
5870 * @name: the name of the attribute
5871 *
5872 * Extracts and validates the ID of an attribute value.
5873 *
5874 * Returns 0, in case the ID is valid, a positive error code
5875 * if not valid and -1 if an internal error occurs.
5876 */
5877static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005878xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005879{
5880 int ret;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005881 const xmlChar *value;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005882
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005883 if (attr == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005884 return(0);
5885 value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5886 ret = xmlValidateNCName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005887 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005888 /*
5889 * NOTE: the IDness might have already be declared in the DTD
5890 */
5891 if (attr->atype != XML_ATTRIBUTE_ID) {
5892 xmlIDPtr res;
5893 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005894
5895 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005896 * TODO: Use xmlSchemaStrip here; it's not exported at this
5897 * moment.
5898 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005899 strip = xmlSchemaCollapseString(value);
5900 if (strip != NULL) {
5901 xmlFree((xmlChar *) value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005902 value = strip;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005903 }
5904 res = xmlAddID(NULL, attr->doc, value, attr);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005905 if (res == NULL) {
5906 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005907 xmlSchemaPSimpleTypeErr(ctxt,
5908 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005909 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005910 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5911 NULL, NULL, "Duplicate value '%s' of simple "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005912 "type 'xs:ID'", value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005913 } else
5914 attr->atype = XML_ATTRIBUTE_ID;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005915 }
5916 } else if (ret > 0) {
5917 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005918 xmlSchemaPSimpleTypeErr(ctxt,
5919 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005920 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005921 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5922 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5923 "not a valid 'xs:NCName'",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005924 value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005925 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005926 if (value != NULL)
5927 xmlFree((xmlChar *)value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005928
5929 return (ret);
5930}
5931
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005932static int
5933xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5934 xmlNodePtr ownerElem,
5935 const xmlChar *name)
5936{
5937 xmlAttrPtr attr;
5938
5939 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5940 if (attr == NULL)
5941 return(0);
5942 return(xmlSchemaPValAttrNodeID(ctxt, attr));
5943
5944}
5945
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005946/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005947 * xmlGetMaxOccurs:
5948 * @ctxt: a schema validation context
5949 * @node: a subtree containing XML Schema informations
5950 *
5951 * Get the maxOccurs property
5952 *
5953 * Returns the default if not found, or the value
5954 */
5955static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005956xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5957 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005958{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005959 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005960 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005961 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005962
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005963 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5964 if (attr == NULL)
5965 return (def);
5966 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005967
5968 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005969 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005970 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005971 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5972 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005973 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005974 val, NULL, NULL, NULL);
5975 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005976 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005977 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005978 }
5979
5980 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005981 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005982 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005983 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005984 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005985 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5986 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005987 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005988 val, NULL, NULL, NULL);
5989 return (def);
5990 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005991 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005992 ret = ret * 10 + (*cur - '0');
5993 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005994 }
William M. Brack76e95df2003-10-18 16:20:14 +00005995 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005996 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005997 /*
5998 * TODO: Restrict the maximal value to Integer.
5999 */
6000 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006001 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006002 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6003 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006004 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006005 val, NULL, NULL, NULL);
6006 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006007 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006008 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006009}
6010
6011/**
6012 * xmlGetMinOccurs:
6013 * @ctxt: a schema validation context
6014 * @node: a subtree containing XML Schema informations
6015 *
6016 * Get the minOccurs property
6017 *
6018 * Returns the default if not found, or the value
6019 */
6020static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006021xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006022 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006023{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006024 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00006025 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006026 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006027
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006028 attr = xmlSchemaGetPropNode(node, "minOccurs");
6029 if (attr == NULL)
6030 return (def);
6031 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00006032 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00006033 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006034 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006035 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006036 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006037 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6038 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006039 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006040 val, NULL, NULL, NULL);
6041 return (def);
6042 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006043 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006044 ret = ret * 10 + (*cur - '0');
6045 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00006046 }
William M. Brack76e95df2003-10-18 16:20:14 +00006047 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006048 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006049 /*
6050 * TODO: Restrict the maximal value to Integer.
6051 */
6052 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006053 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006054 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6055 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006056 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006057 val, NULL, NULL, NULL);
6058 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006059 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006060 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006061}
6062
6063/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006064 * xmlSchemaPGetBoolNodeValue:
6065 * @ctxt: a schema validation context
6066 * @ownerDes: owner designation
6067 * @ownerItem: the owner as a schema item
6068 * @node: the node holding the value
6069 *
6070 * Converts a boolean string value into 1 or 0.
6071 *
6072 * Returns 0 or 1.
6073 */
6074static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006075xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006076 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006077 xmlNodePtr node)
6078{
6079 xmlChar *value = NULL;
6080 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006081
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006082 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006083 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006084 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006085 * An instance of a datatype that is defined as ·boolean·
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006086 * can have the following legal literals {true, false, 1, 0}.
6087 */
6088 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6089 res = 1;
6090 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6091 res = 0;
6092 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6093 res = 1;
6094 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006095 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006096 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006097 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006098 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006099 ownerItem, node,
6100 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6101 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006102 NULL, NULL, NULL);
6103 }
6104 if (value != NULL)
6105 xmlFree(value);
6106 return (res);
6107}
6108
6109/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006110 * xmlGetBooleanProp:
6111 * @ctxt: a schema validation context
6112 * @node: a subtree containing XML Schema informations
6113 * @name: the attribute name
6114 * @def: the default value
6115 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006116 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00006117 *
6118 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006119 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00006120 */
6121static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006122xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006123 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006124 const char *name, int def)
6125{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006126 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00006127
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006128 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006129 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006130 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006131 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006132 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006133 * An instance of a datatype that is defined as ·boolean·
Daniel Veillardc0826a72004-08-10 14:17:33 +00006134 * can have the following legal literals {true, false, 1, 0}.
6135 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006136 if (xmlStrEqual(val, BAD_CAST "true"))
6137 def = 1;
6138 else if (xmlStrEqual(val, BAD_CAST "false"))
6139 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006140 else if (xmlStrEqual(val, BAD_CAST "1"))
6141 def = 1;
6142 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006143 def = 0;
6144 else {
6145 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006146 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006147 NULL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006148 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006149 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6150 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006151 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006152 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006153}
6154
6155/************************************************************************
6156 * *
6157 * Shema extraction from an Infoset *
6158 * *
6159 ************************************************************************/
6160static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6161 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006162 xmlNodePtr node,
6163 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006164static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6165 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00006166 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006167 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00006168 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006169static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6170 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00006171 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006172 xmlNodePtr node,
6173 xmlSchemaTypeType parentType);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006174static xmlSchemaBasicItemPtr
6175xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6176 xmlSchemaPtr schema,
6177 xmlNodePtr node,
6178 xmlSchemaItemListPtr uses,
6179 int parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00006180static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6181 xmlSchemaPtr schema,
6182 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00006183static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006184xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6185 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006186
6187/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006188 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006189 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00006190 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00006191 * @ownerDes: the designation of the parent element
6192 * @ownerItem: the schema object owner if existent
6193 * @attr: the schema attribute node being validated
6194 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006195 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00006196 *
6197 * Validates a value against the given built-in type.
6198 * This one is intended to be used internally for validation
6199 * of schema attribute values during parsing of the schema.
6200 *
6201 * Returns 0 if the value is valid, a positive error code
6202 * number otherwise and -1 in case of an internal or API error.
6203 */
6204static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006205xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006206 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006207 xmlAttrPtr attr,
6208 const xmlChar *value,
6209 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00006210{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006211
6212 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006213
6214 /*
6215 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6216 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006217 */
6218 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00006219 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006220 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6221 PERROR_INT("xmlSchemaPValAttrNodeValue",
6222 "the given type is not a built-in type");
6223 return (-1);
6224 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006225 switch (type->builtInType) {
6226 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006227 case XML_SCHEMAS_QNAME:
6228 case XML_SCHEMAS_ANYURI:
6229 case XML_SCHEMAS_TOKEN:
6230 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006231 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6232 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006233 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006234 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006235 PERROR_INT("xmlSchemaPValAttrNodeValue",
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +00006236 "validation using the given type is not supported while "
6237 "parsing a schema");
Daniel Veillard01fa6152004-06-29 17:04:39 +00006238 return (-1);
6239 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006240 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006241 /*
6242 * TODO: Should we use the S4S error codes instead?
6243 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006244 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006245 PERROR_INT("xmlSchemaPValAttrNodeValue",
6246 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006247 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006248 } else if (ret > 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006249 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006250 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6251 else
6252 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6253 xmlSchemaPSimpleTypeErr(pctxt,
6254 ret, ownerItem, (xmlNodePtr) attr,
6255 type, NULL, value, NULL, NULL, NULL);
6256 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006257 return (ret);
6258}
6259
6260/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006261 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006262 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006263 * @ctxt: a schema parser context
6264 * @ownerDes: the designation of the parent element
6265 * @ownerItem: the schema object owner if existent
6266 * @attr: the schema attribute node being validated
6267 * @type: the built-in type to be validated against
6268 * @value: the resulting value if any
6269 *
6270 * Extracts and validates a value against the given built-in type.
6271 * This one is intended to be used internally for validation
6272 * of schema attribute values during parsing of the schema.
6273 *
6274 * Returns 0 if the value is valid, a positive error code
6275 * number otherwise and -1 in case of an internal or API error.
6276 */
6277static int
6278xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006279 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006280 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006281 xmlSchemaTypePtr type,
6282 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006283{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006284 const xmlChar *val;
6285
6286 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006287 return (-1);
6288
Daniel Veillardc0826a72004-08-10 14:17:33 +00006289 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6290 if (value != NULL)
6291 *value = val;
6292
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006293 return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006294 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00006295}
6296
6297/**
6298 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006299 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006300 * @ctxt: a schema parser context
6301 * @node: the element node of the attribute
6302 * @ownerDes: the designation of the parent element
6303 * @ownerItem: the schema object owner if existent
6304 * @ownerElem: the owner element node
6305 * @name: the name of the schema attribute node
6306 * @type: the built-in type to be validated against
6307 * @value: the resulting value if any
6308 *
6309 * Extracts and validates a value against the given built-in type.
6310 * This one is intended to be used internally for validation
6311 * of schema attribute values during parsing of the schema.
6312 *
6313 * Returns 0 if the value is valid, a positive error code
6314 * number otherwise and -1 in case of an internal or API error.
6315 */
6316static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006317xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6318 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006319 xmlNodePtr ownerElem,
6320 const char *name,
6321 xmlSchemaTypePtr type,
6322 const xmlChar **value)
6323{
6324 xmlAttrPtr attr;
6325
6326 if ((ctxt == NULL) || (type == NULL)) {
6327 if (value != NULL)
6328 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006329 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006330 }
6331 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6332 if (value != NULL)
6333 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006334 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006335 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006336 "Internal error: xmlSchemaPValAttr, the given "
6337 "type '%s' is not a built-in type.\n",
6338 type->name, NULL);
6339 return (-1);
6340 }
6341 attr = xmlSchemaGetPropNode(ownerElem, name);
6342 if (attr == NULL) {
6343 if (value != NULL)
6344 *value = NULL;
6345 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006346 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006347 return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006348 type, value));
6349}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006350
6351static int
6352xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006353 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006354 xmlNodePtr node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006355 xmlAttrPtr attr,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006356 const xmlChar *namespaceName)
6357{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006358 /* TODO: Pointer comparison instead? */
6359 if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006360 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006361 if (xmlStrEqual(xmlSchemaNs, namespaceName))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006362 return (0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006363 /*
6364 * Check if the referenced namespace was <import>ed.
6365 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006366 if (WXS_BUCKET(pctxt)->relations != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006367 xmlSchemaSchemaRelationPtr rel;
6368
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006369 rel = WXS_BUCKET(pctxt)->relations;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006370 do {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006371 if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006372 xmlStrEqual(namespaceName, rel->importNamespace))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006373 return (0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006374 rel = rel->next;
6375 } while (rel != NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006376 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006377 /*
6378 * No matching <import>ed namespace found.
6379 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006380 {
6381 xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6382
6383 if (namespaceName == NULL)
6384 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6385 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6386 "References from this schema to components in no "
6387 "namespace are not allowed, since not indicated by an "
6388 "import statement", NULL, NULL);
6389 else
6390 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6391 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6392 "References from this schema to components in the "
6393 "namespace '%s' are not allowed, since not indicated by an "
6394 "import statement", namespaceName, NULL);
6395 }
6396 return (XML_SCHEMAP_SRC_RESOLVE);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006397}
6398
Daniel Veillardc0826a72004-08-10 14:17:33 +00006399/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006400 * xmlSchemaParseLocalAttributes:
Daniel Veillard4255d502002-04-16 15:50:10 +00006401 * @ctxt: a schema validation context
6402 * @schema: the schema being built
6403 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006404 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00006405 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006406 * Parses attribute uses and attribute declarations and
6407 * attribute group references.
Daniel Veillard4255d502002-04-16 15:50:10 +00006408 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006409static int
6410xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6411 xmlNodePtr *child, xmlSchemaItemListPtr *list,
6412 int parentType, int *hasRefs)
Daniel Veillard4255d502002-04-16 15:50:10 +00006413{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006414 void *item;
Daniel Veillard4255d502002-04-16 15:50:10 +00006415
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006416 while ((IS_SCHEMA((*child), "attribute")) ||
6417 (IS_SCHEMA((*child), "attributeGroup"))) {
6418 if (IS_SCHEMA((*child), "attribute")) {
6419 item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6420 *list, parentType);
6421 } else {
6422 item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6423 if ((item != NULL) && (hasRefs != NULL))
6424 *hasRefs = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006425 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006426 if (item != NULL) {
6427 if (*list == NULL) {
6428 /* TODO: Customize grow factor. */
6429 *list = xmlSchemaItemListCreate();
6430 if (*list == NULL)
6431 return(-1);
6432 }
6433 if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6434 return(-1);
6435 }
6436 *child = (*child)->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006437 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006438 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006439}
6440
6441/**
6442 * xmlSchemaParseAnnotation:
6443 * @ctxt: a schema validation context
6444 * @schema: the schema being built
6445 * @node: a subtree containing XML Schema informations
6446 *
6447 * parse a XML schema Attrribute declaration
6448 * *WARNING* this interface is highly subject to change
6449 *
William M. Bracke7091952004-05-11 15:09:58 +00006450 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006451 * 1 in case of success.
6452 */
6453static xmlSchemaAnnotPtr
6454xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006455 xmlNodePtr node, int needed)
Daniel Veillard4255d502002-04-16 15:50:10 +00006456{
6457 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006458 xmlNodePtr child = NULL;
6459 xmlAttrPtr attr;
6460 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00006461
Daniel Veillardc0826a72004-08-10 14:17:33 +00006462 /*
6463 * INFO: S4S completed.
6464 */
6465 /*
6466 * id = ID
6467 * {any attributes with non-schema namespace . . .}>
6468 * Content: (appinfo | documentation)*
6469 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006470 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6471 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006472 if (needed)
6473 ret = xmlSchemaNewAnnot(ctxt, node);
6474 else
6475 ret = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006476 attr = node->properties;
6477 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006478 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006479 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006480 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006481 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006482
6483 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006484 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006485 }
6486 attr = attr->next;
6487 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006488 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006489 /*
6490 * And now for the children...
6491 */
6492 child = node->children;
6493 while (child != NULL) {
6494 if (IS_SCHEMA(child, "appinfo")) {
6495 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006496 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006497 * source = anyURI
6498 * {any attributes with non-schema namespace . . .}>
6499 * Content: ({any})*
6500 */
6501 attr = child->properties;
6502 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006503 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006504 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006505 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006506 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006507
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006508 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006509 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006510 }
6511 attr = attr->next;
6512 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006513 xmlSchemaPValAttr(ctxt, NULL, child, "source",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006514 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006515 child = child->next;
6516 } else if (IS_SCHEMA(child, "documentation")) {
6517 /* TODO: make available the content of "documentation". */
6518 /*
6519 * source = anyURI
6520 * {any attributes with non-schema namespace . . .}>
6521 * Content: ({any})*
6522 */
6523 attr = child->properties;
6524 while (attr != NULL) {
6525 if (attr->ns == NULL) {
6526 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006527 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006528 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006529 }
6530 } else {
6531 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6532 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
6533 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006534
6535 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006536 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006537 }
6538 }
6539 attr = attr->next;
6540 }
6541 /*
6542 * Attribute "xml:lang".
6543 */
6544 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6545 if (attr != NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006546 xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006547 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006548 child = child->next;
6549 } else {
6550 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006551 xmlSchemaPContentErr(ctxt,
6552 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006553 NULL, node, child, NULL, "(appinfo | documentation)*");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006554 barked = 1;
6555 child = child->next;
6556 }
6557 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006558
Daniel Veillard4255d502002-04-16 15:50:10 +00006559 return (ret);
6560}
6561
6562/**
6563 * xmlSchemaParseFacet:
6564 * @ctxt: a schema validation context
6565 * @schema: the schema being built
6566 * @node: a subtree containing XML Schema informations
6567 *
6568 * parse a XML schema Facet declaration
6569 * *WARNING* this interface is highly subject to change
6570 *
6571 * Returns the new type structure or NULL in case of error
6572 */
6573static xmlSchemaFacetPtr
6574xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006575 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006576{
6577 xmlSchemaFacetPtr facet;
6578 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006579 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00006580
6581 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6582 return (NULL);
6583
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006584 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006585 if (facet == NULL) {
6586 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6587 return (NULL);
6588 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006589 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006590 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00006591 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006592 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6593 "Facet %s has no value\n", node->name, NULL);
6594 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00006595 return (NULL);
6596 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006597 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006598 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006599 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006600 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006601 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006602 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006603 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006604 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006605 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006606 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006607 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006608 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006609 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006610 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006611 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006612 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006613 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006614 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006615 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006616 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006617 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006618 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6619 } else if (IS_SCHEMA(node, "minLength")) {
6620 facet->type = XML_SCHEMA_FACET_MINLENGTH;
6621 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006622 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6623 "Unknown facet type %s\n", node->name, NULL);
6624 xmlSchemaFreeFacet(facet);
6625 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006626 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006627 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006628 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006629 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6630 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6631 const xmlChar *fixed;
6632
6633 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6634 if (fixed != NULL) {
6635 if (xmlStrEqual(fixed, BAD_CAST "true"))
6636 facet->fixed = 1;
6637 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006638 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006639 child = node->children;
6640
6641 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006642 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006643 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006644 }
6645 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006646 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6647 "Facet %s has unexpected child content\n",
6648 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006649 }
6650 return (facet);
6651}
6652
6653/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006654 * xmlSchemaParseWildcardNs:
6655 * @ctxt: a schema parser context
6656 * @wildc: the wildcard, already created
6657 * @node: a subtree containing XML Schema informations
6658 *
6659 * Parses the attribute "processContents" and "namespace"
6660 * of a xsd:anyAttribute and xsd:any.
6661 * *WARNING* this interface is highly subject to change
6662 *
6663 * Returns 0 if everything goes fine, a positive error code
6664 * if something is not valid and -1 if an internal error occurs.
6665 */
6666static int
6667xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006668 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006669 xmlSchemaWildcardPtr wildc,
6670 xmlNodePtr node)
6671{
6672 const xmlChar *pc, *ns, *dictnsItem;
6673 int ret = 0;
6674 xmlChar *nsItem;
6675 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6676 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006677
Daniel Veillardc0826a72004-08-10 14:17:33 +00006678 pc = xmlSchemaGetProp(ctxt, node, "processContents");
6679 if ((pc == NULL)
6680 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6681 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6682 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6683 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6684 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6685 wildc->processContents = XML_SCHEMAS_ANY_LAX;
6686 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006687 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006688 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006689 NULL, node,
6690 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006691 NULL, NULL, NULL);
6692 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006693 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006694 }
6695 /*
6696 * Build the namespace constraints.
6697 */
6698 attr = xmlSchemaGetPropNode(node, "namespace");
6699 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006700 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00006701 wildc->any = 1;
6702 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6703 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006704 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006705 return (-1);
6706 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006707 wildc->negNsSet->value = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006708 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006709 const xmlChar *end, *cur;
6710
6711 cur = ns;
6712 do {
6713 while (IS_BLANK_CH(*cur))
6714 cur++;
6715 end = cur;
6716 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6717 end++;
6718 if (end == cur)
6719 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006720 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006721 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6722 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006723 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006724 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006725 NULL, (xmlNodePtr) attr,
6726 NULL,
6727 "((##any | ##other) | List of (xs:anyURI | "
6728 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006729 nsItem, NULL, NULL, NULL);
6730 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6731 } else {
6732 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006733 dictnsItem = ctxt->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006734 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6735 dictnsItem = NULL;
6736 } else {
6737 /*
6738 * Validate the item (anyURI).
6739 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006740 xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006741 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6742 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6743 }
6744 /*
6745 * Avoid dublicate namespaces.
6746 */
6747 tmp = wildc->nsSet;
6748 while (tmp != NULL) {
6749 if (dictnsItem == tmp->value)
6750 break;
6751 tmp = tmp->next;
6752 }
6753 if (tmp == NULL) {
6754 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6755 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006756 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006757 return (-1);
6758 }
6759 tmp->value = dictnsItem;
6760 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006761 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006762 wildc->nsSet = tmp;
6763 else
6764 lastNs->next = tmp;
6765 lastNs = tmp;
6766 }
6767
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006768 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006769 xmlFree(nsItem);
6770 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006771 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006772 }
6773 return (ret);
6774}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006775
6776static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006777xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6778 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006779 xmlNodePtr node,
6780 int minOccurs,
6781 int maxOccurs) {
6782
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006783 if ((maxOccurs == 0) && ( minOccurs == 0))
6784 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006785 if (maxOccurs != UNBOUNDED) {
6786 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006787 * TODO: Maybe we should better not create the particle,
6788 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006789 * content model.
6790 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006791 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006792 * 3.9.6 Schema Component Constraint: Particle Correct
6793 *
6794 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006795 if (maxOccurs < 1) {
6796 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006797 * 2.2 {max occurs} must be greater than or equal to 1.
6798 */
6799 xmlSchemaPCustomAttrErr(ctxt,
6800 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006801 NULL, NULL,
6802 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006803 "The value must be greater than or equal to 1");
6804 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6805 } else if (minOccurs > maxOccurs) {
6806 /*
6807 * 2.1 {min occurs} must not be greater than {max occurs}.
6808 */
6809 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006810 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006811 NULL, NULL,
6812 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006813 "The value must not be greater than the value of 'maxOccurs'");
6814 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6815 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006816 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006817 return (0);
6818}
6819
Daniel Veillardc0826a72004-08-10 14:17:33 +00006820/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006821 * xmlSchemaParseAny:
6822 * @ctxt: a schema validation context
6823 * @schema: the schema being built
6824 * @node: a subtree containing XML Schema informations
6825 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006826 * Parsea a XML schema <any> element. A particle and wildcard
6827 * will be created (except if minOccurs==maxOccurs==0, in this case
6828 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006829 * *WARNING* this interface is highly subject to change
6830 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006831 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006832 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006833static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006834xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6835 xmlNodePtr node)
6836{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006837 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006838 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006839 xmlSchemaWildcardPtr wild;
6840 int min, max;
6841 xmlAttrPtr attr;
6842 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006843
6844 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6845 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006846 /*
6847 * Check for illegal attributes.
6848 */
6849 attr = node->properties;
6850 while (attr != NULL) {
6851 if (attr->ns == NULL) {
6852 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6853 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6854 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6855 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6856 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006857 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006858 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006859 }
6860 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006861 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006862 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006863 }
6864 attr = attr->next;
6865 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006866 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006867 /*
6868 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006869 */
6870 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6871 "(xs:nonNegativeInteger | unbounded)");
6872 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6873 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006874 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6875 /*
6876 * Create & parse the wildcard.
6877 */
6878 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6879 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006880 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006881 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006882 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006883 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006884 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006885 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006886 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006887 annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006888 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006889 }
6890 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006891 xmlSchemaPContentErr(ctxt,
6892 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006893 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006894 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006895 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006896 /*
6897 * No component if minOccurs==maxOccurs==0.
6898 */
6899 if ((min == 0) && (max == 0)) {
6900 /* Don't free the wildcard, since it's already on the list. */
6901 return (NULL);
6902 }
6903 /*
6904 * Create the particle.
6905 */
6906 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6907 if (particle == NULL)
6908 return (NULL);
6909 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006910 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006911
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006912 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006913}
6914
6915/**
6916 * xmlSchemaParseNotation:
6917 * @ctxt: a schema validation context
6918 * @schema: the schema being built
6919 * @node: a subtree containing XML Schema informations
6920 *
6921 * parse a XML schema Notation declaration
6922 *
6923 * Returns the new structure or NULL in case of error
6924 */
6925static xmlSchemaNotationPtr
6926xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006927 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006928{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006929 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006930 xmlSchemaNotationPtr ret;
6931 xmlNodePtr child = NULL;
6932
6933 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6934 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006935 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006936 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006937 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6938 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006939 return (NULL);
6940 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006941 ret = xmlSchemaAddNotation(ctxt, schema, name,
6942 ctxt->targetNamespace, node);
6943 if (ret == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00006944 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006945 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006946
6947 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006948 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006949 child = child->next;
6950 }
6951
Daniel Veillard4255d502002-04-16 15:50:10 +00006952 child = node->children;
6953 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006954 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006955 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006956 }
6957 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006958 xmlSchemaPContentErr(ctxt,
6959 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006960 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006961 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006962 }
6963
6964 return (ret);
6965}
6966
6967/**
6968 * xmlSchemaParseAnyAttribute:
6969 * @ctxt: a schema validation context
6970 * @schema: the schema being built
6971 * @node: a subtree containing XML Schema informations
6972 *
6973 * parse a XML schema AnyAttrribute declaration
6974 * *WARNING* this interface is highly subject to change
6975 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006976 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006977 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006978static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006979xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6980 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006981{
Daniel Veillard3646d642004-06-02 19:19:14 +00006982 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006983 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006984 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006985
6986 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6987 return (NULL);
6988
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006989 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6990 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006991 if (ret == NULL) {
6992 return (NULL);
6993 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006994 /*
6995 * Check for illegal attributes.
6996 */
6997 attr = node->properties;
6998 while (attr != NULL) {
6999 if (attr->ns == NULL) {
7000 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7001 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7002 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007003 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007004 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007005 }
7006 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007007 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007008 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007009 }
7010 attr = attr->next;
7011 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007012 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007013 /*
7014 * Parse the namespace list.
7015 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007016 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007017 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007018 /*
7019 * And now for the children...
7020 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007021 child = node->children;
7022 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007023 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007024 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007025 }
7026 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007027 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007028 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007029 NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007030 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007031 }
7032
7033 return (ret);
7034}
7035
7036
7037/**
7038 * xmlSchemaParseAttribute:
7039 * @ctxt: a schema validation context
7040 * @schema: the schema being built
7041 * @node: a subtree containing XML Schema informations
7042 *
7043 * parse a XML schema Attrribute declaration
7044 * *WARNING* this interface is highly subject to change
7045 *
William M. Bracke7091952004-05-11 15:09:58 +00007046 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007047 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007048static xmlSchemaBasicItemPtr
7049xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7050 xmlSchemaPtr schema,
7051 xmlNodePtr node,
7052 xmlSchemaItemListPtr uses,
7053 int parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00007054{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007055 const xmlChar *attrValue, *name = NULL, *ns = NULL;
7056 xmlSchemaAttributeUsePtr use = NULL;
7057 xmlNodePtr child = NULL;
7058 xmlAttrPtr attr;
7059 const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7060 int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7061 int nberrors, hasForm = 0, defValueType = 0;
7062
7063#define WXS_ATTR_DEF_VAL_DEFAULT 1
7064#define WXS_ATTR_DEF_VAL_FIXED 2
7065
7066 /*
7067 * 3.2.3 Constraints on XML Representations of Attribute Declarations
7068 */
7069
7070 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7071 return (NULL);
7072 attr = xmlSchemaGetPropNode(node, "ref");
7073 if (attr != NULL) {
7074 if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7075 NULL, attr, &tmpNs, &tmpName) != 0) {
7076 return (NULL);
7077 }
7078 if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7079 return(NULL);
7080 isRef = 1;
7081 }
7082 nberrors = pctxt->nberrors;
7083 /*
7084 * Check for illegal attributes.
7085 */
7086 attr = node->properties;
7087 while (attr != NULL) {
7088 if (attr->ns == NULL) {
7089 if (isRef) {
7090 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7091 xmlSchemaPValAttrNodeID(pctxt, attr);
7092 goto attr_next;
7093 } else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7094 goto attr_next;
7095 }
7096 } else {
7097 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7098 goto attr_next;
7099 } else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7100 xmlSchemaPValAttrNodeID(pctxt, attr);
7101 goto attr_next;
7102 } else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7103 xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7104 attr, &tmpNs, &tmpName);
7105 goto attr_next;
7106 } else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7107 /*
7108 * Evaluate the target namespace
7109 */
7110 hasForm = 1;
7111 attrValue = xmlSchemaGetNodeContent(pctxt,
7112 (xmlNodePtr) attr);
7113 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7114 ns = pctxt->targetNamespace;
7115 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7116 {
7117 xmlSchemaPSimpleTypeErr(pctxt,
7118 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7119 NULL, (xmlNodePtr) attr,
7120 NULL, "(qualified | unqualified)",
7121 attrValue, NULL, NULL, NULL);
7122 }
7123 goto attr_next;
7124 }
7125 }
7126 if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7127
7128 attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7129 /* TODO: Maybe we need to normalize the value beforehand. */
7130 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7131 occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7132 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7133 occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7134 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7135 occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7136 else {
7137 xmlSchemaPSimpleTypeErr(pctxt,
7138 XML_SCHEMAP_INVALID_ATTR_USE,
7139 NULL, (xmlNodePtr) attr,
7140 NULL, "(optional | prohibited | required)",
7141 attrValue, NULL, NULL, NULL);
7142 }
7143 goto attr_next;
7144 } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7145 /*
7146 * 3.2.3 : 1
7147 * default and fixed must not both be present.
7148 */
7149 if (defValue) {
7150 xmlSchemaPMutualExclAttrErr(pctxt,
7151 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7152 NULL, attr, "default", "fixed");
7153 } else {
7154 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7155 defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7156 }
7157 goto attr_next;
7158 } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7159 /*
7160 * 3.2.3 : 1
7161 * default and fixed must not both be present.
7162 */
7163 if (defValue) {
7164 xmlSchemaPMutualExclAttrErr(pctxt,
7165 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7166 NULL, attr, "default", "fixed");
7167 } else {
7168 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7169 defValueType = WXS_ATTR_DEF_VAL_FIXED;
7170 }
7171 goto attr_next;
7172 }
7173 } else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7174 goto attr_next;
7175
7176 xmlSchemaPIllegalAttrErr(pctxt,
7177 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7178
7179attr_next:
7180 attr = attr->next;
7181 }
7182 /*
7183 * 3.2.3 : 2
7184 * If default and use are both present, use must have
7185 * the actual value optional.
7186 */
7187 if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7188 (occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7189 xmlSchemaPSimpleTypeErr(pctxt,
7190 XML_SCHEMAP_SRC_ATTRIBUTE_2,
7191 NULL, node, NULL,
7192 "(optional | prohibited | required)", NULL,
7193 "The value of the attribute 'use' must be 'optional' "
7194 "if the attribute 'default' is present",
7195 NULL, NULL);
7196 }
7197 /*
7198 * We want correct attributes.
7199 */
7200 if (nberrors != pctxt->nberrors)
7201 return(NULL);
7202 if (! isRef) {
7203 xmlSchemaAttributePtr attrDecl;
7204
7205 /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7206 if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7207 ns = pctxt->targetNamespace;
7208 /*
7209 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7210 * TODO: Move this to the component layer.
7211 */
7212 if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7213 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7214 XML_SCHEMAP_NO_XSI,
7215 node, NULL,
7216 "The target namespace must not match '%s'",
7217 xmlSchemaInstanceNs, NULL);
7218 }
7219 attr = xmlSchemaGetPropNode(node, "name");
7220 if (attr == NULL) {
7221 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7222 NULL, node, "name", NULL);
7223 return (NULL);
7224 }
7225 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7226 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7227 return (NULL);
7228 }
7229 /*
7230 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7231 * TODO: Move this to the component layer.
7232 */
7233 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7234 xmlSchemaPSimpleTypeErr(pctxt,
7235 XML_SCHEMAP_NO_XMLNS,
7236 NULL, (xmlNodePtr) attr,
7237 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7238 "The value of the attribute must not match 'xmlns'",
7239 NULL, NULL);
7240 return (NULL);
7241 }
7242 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7243 goto check_children;
7244 /*
7245 * Create the attribute use component.
7246 */
7247 use = xmlSchemaAddAttributeUse(pctxt, node);
7248 if (use == NULL)
7249 return(NULL);
7250 use->occurs = occurs;
7251 /*
7252 * Create the attribute declaration.
7253 */
7254 attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7255 if (attrDecl == NULL)
7256 return (NULL);
7257 if (tmpName != NULL) {
7258 attrDecl->typeName = tmpName;
7259 attrDecl->typeNs = tmpNs;
7260 }
7261 use->attrDecl = attrDecl;
7262 /*
7263 * Value constraint.
7264 */
7265 if (defValue != NULL) {
7266 attrDecl->defValue = defValue;
7267 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7268 attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7269 }
7270 } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7271 xmlSchemaQNameRefPtr ref;
7272
7273 /*
7274 * Create the attribute use component.
7275 */
7276 use = xmlSchemaAddAttributeUse(pctxt, node);
7277 if (use == NULL)
7278 return(NULL);
7279 /*
7280 * We need to resolve the reference at later stage.
7281 */
7282 WXS_ADD_PENDING(pctxt, use);
7283 use->occurs = occurs;
7284 /*
7285 * Create a QName reference to the attribute declaration.
7286 */
7287 ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7288 tmpName, tmpNs);
7289 if (ref == NULL)
7290 return(NULL);
7291 /*
7292 * Assign the reference. This will be substituted for the
7293 * referenced attribute declaration when the QName is resolved.
7294 */
7295 use->attrDecl = WXS_ATTR_CAST ref;
7296 /*
7297 * Value constraint.
7298 */
7299 if (defValue != NULL)
7300 use->defValue = defValue;
7301 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7302 use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7303 }
7304
7305check_children:
7306 /*
7307 * And now for the children...
7308 */
7309 child = node->children;
7310 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7311 xmlSchemaAttributeUseProhibPtr prohib;
7312
7313 if (IS_SCHEMA(child, "annotation")) {
7314 xmlSchemaParseAnnotation(pctxt, schema, child, 0);
7315 child = child->next;
7316 }
7317 if (child != NULL) {
7318 xmlSchemaPContentErr(pctxt,
7319 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7320 NULL, node, child, NULL,
7321 "(annotation?)");
7322 }
7323 /*
7324 * Check for pointlessness of attribute prohibitions.
7325 */
7326 if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7327 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7328 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7329 node, NULL,
7330 "Skipping attribute use prohibition, since it is "
7331 "pointless inside an <attributeGroup>",
7332 NULL, NULL, NULL);
7333 return(NULL);
7334 } else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7335 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7336 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7337 node, NULL,
7338 "Skipping attribute use prohibition, since it is "
7339 "pointless when extending a type",
7340 NULL, NULL, NULL);
7341 return(NULL);
7342 }
7343 if (! isRef) {
7344 tmpName = name;
7345 tmpNs = ns;
7346 }
7347 /*
7348 * Check for duplicate attribute prohibitions.
7349 */
7350 if (uses) {
7351 int i;
7352
7353 for (i = 0; i < uses->nbItems; i++) {
7354 use = uses->items[i];
7355 if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7356 (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7357 (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7358 {
7359 xmlChar *str = NULL;
7360
7361 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7362 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7363 node, NULL,
7364 "Skipping duplicate attribute use prohibition '%s'",
7365 xmlSchemaFormatQName(&str, tmpNs, tmpName),
7366 NULL, NULL);
7367 FREE_AND_NULL(str)
7368 return(NULL);
7369 }
7370 }
7371 }
7372 /*
7373 * Create the attribute prohibition helper component.
7374 */
7375 prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7376 if (prohib == NULL)
7377 return(NULL);
7378 prohib->node = node;
7379 prohib->name = tmpName;
7380 prohib->targetNamespace = tmpNs;
7381 if (isRef) {
7382 /*
7383 * We need at least to resolve to the attribute declaration.
7384 */
7385 WXS_ADD_PENDING(pctxt, prohib);
7386 }
7387 return(WXS_BASIC_CAST prohib);
7388 } else {
7389 if (IS_SCHEMA(child, "annotation")) {
7390 /*
7391 * TODO: Should this go into the attr decl?
7392 */
7393 use->annot = xmlSchemaParseAnnotation(pctxt, schema, child, 1);
7394 child = child->next;
7395 }
7396 if (isRef) {
7397 if (child != NULL) {
7398 if (IS_SCHEMA(child, "simpleType"))
7399 /*
7400 * 3.2.3 : 3.2
7401 * If ref is present, then all of <simpleType>,
7402 * form and type must be absent.
7403 */
7404 xmlSchemaPContentErr(pctxt,
7405 XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7406 NULL, node, child, NULL,
7407 "(annotation?)");
7408 else
7409 xmlSchemaPContentErr(pctxt,
7410 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7411 NULL, node, child, NULL,
7412 "(annotation?)");
7413 }
7414 } else {
7415 if (IS_SCHEMA(child, "simpleType")) {
7416 if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7417 /*
7418 * 3.2.3 : 4
7419 * type and <simpleType> must not both be present.
7420 */
7421 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7422 NULL, node, child,
7423 "The attribute 'type' and the <simpleType> child "
7424 "are mutually exclusive", NULL);
7425 } else
7426 WXS_ATTRUSE_TYPEDEF(use) =
7427 xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7428 child = child->next;
7429 }
7430 if (child != NULL)
7431 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7432 NULL, node, child, NULL,
7433 "(annotation?, simpleType?)");
7434 }
7435 }
7436 return (WXS_BASIC_CAST use);
7437}
7438
7439
7440static xmlSchemaAttributePtr
7441xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7442 xmlSchemaPtr schema,
7443 xmlNodePtr node)
7444{
7445 const xmlChar *attrValue;
Daniel Veillard4255d502002-04-16 15:50:10 +00007446 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007447 xmlNodePtr child = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007448 xmlAttrPtr attr;
William M. Bracke7091952004-05-11 15:09:58 +00007449
7450 /*
7451 * Note that the w3c spec assumes the schema to be validated with schema
7452 * for schemas beforehand.
7453 *
7454 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00007455 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007456 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7457 return (NULL);
7458 /*
7459 * 3.2.3 : 3.1
7460 * One of ref or name must be present, but not both
7461 */
7462 attr = xmlSchemaGetPropNode(node, "name");
7463 if (attr == NULL) {
7464 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7465 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007466 return (NULL);
7467 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007468 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7469 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7470 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007471 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007472 /*
7473 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7474 * TODO: Move this to the component layer.
7475 */
7476 if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7477 xmlSchemaPSimpleTypeErr(pctxt,
7478 XML_SCHEMAP_NO_XMLNS,
7479 NULL, (xmlNodePtr) attr,
7480 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7481 "The value of the attribute must not match 'xmlns'",
7482 NULL, NULL);
7483 return (NULL);
7484 }
7485 /*
7486 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7487 * TODO: Move this to the component layer.
7488 * Or better leave it here and add it to the component layer
7489 * if we have a schema construction API.
7490 */
7491 if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7492 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7493 XML_SCHEMAP_NO_XSI, node, NULL,
7494 "The target namespace must not match '%s'",
7495 xmlSchemaInstanceNs, NULL);
7496 }
7497
7498 ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7499 pctxt->targetNamespace, node, 1);
7500 if (ret == NULL)
7501 return (NULL);
7502 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7503
7504 /*
7505 * Check for illegal attributes.
7506 */
7507 attr = node->properties;
7508 while (attr != NULL) {
7509 if (attr->ns == NULL) {
7510 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7511 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7512 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7513 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7514 (!xmlStrEqual(attr->name, BAD_CAST "type")))
7515 {
7516 xmlSchemaPIllegalAttrErr(pctxt,
7517 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7518 }
7519 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7520 xmlSchemaPIllegalAttrErr(pctxt,
7521 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7522 }
7523 attr = attr->next;
7524 }
7525 xmlSchemaPValAttrQName(pctxt, schema, NULL,
7526 node, "type", &ret->typeNs, &ret->typeName);
7527
7528 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00007529 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007530 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00007531 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007532 ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007533 if (ret->defValue != NULL)
7534 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007535 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007536 * Attribute "default".
7537 */
7538 attr = xmlSchemaGetPropNode(node, "default");
7539 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007540 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007541 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007542 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007543 */
7544 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007545 xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7546 WXS_BASIC_CAST ret, attr, "default", "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007547 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007548 ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007549 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007550 /*
7551 * And now for the children...
7552 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007553 child = node->children;
7554 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007555 ret->annot = xmlSchemaParseAnnotation(pctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007556 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007557 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007558 if (IS_SCHEMA(child, "simpleType")) {
7559 if (ret->typeName != NULL) {
7560 /*
7561 * 3.2.3 : 4
7562 * type and <simpleType> must not both be present.
7563 */
7564 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7565 NULL, node, child,
7566 "The attribute 'type' and the <simpleType> child "
7567 "are mutually exclusive", NULL);
7568 } else
7569 ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7570 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007571 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007572 if (child != NULL)
7573 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7574 NULL, node, child, NULL,
7575 "(annotation?, simpleType?)");
7576
Daniel Veillard4255d502002-04-16 15:50:10 +00007577 return (ret);
7578}
7579
7580/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007581 * xmlSchemaParseAttributeGroupRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00007582 * @ctxt: a schema validation context
7583 * @schema: the schema being built
7584 * @node: a subtree containing XML Schema informations
7585 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007586 * Parse an attribute group definition reference.
7587 * Note that a reference to an attribute group does not
7588 * correspond to any component at all.
Daniel Veillard4255d502002-04-16 15:50:10 +00007589 * *WARNING* this interface is highly subject to change
7590 *
7591 * Returns the attribute group or NULL in case of error.
7592 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007593static xmlSchemaQNameRefPtr
7594xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7595 xmlSchemaPtr schema,
7596 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007597{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007598 xmlSchemaQNameRefPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00007599 xmlNodePtr child = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007600 xmlAttrPtr attr;
7601 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007602
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007603 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00007604 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007605
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007606 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007607 if (attr == NULL) {
7608 xmlSchemaPMissingAttrErr(pctxt,
7609 XML_SCHEMAP_S4S_ATTR_MISSING,
7610 NULL, node, "ref", NULL);
7611 return (NULL);
7612 }
7613 xmlSchemaPValAttrNodeQName(pctxt, schema,
7614 NULL, attr, &refNs, &ref);
7615 if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7616 return(NULL);
7617
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007618 /*
7619 * Check for illegal attributes.
7620 */
7621 attr = node->properties;
7622 while (attr != NULL) {
7623 if (attr->ns == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007624 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007625 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007626 {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007627 xmlSchemaPIllegalAttrErr(pctxt,
7628 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007629 }
7630 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007631 xmlSchemaPIllegalAttrErr(pctxt,
7632 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007633 }
7634 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007635 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00007636 /* Attribute ID */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007637 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7638
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007639 /*
7640 * And now for the children...
7641 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007642 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00007643 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007644 /*
7645 * TODO: We do not have a place to store the annotation, do we?
7646 */
7647 xmlSchemaParseAnnotation(pctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007648 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007649 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007650 if (child != NULL) {
7651 xmlSchemaPContentErr(pctxt,
7652 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7653 NULL, node, child, NULL,
7654 "(annotation?)");
7655 }
7656
7657 /*
7658 * Handle attribute group redefinitions.
7659 */
7660 if (pctxt->isRedefine && pctxt->redef &&
7661 (pctxt->redef->item->type ==
7662 XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7663 (ref == pctxt->redef->refName) &&
7664 (refNs == pctxt->redef->refTargetNs))
7665 {
7666 /*
7667 * SPEC src-redefine:
7668 * (7.1) "If it has an <attributeGroup> among its contents
7669 * the ·actual value· of whose ref [attribute] is the same
7670 * as the ·actual value· of its own name attribute plus
7671 * target namespace, then it must have exactly one such group."
7672 */
7673 if (pctxt->redefCounter != 0) {
7674 xmlChar *str = NULL;
7675
7676 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7677 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7678 "The redefining attribute group definition "
7679 "'%s' must not contain more than one "
7680 "reference to the redefined definition",
7681 xmlSchemaFormatQName(&str, refNs, ref), NULL);
7682 FREE_AND_NULL(str);
7683 return(NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007684 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007685 pctxt->redefCounter++;
7686 /*
7687 * URGENT TODO: How to ensure that the reference will not be
7688 * handled by the normal component resolution mechanism?
7689 */
7690 ret = xmlSchemaNewQNameRef(pctxt,
7691 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7692 if (ret == NULL)
7693 return(NULL);
7694 ret->node = node;
7695 pctxt->redef->reference = WXS_BASIC_CAST ret;
7696 } else {
7697 /*
7698 * Create a QName-reference helper component. We will substitute this
7699 * component for the attribute uses of the referenced attribute group
7700 * definition.
7701 */
7702 ret = xmlSchemaNewQNameRef(pctxt,
7703 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7704 if (ret == NULL)
7705 return(NULL);
7706 ret->node = node;
7707 /* Add to pending items, to be able to resolve the reference. */
7708 WXS_ADD_PENDING(pctxt, ret);
7709 }
7710 return (ret);
7711}
7712
7713/**
7714 * xmlSchemaParseAttributeGroupDefinition:
7715 * @pctxt: a schema validation context
7716 * @schema: the schema being built
7717 * @node: a subtree containing XML Schema informations
7718 *
7719 * parse a XML schema Attribute Group declaration
7720 * *WARNING* this interface is highly subject to change
7721 *
7722 * Returns the attribute group definition or NULL in case of error.
7723 */
7724static xmlSchemaAttributeGroupPtr
7725xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7726 xmlSchemaPtr schema,
7727 xmlNodePtr node)
7728{
7729 const xmlChar *name;
7730 xmlSchemaAttributeGroupPtr ret;
7731 xmlNodePtr child = NULL;
7732 xmlAttrPtr attr;
7733 int hasRefs = 0;
7734
7735 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7736 return (NULL);
7737
7738 attr = xmlSchemaGetPropNode(node, "name");
7739 if (attr == NULL) {
7740 xmlSchemaPMissingAttrErr(pctxt,
7741 XML_SCHEMAP_S4S_ATTR_MISSING,
7742 NULL, node, "name", NULL);
7743 return (NULL);
7744 }
7745 /*
7746 * The name is crucial, exit if invalid.
7747 */
7748 if (xmlSchemaPValAttrNode(pctxt,
7749 NULL, attr,
7750 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7751 return (NULL);
7752 }
7753 ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7754 name, pctxt->targetNamespace, node);
7755 if (ret == NULL)
7756 return (NULL);
7757 /*
7758 * Check for illegal attributes.
7759 */
7760 attr = node->properties;
7761 while (attr != NULL) {
7762 if (attr->ns == NULL) {
7763 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7764 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7765 {
7766 xmlSchemaPIllegalAttrErr(pctxt,
7767 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7768 }
7769 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7770 xmlSchemaPIllegalAttrErr(pctxt,
7771 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7772 }
7773 attr = attr->next;
7774 }
7775 /* Attribute ID */
7776 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7777 /*
7778 * And now for the children...
7779 */
7780 child = node->children;
7781 if (IS_SCHEMA(child, "annotation")) {
7782 ret->annot = xmlSchemaParseAnnotation(pctxt, schema, child, 1);
7783 child = child->next;
7784 }
7785 /*
7786 * Parse contained attribute decls/refs.
7787 */
7788 if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7789 (xmlSchemaItemListPtr *) &(ret->attrUses),
7790 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7791 return(NULL);
7792 if (hasRefs)
7793 ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7794 /*
7795 * Parse the attribute wildcard.
7796 */
7797 if (IS_SCHEMA(child, "anyAttribute")) {
7798 ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7799 schema, child);
7800 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007801 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007802 if (child != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007803 xmlSchemaPContentErr(pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007804 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007805 NULL, node, child, NULL,
7806 "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007807 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007808 return (ret);
7809}
7810
7811/**
William M. Brack2f2a6632004-08-20 23:09:47 +00007812 * xmlSchemaPValAttrFormDefault:
7813 * @value: the value
7814 * @flags: the flags to be modified
7815 * @flagQualified: the specific flag for "qualified"
7816 *
7817 * Returns 0 if the value is valid, 1 otherwise.
7818 */
7819static int
7820xmlSchemaPValAttrFormDefault(const xmlChar *value,
7821 int *flags,
7822 int flagQualified)
7823{
7824 if (xmlStrEqual(value, BAD_CAST "qualified")) {
7825 if ((*flags & flagQualified) == 0)
7826 *flags |= flagQualified;
7827 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007828 return (1);
7829
William M. Brack2f2a6632004-08-20 23:09:47 +00007830 return (0);
7831}
7832
7833/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00007834 * xmlSchemaPValAttrBlockFinal:
7835 * @value: the value
7836 * @flags: the flags to be modified
7837 * @flagAll: the specific flag for "#all"
7838 * @flagExtension: the specific flag for "extension"
7839 * @flagRestriction: the specific flag for "restriction"
7840 * @flagSubstitution: the specific flag for "substitution"
7841 * @flagList: the specific flag for "list"
7842 * @flagUnion: the specific flag for "union"
7843 *
7844 * Validates the value of the attribute "final" and "block". The value
7845 * is converted into the specified flag values and returned in @flags.
7846 *
7847 * Returns 0 if the value is valid, 1 otherwise.
7848 */
7849
7850static int
7851xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007852 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007853 int flagAll,
7854 int flagExtension,
7855 int flagRestriction,
7856 int flagSubstitution,
7857 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007858 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007859{
7860 int ret = 0;
7861
7862 /*
7863 * TODO: This does not check for dublicate entries.
7864 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007865 if ((flags == NULL) || (value == NULL))
7866 return (-1);
7867 if (value[0] == 0)
7868 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007869 if (xmlStrEqual(value, BAD_CAST "#all")) {
7870 if (flagAll != -1)
7871 *flags |= flagAll;
7872 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007873 if (flagExtension != -1)
7874 *flags |= flagExtension;
7875 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007876 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007877 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007878 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007879 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007880 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007881 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007882 *flags |= flagUnion;
7883 }
7884 } else {
7885 const xmlChar *end, *cur = value;
7886 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007887
Daniel Veillardc0826a72004-08-10 14:17:33 +00007888 do {
7889 while (IS_BLANK_CH(*cur))
7890 cur++;
7891 end = cur;
7892 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7893 end++;
7894 if (end == cur)
7895 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007896 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007897 if (xmlStrEqual(item, BAD_CAST "extension")) {
7898 if (flagExtension != -1) {
7899 if ((*flags & flagExtension) == 0)
7900 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007901 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007902 ret = 1;
7903 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7904 if (flagRestriction != -1) {
7905 if ((*flags & flagRestriction) == 0)
7906 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007907 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007908 ret = 1;
7909 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7910 if (flagSubstitution != -1) {
7911 if ((*flags & flagSubstitution) == 0)
7912 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007913 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007914 ret = 1;
7915 } else if (xmlStrEqual(item, BAD_CAST "list")) {
7916 if (flagList != -1) {
7917 if ((*flags & flagList) == 0)
7918 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007919 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007920 ret = 1;
7921 } else if (xmlStrEqual(item, BAD_CAST "union")) {
7922 if (flagUnion != -1) {
7923 if ((*flags & flagUnion) == 0)
7924 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007925 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007926 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007927 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007928 ret = 1;
7929 if (item != NULL)
7930 xmlFree(item);
7931 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007932 } while ((ret == 0) && (*cur != 0));
7933 }
7934
Daniel Veillardc0826a72004-08-10 14:17:33 +00007935 return (ret);
7936}
7937
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007938static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007939xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007940 xmlSchemaIDCPtr idc,
7941 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007942 xmlAttrPtr attr,
7943 int isField)
7944{
7945 xmlNodePtr node;
7946
7947 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007948 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007949 * Schema Component Constraint: Selector Value OK
7950 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007951 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007952 * in [XPath].
7953 */
7954 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007955 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007956 XML_SCHEMAP_INTERNAL,
7957 "Internal error: xmlSchemaCheckCSelectorXPath, "
7958 "the selector is not specified.\n", NULL, NULL);
7959 return (-1);
7960 }
7961 if (attr == NULL)
7962 node = idc->node;
7963 else
7964 node = (xmlNodePtr) attr;
7965 if (selector->xpath == NULL) {
7966 xmlSchemaPCustomErr(ctxt,
7967 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007968 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007969 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007970 "The XPath expression of the selector is not valid", NULL);
7971 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
7972 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007973 const xmlChar **nsArray = NULL;
7974 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007975 /*
7976 * Compile the XPath expression.
7977 */
7978 /*
7979 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007980 * TODO: Call xmlPatterncompile with different options for selector/
7981 * field.
7982 */
7983 nsList = xmlGetNsList(attr->doc, attr->parent);
7984 /*
7985 * Build an array of prefixes and namespaces.
7986 */
7987 if (nsList != NULL) {
7988 int i, count = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007989
7990 for (i = 0; nsList[i] != NULL; i++)
7991 count++;
7992
7993 nsArray = (const xmlChar **) xmlMalloc(
7994 (count * 2 + 1) * sizeof(const xmlChar *));
7995 if (nsArray == NULL) {
7996 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
7997 NULL);
Kasimier T. Buchcik940ab0c2005-10-19 17:00:53 +00007998 xmlFree(nsList);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007999 return (-1);
8000 }
8001 for (i = 0; i < count; i++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008002 nsArray[2 * i] = nsList[i]->href;
8003 nsArray[2 * i + 1] = nsList[i]->prefix;
8004 }
8005 nsArray[count * 2] = NULL;
8006 xmlFree(nsList);
8007 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008008 /*
8009 * TODO: Differentiate between "selector" and "field".
8010 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008011 if (isField)
8012 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008013 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008014 else
8015 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008016 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008017 if (nsArray != NULL)
8018 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008019
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00008020 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008021 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00008022 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008023 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008024 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008025 "The XPath expression '%s' could not be "
8026 "compiled", selector->xpath);
8027 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008028 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008029 }
8030 return (0);
8031}
8032
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008033#define ADD_ANNOTATION(annot) \
8034 xmlSchemaAnnotPtr cur = item->annot; \
8035 if (item->annot == NULL) { \
8036 item->annot = annot; \
8037 return (annot); \
8038 } \
8039 cur = item->annot; \
8040 if (cur->next != NULL) { \
8041 cur = cur->next; \
8042 } \
8043 cur->next = annot;
8044
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008045/**
8046 * xmlSchemaAssignAnnotation:
8047 * @item: the schema component
8048 * @annot: the annotation
8049 *
8050 * Adds the annotation to the given schema component.
8051 *
8052 * Returns the given annotaion.
8053 */
8054static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008055xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8056 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008057{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008058 if ((annItem == NULL) || (annot == NULL))
8059 return (NULL);
8060 switch (annItem->type) {
8061 case XML_SCHEMA_TYPE_ELEMENT: {
8062 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8063 ADD_ANNOTATION(annot)
8064 }
8065 break;
8066 case XML_SCHEMA_TYPE_ATTRIBUTE: {
8067 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8068 ADD_ANNOTATION(annot)
8069 }
8070 break;
8071 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8072 case XML_SCHEMA_TYPE_ANY: {
8073 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8074 ADD_ANNOTATION(annot)
8075 }
8076 break;
8077 case XML_SCHEMA_TYPE_PARTICLE:
8078 case XML_SCHEMA_TYPE_IDC_KEY:
8079 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008080 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008081 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8082 ADD_ANNOTATION(annot)
8083 }
8084 break;
8085 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8086 xmlSchemaAttributeGroupPtr item =
8087 (xmlSchemaAttributeGroupPtr) annItem;
8088 ADD_ANNOTATION(annot)
8089 }
8090 break;
8091 case XML_SCHEMA_TYPE_NOTATION: {
8092 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8093 ADD_ANNOTATION(annot)
8094 }
8095 break;
8096 case XML_SCHEMA_FACET_MININCLUSIVE:
8097 case XML_SCHEMA_FACET_MINEXCLUSIVE:
8098 case XML_SCHEMA_FACET_MAXINCLUSIVE:
8099 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8100 case XML_SCHEMA_FACET_TOTALDIGITS:
8101 case XML_SCHEMA_FACET_FRACTIONDIGITS:
8102 case XML_SCHEMA_FACET_PATTERN:
8103 case XML_SCHEMA_FACET_ENUMERATION:
8104 case XML_SCHEMA_FACET_WHITESPACE:
8105 case XML_SCHEMA_FACET_LENGTH:
8106 case XML_SCHEMA_FACET_MAXLENGTH:
8107 case XML_SCHEMA_FACET_MINLENGTH: {
8108 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8109 ADD_ANNOTATION(annot)
8110 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008111 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008112 case XML_SCHEMA_TYPE_SIMPLE:
8113 case XML_SCHEMA_TYPE_COMPLEX: {
8114 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8115 ADD_ANNOTATION(annot)
8116 }
8117 break;
8118 case XML_SCHEMA_TYPE_GROUP: {
8119 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8120 ADD_ANNOTATION(annot)
8121 }
8122 break;
8123 case XML_SCHEMA_TYPE_SEQUENCE:
8124 case XML_SCHEMA_TYPE_CHOICE:
8125 case XML_SCHEMA_TYPE_ALL: {
8126 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8127 ADD_ANNOTATION(annot)
8128 }
8129 break;
8130 default:
8131 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008132 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008133 NULL, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008134 "Internal error: xmlSchemaAddAnnotation, "
8135 "The item is not a annotated schema component", NULL);
8136 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008137 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008138 return (annot);
8139}
8140
8141/**
8142 * xmlSchemaParseIDCSelectorAndField:
8143 * @ctxt: a schema validation context
8144 * @schema: the schema being built
8145 * @node: a subtree containing XML Schema informations
8146 *
8147 * Parses a XML Schema identity-contraint definition's
8148 * <selector> and <field> elements.
8149 *
8150 * Returns the parsed identity-constraint definition.
8151 */
8152static xmlSchemaIDCSelectPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008153xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008154 xmlSchemaPtr schema,
8155 xmlSchemaIDCPtr idc,
8156 xmlNodePtr node,
8157 int isField)
8158{
8159 xmlSchemaIDCSelectPtr item;
8160 xmlNodePtr child = NULL;
8161 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008162
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008163 /*
8164 * Check for illegal attributes.
8165 */
8166 attr = node->properties;
8167 while (attr != NULL) {
8168 if (attr->ns == NULL) {
8169 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8170 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008171 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008172 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008173 }
8174 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008175 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008176 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008177 }
8178 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008179 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008180 /*
8181 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008182 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008183 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8184 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008185 xmlSchemaPErrMemory(ctxt,
8186 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008187 NULL);
8188 return (NULL);
8189 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008190 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008191 /*
8192 * Attribute "xpath" (mandatory).
8193 */
8194 attr = xmlSchemaGetPropNode(node, "xpath");
8195 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008196 xmlSchemaPMissingAttrErr(ctxt,
8197 XML_SCHEMAP_S4S_ATTR_MISSING,
8198 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008199 "name", NULL);
8200 } else {
8201 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8202 /*
8203 * URGENT TODO: "field"s have an other syntax than "selector"s.
8204 */
8205
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008206 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8207 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008208 xmlSchemaPErr(ctxt,
8209 (xmlNodePtr) attr,
8210 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008211 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008212 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008213 NULL, NULL);
8214 }
8215
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008216 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008217 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008218 /*
8219 * And now for the children...
8220 */
8221 child = node->children;
8222 if (IS_SCHEMA(child, "annotation")) {
8223 /*
8224 * Add the annotation to the parent IDC.
8225 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008226 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008227 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008228 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008229 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008230 if (child != NULL) {
8231 xmlSchemaPContentErr(ctxt,
8232 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008233 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008234 NULL, "(annotation?)");
8235 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008236
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008237 return (item);
8238}
8239
8240/**
8241 * xmlSchemaParseIDC:
8242 * @ctxt: a schema validation context
8243 * @schema: the schema being built
8244 * @node: a subtree containing XML Schema informations
8245 *
8246 * Parses a XML Schema identity-contraint definition.
8247 *
8248 * Returns the parsed identity-constraint definition.
8249 */
8250static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008251xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008252 xmlSchemaPtr schema,
8253 xmlNodePtr node,
8254 xmlSchemaTypeType idcCategory,
8255 const xmlChar *targetNamespace)
8256{
8257 xmlSchemaIDCPtr item = NULL;
8258 xmlNodePtr child = NULL;
8259 xmlAttrPtr attr;
8260 const xmlChar *name = NULL;
8261 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008262
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008263 /*
8264 * Check for illegal attributes.
8265 */
8266 attr = node->properties;
8267 while (attr != NULL) {
8268 if (attr->ns == NULL) {
8269 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8270 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8271 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8272 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008273 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008274 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008275 }
8276 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008277 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008278 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008279 }
8280 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008281 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008282 /*
8283 * Attribute "name" (mandatory).
8284 */
8285 attr = xmlSchemaGetPropNode(node, "name");
8286 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008287 xmlSchemaPMissingAttrErr(ctxt,
8288 XML_SCHEMAP_S4S_ATTR_MISSING,
8289 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008290 "name", NULL);
8291 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008292 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008293 NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008294 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8295 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008296 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008297 /* Create the component. */
8298 item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8299 idcCategory, node);
8300 if (item == NULL)
8301 return(NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008302
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008303 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008304 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8305 /*
8306 * Attribute "refer" (mandatory).
8307 */
8308 attr = xmlSchemaGetPropNode(node, "refer");
8309 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008310 xmlSchemaPMissingAttrErr(ctxt,
8311 XML_SCHEMAP_S4S_ATTR_MISSING,
8312 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008313 "refer", NULL);
8314 } else {
8315 /*
8316 * Create a reference item.
8317 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008318 item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008319 NULL, NULL);
8320 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008321 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008322 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008323 NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008324 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008325 &(item->ref->name));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008326 xmlSchemaCheckReference(ctxt, schema, node, attr,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008327 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008328 }
8329 }
8330 /*
8331 * And now for the children...
8332 */
8333 child = node->children;
8334 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008335 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008336 child = child->next;
8337 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00008338 if (child == NULL) {
8339 xmlSchemaPContentErr(ctxt,
8340 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008341 NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00008342 "A child element is missing",
8343 "(annotation?, (selector, field+))");
8344 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008345 /*
8346 * Child element <selector>.
8347 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008348 if (IS_SCHEMA(child, "selector")) {
8349 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008350 item, child, 0);
8351 child = child->next;
8352 /*
8353 * Child elements <field>.
8354 */
8355 if (IS_SCHEMA(child, "field")) {
8356 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008357 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008358 item, child, 1);
8359 if (field != NULL) {
8360 field->index = item->nbFields;
8361 item->nbFields++;
8362 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008363 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008364 else
8365 item->fields = field;
8366 lastField = field;
8367 }
8368 child = child->next;
8369 } while (IS_SCHEMA(child, "field"));
8370 } else {
8371 xmlSchemaPContentErr(ctxt,
8372 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008373 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008374 NULL, "(annotation?, (selector, field+))");
8375 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008376 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008377 if (child != NULL) {
8378 xmlSchemaPContentErr(ctxt,
8379 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008380 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008381 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008382 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008383
8384 return (item);
8385}
8386
Daniel Veillardc0826a72004-08-10 14:17:33 +00008387/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008388 * xmlSchemaParseElement:
8389 * @ctxt: a schema validation context
8390 * @schema: the schema being built
8391 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008392 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00008393 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008394 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00008395 * *WARNING* this interface is highly subject to change
8396 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008397 * Returns the element declaration or a particle; NULL in case
8398 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00008399 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008400static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00008401xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008402 xmlNodePtr node, int *isElemRef, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008403{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008404 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008405 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008406 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008407 xmlNodePtr child = NULL;
8408 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008409 int min, max, isRef = 0;
8410 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00008411
8412 /* 3.3.3 Constraints on XML Representations of Element Declarations */
8413 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008414
Daniel Veillard4255d502002-04-16 15:50:10 +00008415 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008416 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008417
8418 if (isElemRef != NULL)
8419 *isElemRef = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008420 /*
8421 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008422 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008423 * robust.
8424 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008425 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008426 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008427 if ((topLevel) || (attr == NULL)) {
8428 if (nameAttr == NULL) {
8429 xmlSchemaPMissingAttrErr(ctxt,
8430 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008431 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008432 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008433 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008434 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00008435 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008436
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008437 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008438 child = node->children;
8439 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008440 annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008441 child = child->next;
8442 }
8443 /*
8444 * Skip particle part if a global declaration.
8445 */
8446 if (topLevel)
8447 goto declaration_part;
8448 /*
8449 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008450 */
8451 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8452 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8453 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008454 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8455 if (particle == NULL)
8456 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008457
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008458 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8459
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008460 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008461 const xmlChar *refNs = NULL, *ref = NULL;
8462 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008463 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008464 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00008465 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008466 if (isElemRef != NULL)
8467 *isElemRef = 1;
8468
Daniel Veillardc0826a72004-08-10 14:17:33 +00008469 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008470 NULL, attr, &refNs, &ref);
8471 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008472 /*
8473 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00008474 */
8475 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008476 xmlSchemaPMutualExclAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008477 XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008478 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008479 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008480 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008481 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008482 attr = node->properties;
8483 while (attr != NULL) {
8484 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008485 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8486 xmlStrEqual(attr->name, BAD_CAST "name") ||
8487 xmlStrEqual(attr->name, BAD_CAST "id") ||
8488 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8489 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8490 {
8491 attr = attr->next;
8492 continue;
8493 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008494 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008495 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008496 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008497 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008498 "Only the attributes 'minOccurs', 'maxOccurs' and "
8499 "'id' are allowed in addition to 'ref'");
8500 break;
8501 }
8502 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8503 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008504 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008505 }
8506 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008507 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008508 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008509 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008510 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008511 if (child != NULL) {
8512 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008513 NULL, node, child, NULL, "(annotation?)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008514 }
8515 if ((min == 0) && (max == 0))
8516 goto return_null;
8517 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008518 * Create the reference item and attach it to the particle.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008519 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008520 refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008521 ref, refNs);
8522 if (refer == NULL)
8523 goto return_null;
8524 particle->children = (xmlSchemaTreeItemPtr) refer;
8525 particle->annot = annot;
8526 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008527 * Add the particle to pending components, since the reference
8528 * need to be resolved.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008529 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008530 WXS_ADD_PENDING(ctxt, particle);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008531 return ((xmlSchemaBasicItemPtr) particle);
8532 }
8533 /*
8534 * The declaration part ===============================================
8535 */
8536declaration_part:
8537 {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008538 const xmlChar *ns = NULL, *fixed, *name, *attrValue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008539 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8540
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008541 if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008542 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008543 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008544 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008545 * Evaluate the target namespace.
8546 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008547 if (topLevel) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008548 ns = ctxt->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008549 } else {
8550 attr = xmlSchemaGetPropNode(node, "form");
8551 if (attr != NULL) {
8552 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8553 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008554 ns = ctxt->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008555 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008556 xmlSchemaPSimpleTypeErr(ctxt,
8557 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8558 NULL, (xmlNodePtr) attr,
8559 NULL, "(qualified | unqualified)",
8560 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008561 }
8562 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008563 ns = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008564 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008565 decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008566 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008567 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00008568 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008569 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008570 * Check for illegal attributes.
8571 */
William M. Bracke7091952004-05-11 15:09:58 +00008572 attr = node->properties;
8573 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008574 if (attr->ns == NULL) {
8575 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8576 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008577 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008578 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008579 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008580 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008581 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8582 {
8583 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008584 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008585 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008586 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008587 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008588 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008589 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008590 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008591 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8592 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008593 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8594
8595 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008596 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008597 }
8598 }
8599 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008600
Daniel Veillardc0826a72004-08-10 14:17:33 +00008601 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008602 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Bracke7091952004-05-11 15:09:58 +00008603 }
8604 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008605 }
William M. Bracke7091952004-05-11 15:09:58 +00008606 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008607 * Extract/validate attributes.
8608 */
8609 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008610 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008611 * Process top attributes of global element declarations here.
8612 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008613 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8614 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008615 xmlSchemaPValAttrQName(ctxt, schema,
8616 NULL, node, "substitutionGroup",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008617 &(decl->substGroupNs), &(decl->substGroup));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008618 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008619 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008620 /*
8621 * Attribute "final".
8622 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008623 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008624 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008625 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8626 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8627 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8628 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008629 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008630 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8631 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00008632 -1,
8633 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8634 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008635 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008636 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008637 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008638 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008639 attrValue, NULL, NULL, NULL);
8640 }
8641 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008642 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008643 /*
8644 * Attribute "block".
8645 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008646 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008647 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00008648 /*
8649 * Apply default "block" values.
8650 */
8651 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8652 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8653 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8654 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8655 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8656 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008657 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008658 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8659 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00008660 -1,
8661 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008662 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008663 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8664 xmlSchemaPSimpleTypeErr(ctxt,
8665 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008666 NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00008667 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008668 "restriction | substitution))", attrValue,
8669 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008670 }
8671 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008672 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008673 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008674
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008675 attr = xmlSchemaGetPropNode(node, "type");
8676 if (attr != NULL) {
8677 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008678 NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008679 &(decl->namedTypeNs), &(decl->namedType));
8680 xmlSchemaCheckReference(ctxt, schema, node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008681 attr, decl->namedTypeNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008682 }
8683 decl->value = xmlSchemaGetProp(ctxt, node, "default");
8684 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008685 if (attr != NULL) {
8686 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008687 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008688 /*
8689 * 3.3.3 : 1
8690 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008691 */
8692 xmlSchemaPMutualExclAttrErr(ctxt,
8693 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008694 NULL, attr, "default", "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008695 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008696 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8697 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008698 }
William M. Bracke7091952004-05-11 15:09:58 +00008699 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008700 /*
8701 * And now for the children...
8702 */
William M. Bracke7091952004-05-11 15:09:58 +00008703 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008704 /*
8705 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00008706 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008707 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00008708 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008709 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008710 xmlSchemaPContentErr(ctxt,
8711 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008712 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008713 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008714 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008715 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008716 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00008717 child = child->next;
8718 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008719 /*
8720 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00008721 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008722 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00008723 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008724 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008725 xmlSchemaPContentErr(ctxt,
8726 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008727 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008728 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008729 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008730 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008731 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00008732 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008733 }
William M. Bracke7091952004-05-11 15:09:58 +00008734 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00008735 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008736 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008737 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008738 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008739 } else if (IS_SCHEMA(child, "key")) {
8740 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008741 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008742 } else if (IS_SCHEMA(child, "keyref")) {
8743 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008744 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008745 }
8746 if (lastIDC != NULL)
8747 lastIDC->next = curIDC;
8748 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008749 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008750 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008751 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00008752 }
8753 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008754 xmlSchemaPContentErr(ctxt,
8755 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008756 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008757 NULL, "(annotation?, ((simpleType | complexType)?, "
8758 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008759 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008760 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008761 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008762 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008763 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00008764 * different layer.
8765 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008766 FREE_AND_NULL(des)
8767 if (topLevel)
8768 return ((xmlSchemaBasicItemPtr) decl);
8769 else {
8770 particle->children = (xmlSchemaTreeItemPtr) decl;
8771 return ((xmlSchemaBasicItemPtr) particle);
8772 }
8773
8774return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008775 FREE_AND_NULL(des);
8776 if (annot != NULL) {
8777 if (particle != NULL)
8778 particle->annot = NULL;
8779 if (decl != NULL)
8780 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008781 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008782 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008783 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008784}
8785
8786/**
8787 * xmlSchemaParseUnion:
8788 * @ctxt: a schema validation context
8789 * @schema: the schema being built
8790 * @node: a subtree containing XML Schema informations
8791 *
8792 * parse a XML schema Union definition
8793 * *WARNING* this interface is highly subject to change
8794 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008795 * Returns -1 in case of internal error, 0 in case of success and a positive
8796 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00008797 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008798static int
Daniel Veillard4255d502002-04-16 15:50:10 +00008799xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008800 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008801{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008802 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008803 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008804 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008805 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008806
8807 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008808 return (-1);
8809 /* Not a component, don't create it. */
8810 type = ctxt->ctxtType;
8811 /*
8812 * Mark the simple type as being of variety "union".
8813 */
8814 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008815 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008816 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8817 * then the ·simple ur-type definition·."
8818 */
8819 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008820 /*
8821 * Check for illegal attributes.
8822 */
8823 attr = node->properties;
8824 while (attr != NULL) {
8825 if (attr->ns == NULL) {
8826 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8827 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008828 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008829 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008830 }
8831 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008832 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008833 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008834 }
8835 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008836 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008837 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008838 /*
8839 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008840 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00008841 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008842 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008843 if (attr != NULL) {
8844 const xmlChar *end;
8845 xmlChar *tmp;
8846 const xmlChar *localName, *nsName;
8847 xmlSchemaTypeLinkPtr link, lastLink = NULL;
8848 xmlSchemaQNameRefPtr ref;
8849
8850 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008851 type->base = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008852 do {
8853 while (IS_BLANK_CH(*cur))
8854 cur++;
8855 end = cur;
8856 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8857 end++;
8858 if (end == cur)
8859 break;
8860 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008861 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008862 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008863 /*
8864 * Create the member type link.
8865 */
8866 link = (xmlSchemaTypeLinkPtr)
8867 xmlMalloc(sizeof(xmlSchemaTypeLink));
8868 if (link == NULL) {
8869 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8870 "allocating a type link", NULL);
8871 return (-1);
8872 }
8873 link->type = NULL;
8874 link->next = NULL;
8875 if (lastLink == NULL)
8876 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008877 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008878 lastLink->next = link;
8879 lastLink = link;
8880 /*
8881 * Create a reference item.
8882 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008883 ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008884 localName, nsName);
8885 if (ref == NULL) {
8886 FREE_AND_NULL(tmp)
8887 return (-1);
8888 }
8889 /*
8890 * Assign the reference to the link, it will be resolved
8891 * later during fixup of the union simple type.
8892 */
8893 link->type = (xmlSchemaTypePtr) ref;
8894 }
8895 FREE_AND_NULL(tmp)
8896 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008897 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008898
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008899 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008900 /*
8901 * And now for the children...
8902 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008903 child = node->children;
8904 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008905 /*
8906 * Add the annotation to the simple type ancestor.
8907 */
8908 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008909 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008910 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008911 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008912 if (IS_SCHEMA(child, "simpleType")) {
8913 xmlSchemaTypePtr subtype, last = NULL;
8914
8915 /*
8916 * Anchor the member types in the "subtypes" field of the
8917 * simple type.
8918 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008919 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008920 subtype = (xmlSchemaTypePtr)
8921 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8922 if (subtype != NULL) {
8923 if (last == NULL) {
8924 type->subtypes = subtype;
8925 last = subtype;
8926 } else {
8927 last->next = subtype;
8928 last = subtype;
8929 }
8930 last->next = NULL;
8931 }
8932 child = child->next;
8933 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008934 }
8935 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008936 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008937 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008938 NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008939 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008940 if ((attr == NULL) && (type->subtypes == NULL)) {
8941 /*
8942 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008943 * Either the memberTypes [attribute] of the <union> element must
8944 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008945 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008946 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008947 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008948 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008949 "Either the attribute 'memberTypes' or "
8950 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008951 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008952 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00008953}
8954
8955/**
8956 * xmlSchemaParseList:
8957 * @ctxt: a schema validation context
8958 * @schema: the schema being built
8959 * @node: a subtree containing XML Schema informations
8960 *
8961 * parse a XML schema List definition
8962 * *WARNING* this interface is highly subject to change
8963 *
William M. Bracke7091952004-05-11 15:09:58 +00008964 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008965 * 1 in case of success.
8966 */
8967static xmlSchemaTypePtr
8968xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008969 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008970{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008971 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008972 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008973 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008974
8975 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8976 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008977 /* Not a component, don't create it. */
8978 type = ctxt->ctxtType;
8979 /*
8980 * Mark the type as being of variety "list".
8981 */
8982 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008983 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008984 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8985 * then the ·simple ur-type definition·."
8986 */
8987 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008988 /*
8989 * Check for illegal attributes.
8990 */
8991 attr = node->properties;
8992 while (attr != NULL) {
8993 if (attr->ns == NULL) {
8994 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8995 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008996 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008997 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008998 }
8999 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009000 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009001 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009002 }
9003 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009004 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009005
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009006 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009007
William M. Brack2f2a6632004-08-20 23:09:47 +00009008 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009009 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9010 * fields for holding the reference to the itemType.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009011 *
9012 * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9013 * the "ref" fields.
William M. Brack2f2a6632004-08-20 23:09:47 +00009014 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009015 xmlSchemaPValAttrQName(ctxt, schema, NULL,
9016 node, "itemType", &(type->baseNs), &(type->base));
William M. Brack2f2a6632004-08-20 23:09:47 +00009017 /*
9018 * And now for the children...
9019 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009020 child = node->children;
9021 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009022 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009023 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009024 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009025 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009026 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009027 /*
9028 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009029 * Either the itemType [attribute] or the <simpleType> [child] of
9030 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009031 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009032 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009033 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009034 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009035 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00009036 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009037 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009038 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009039 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009040 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009041 child = child->next;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009042 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009043 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009044 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009045 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009046 "Either the attribute 'itemType' or the <simpleType> child "
9047 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009048 }
9049 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009050 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009051 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009052 NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00009053 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009054 if ((type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009055 (type->subtypes == NULL) &&
9056 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009057 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009058 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009059 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009060 "Either the attribute 'itemType' or the <simpleType> child "
9061 "must be present", NULL);
9062 }
9063 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009064}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009065
Daniel Veillard4255d502002-04-16 15:50:10 +00009066/**
9067 * xmlSchemaParseSimpleType:
9068 * @ctxt: a schema validation context
9069 * @schema: the schema being built
9070 * @node: a subtree containing XML Schema informations
9071 *
9072 * parse a XML schema Simple Type definition
9073 * *WARNING* this interface is highly subject to change
9074 *
William M. Bracke7091952004-05-11 15:09:58 +00009075 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00009076 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00009077 */
9078static xmlSchemaTypePtr
9079xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00009080 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00009081{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009082 xmlSchemaTypePtr type, oldCtxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009083 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009084 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009085 xmlAttrPtr attr;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009086 int hasRestriction = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009087
9088 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9089 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009090
Daniel Veillardc0826a72004-08-10 14:17:33 +00009091 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009092 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009093 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009094 xmlSchemaPMissingAttrErr(ctxt,
9095 XML_SCHEMAP_S4S_ATTR_MISSING,
9096 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009097 "name", NULL);
9098 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009099 } else {
9100 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009101 NULL, attr,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009102 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9103 return (NULL);
9104 /*
9105 * Skip built-in types.
9106 */
9107 if (ctxt->isS4S) {
9108 xmlSchemaTypePtr biType;
9109
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009110 if (ctxt->isRedefine) {
9111 /*
9112 * REDEFINE: Disallow redefinition of built-in-types.
9113 * TODO: It seems that the spec does not say anything
9114 * about this case.
9115 */
9116 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009117 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009118 "Redefinition of built-in simple types is not "
9119 "supported", NULL);
9120 return(NULL);
9121 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009122 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9123 if (biType != NULL)
9124 return (biType);
9125 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009126 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009127 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009128 /*
9129 * TargetNamespace:
9130 * SPEC "The ·actual value· of the targetNamespace [attribute]
9131 * of the <schema> ancestor element information item if present,
9132 * otherwise ·absent·.
9133 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009134 if (topLevel == 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009135#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009136 char buf[40];
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009137#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +00009138 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00009139 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009140 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009141#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009142 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009143 type = xmlSchemaAddType(ctxt, schema,
9144 XML_SCHEMA_TYPE_SIMPLE,
9145 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009146 ctxt->targetNamespace, node, 0);
9147#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009148 type = xmlSchemaAddType(ctxt, schema,
9149 XML_SCHEMA_TYPE_SIMPLE,
9150 NULL, ctxt->targetNamespace, node, 0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009151#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +00009152 if (type == NULL)
9153 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009154 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009155 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009156 /*
9157 * Check for illegal attributes.
9158 */
9159 attr = node->properties;
9160 while (attr != NULL) {
9161 if (attr->ns == NULL) {
9162 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009163 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009164 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009165 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009166 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009167 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009168 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009169 }
9170 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009171 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009172 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009173 /*
9174 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009175 *
9176 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009177 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009178 type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9179 attrValue, ctxt->targetNamespace, node, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009180 if (type == NULL)
9181 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009182 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009183 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009184 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9185 /*
9186 * Check for illegal attributes.
9187 */
9188 attr = node->properties;
9189 while (attr != NULL) {
9190 if (attr->ns == NULL) {
9191 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9192 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009193 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009194 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009195 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009196 }
9197 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009198 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009199 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009200 }
9201 attr = attr->next;
9202 }
9203 /*
9204 * Attribute "final".
9205 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009206 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009207 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009208 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9209 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9210 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9211 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9212 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9213 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009214 } else {
9215 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009216 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9217 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009218 XML_SCHEMAS_TYPE_FINAL_LIST,
9219 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9220
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009221 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009222 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009223 WXS_BASIC_CAST type, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009224 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00009225 attrValue, NULL, NULL, NULL);
9226 }
9227 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009228 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009229 type->targetNamespace = ctxt->targetNamespace;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009230 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009231 /*
9232 * And now for the children...
9233 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009234 oldCtxtType = ctxt->ctxtType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009235
Daniel Veillardc0826a72004-08-10 14:17:33 +00009236 ctxt->ctxtType = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009237
Daniel Veillard4255d502002-04-16 15:50:10 +00009238 child = node->children;
9239 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009240 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009241 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009242 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009243 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009244 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009245 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009246 "(annotation?, (restriction | list | union))");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009247 } else if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009248 xmlSchemaParseRestriction(ctxt, schema, child,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009249 XML_SCHEMA_TYPE_SIMPLE);
9250 hasRestriction = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009251 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009252 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009253 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009254 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009255 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009256 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009257 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009258 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009259 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009260 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009261 NULL, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009262 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00009263 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009264 /*
9265 * REDEFINE: SPEC src-redefine (5)
9266 * "Within the [children], each <simpleType> must have a
9267 * <restriction> among its [children] ... the ·actual value· of whose
9268 * base [attribute] must be the same as the ·actual value· of its own
9269 * name attribute plus target namespace;"
9270 */
9271 if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9272 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009273 NULL, node, "This is a redefinition, thus the "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009274 "<simpleType> must have a <restriction> child", NULL);
9275 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009276
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009277 ctxt->ctxtType = oldCtxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009278 return (type);
9279}
9280
Daniel Veillard4255d502002-04-16 15:50:10 +00009281/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009282 * xmlSchemaParseModelGroupDefRef:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009283 * @ctxt: the parser context
9284 * @schema: the schema being built
9285 * @node: the node
Daniel Veillard4255d502002-04-16 15:50:10 +00009286 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009287 * Parses a reference to a model group definition.
Daniel Veillard4255d502002-04-16 15:50:10 +00009288 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009289 * We will return a particle component with a qname-component or
9290 * NULL in case of an error.
Daniel Veillard4255d502002-04-16 15:50:10 +00009291 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009292static xmlSchemaTreeItemPtr
9293xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9294 xmlSchemaPtr schema,
9295 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00009296{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009297 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009298 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009299 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009300 const xmlChar *ref = NULL, *refNs = NULL;
9301 int min, max;
9302
9303 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009304 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009305
9306 attr = xmlSchemaGetPropNode(node, "ref");
9307 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009308 xmlSchemaPMissingAttrErr(ctxt,
9309 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009310 NULL, node, "ref", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009311 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009312 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009313 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009314 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009315 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009316 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009317 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009318 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009319 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009320 /*
9321 * Check for illegal attributes.
9322 */
9323 attr = node->properties;
9324 while (attr != NULL) {
9325 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009326 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009327 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9328 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9329 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009330 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009331 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009332 }
9333 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009334 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009335 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009336 }
9337 attr = attr->next;
9338 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009339 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009340 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
9341 if (item == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009342 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009343 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009344 * Create a qname-reference and set as the term; it will be substituted
9345 * for the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009346 */
9347 item->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009348 xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009349 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9350 /*
9351 * And now for the children...
9352 */
9353 child = node->children;
9354 /* TODO: Is annotation even allowed for a model group reference? */
9355 if (IS_SCHEMA(child, "annotation")) {
9356 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009357 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009358 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009359 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009360 child = child->next;
9361 }
9362 if (child != NULL) {
9363 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009364 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009365 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009366 "(annotation?)");
9367 }
9368 /*
9369 * Corresponds to no component at all if minOccurs==maxOccurs==0.
9370 */
9371 if ((min == 0) && (max == 0))
9372 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009373
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009374 return ((xmlSchemaTreeItemPtr) item);
9375}
9376
9377/**
9378 * xmlSchemaParseModelGroupDefinition:
9379 * @ctxt: a schema validation context
9380 * @schema: the schema being built
9381 * @node: a subtree containing XML Schema informations
9382 *
9383 * Parses a XML schema model group definition.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009384 *
9385 * Note that the contraint src-redefine (6.2) can't be applied until
9386 * references have been resolved. So we will do this at the
9387 * component fixup level.
9388 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009389 * *WARNING* this interface is highly subject to change
9390 *
9391 * Returns -1 in case of error, 0 if the declaration is improper and
9392 * 1 in case of success.
9393 */
9394static xmlSchemaModelGroupDefPtr
9395xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9396 xmlSchemaPtr schema,
9397 xmlNodePtr node)
9398{
9399 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009400 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009401 xmlAttrPtr attr;
9402 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00009403
9404 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009405 return (NULL);
9406
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009407 attr = xmlSchemaGetPropNode(node, "name");
9408 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009409 xmlSchemaPMissingAttrErr(ctxt,
9410 XML_SCHEMAP_S4S_ATTR_MISSING,
9411 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009412 "name", NULL);
9413 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009414 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009415 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9416 return (NULL);
9417 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009418 item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9419 ctxt->targetNamespace, node);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009420 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009421 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009422 /*
9423 * Check for illegal attributes.
9424 */
9425 attr = node->properties;
9426 while (attr != NULL) {
9427 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009428 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009429 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009430 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009431 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009432 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009433 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009434 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009435 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009436 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009437 attr = attr->next;
9438 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009439 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009440 /*
9441 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009442 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009443 child = node->children;
9444 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009445 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009446 child = child->next;
9447 }
9448 if (IS_SCHEMA(child, "all")) {
9449 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9450 XML_SCHEMA_TYPE_ALL, 0);
9451 child = child->next;
9452 } else if (IS_SCHEMA(child, "choice")) {
9453 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9454 XML_SCHEMA_TYPE_CHOICE, 0);
9455 child = child->next;
9456 } else if (IS_SCHEMA(child, "sequence")) {
9457 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9458 XML_SCHEMA_TYPE_SEQUENCE, 0);
9459 child = child->next;
9460 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009461
9462
9463
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009464 if (child != NULL) {
9465 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009466 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009467 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009468 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009469 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009470 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009471}
9472
9473/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009474 * xmlSchemaCleanupDoc:
9475 * @ctxt: a schema validation context
9476 * @node: the root of the document.
9477 *
9478 * removes unwanted nodes in a schemas document tree
9479 */
9480static void
9481xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9482{
9483 xmlNodePtr delete, cur;
9484
9485 if ((ctxt == NULL) || (root == NULL)) return;
9486
9487 /*
9488 * Remove all the blank text nodes
9489 */
9490 delete = NULL;
9491 cur = root;
9492 while (cur != NULL) {
9493 if (delete != NULL) {
9494 xmlUnlinkNode(delete);
9495 xmlFreeNode(delete);
9496 delete = NULL;
9497 }
9498 if (cur->type == XML_TEXT_NODE) {
9499 if (IS_BLANK_NODE(cur)) {
9500 if (xmlNodeGetSpacePreserve(cur) != 1) {
9501 delete = cur;
9502 }
9503 }
9504 } else if ((cur->type != XML_ELEMENT_NODE) &&
9505 (cur->type != XML_CDATA_SECTION_NODE)) {
9506 delete = cur;
9507 goto skip_children;
9508 }
9509
9510 /*
9511 * Skip to next node
9512 */
9513 if (cur->children != NULL) {
9514 if ((cur->children->type != XML_ENTITY_DECL) &&
9515 (cur->children->type != XML_ENTITY_REF_NODE) &&
9516 (cur->children->type != XML_ENTITY_NODE)) {
9517 cur = cur->children;
9518 continue;
9519 }
9520 }
9521 skip_children:
9522 if (cur->next != NULL) {
9523 cur = cur->next;
9524 continue;
9525 }
9526
9527 do {
9528 cur = cur->parent;
9529 if (cur == NULL)
9530 break;
9531 if (cur == root) {
9532 cur = NULL;
9533 break;
9534 }
9535 if (cur->next != NULL) {
9536 cur = cur->next;
9537 break;
9538 }
9539 } while (cur != NULL);
9540 }
9541 if (delete != NULL) {
9542 xmlUnlinkNode(delete);
9543 xmlFreeNode(delete);
9544 delete = NULL;
9545 }
9546}
9547
William M. Brack2f2a6632004-08-20 23:09:47 +00009548
William M. Brack2f2a6632004-08-20 23:09:47 +00009549static void
9550xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9551{
9552 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9553 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9554
9555 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9556 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9557
9558 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9559 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9560 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9561 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9562 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9563 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9564 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9565 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9566
9567 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9568 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9569 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9570 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9571 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9572 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9573}
9574
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009575static int
9576xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009577 xmlSchemaPtr schema,
9578 xmlNodePtr node)
9579{
9580 xmlAttrPtr attr;
9581 const xmlChar *val;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009582 int res = 0, oldErrs = ctxt->nberrors;
William M. Brack2f2a6632004-08-20 23:09:47 +00009583
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009584 /*
9585 * Those flags should be moved to the parser context flags,
9586 * since they are not visible at the component level. I.e.
9587 * they are used if processing schema *documents* only.
9588 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009589 res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009590 HFAILURE;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009591
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009592 /*
9593 * Since the version is of type xs:token, we won't bother to
9594 * check it.
9595 */
9596 /* REMOVED:
9597 attr = xmlSchemaGetPropNode(node, "version");
9598 if (attr != NULL) {
9599 res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9600 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9601 HFAILURE;
9602 }
9603 */
9604 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9605 if (attr != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009606 res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009607 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9608 HFAILURE;
9609 if (res != 0) {
9610 ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9611 goto exit;
9612 }
9613 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009614 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009615 if (attr != NULL) {
9616 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009617 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9618 XML_SCHEMAS_QUALIF_ELEM);
9619 HFAILURE;
9620 if (res != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009621 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009622 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009623 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009624 "(qualified | unqualified)", val, NULL, NULL, NULL);
9625 }
9626 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009627 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009628 if (attr != NULL) {
9629 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009630 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9631 XML_SCHEMAS_QUALIF_ATTR);
9632 HFAILURE;
9633 if (res != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009634 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009635 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009636 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009637 "(qualified | unqualified)", val, NULL, NULL, NULL);
9638 }
9639 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009640 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009641 if (attr != NULL) {
9642 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009643 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
William M. Brack2f2a6632004-08-20 23:09:47 +00009644 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9645 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9646 -1,
9647 XML_SCHEMAS_FINAL_DEFAULT_LIST,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009648 XML_SCHEMAS_FINAL_DEFAULT_UNION);
9649 HFAILURE;
9650 if (res != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009651 xmlSchemaPSimpleTypeErr(ctxt,
9652 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009653 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009654 "(#all | List of (extension | restriction | list | union))",
9655 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009656 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009657 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009658 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009659 if (attr != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009660 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9661 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
William M. Brack2f2a6632004-08-20 23:09:47 +00009662 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9663 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009664 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9665 HFAILURE;
9666 if (res != 0) {
9667 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009668 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009669 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009670 "(#all | List of (extension | restriction | substitution))",
9671 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009672 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009673 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009674
9675exit:
9676 if (oldErrs != ctxt->nberrors)
9677 res = ctxt->err;
9678 return(res);
9679exit_failure:
9680 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009681}
9682
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009683/**
9684 * xmlSchemaParseSchemaTopLevel:
9685 * @ctxt: a schema validation context
9686 * @schema: the schemas
9687 * @nodes: the list of top level nodes
9688 *
9689 * Returns the internal XML Schema structure built from the resource or
9690 * NULL in case of error
9691 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009692static int
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009693xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9694 xmlSchemaPtr schema, xmlNodePtr nodes)
9695{
9696 xmlNodePtr child;
9697 xmlSchemaAnnotPtr annot;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009698 int res = 0, oldErrs, tmpOldErrs;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009699
9700 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009701 return(-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009702
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009703 oldErrs = ctxt->nberrors;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009704 child = nodes;
9705 while ((IS_SCHEMA(child, "include")) ||
9706 (IS_SCHEMA(child, "import")) ||
9707 (IS_SCHEMA(child, "redefine")) ||
9708 (IS_SCHEMA(child, "annotation"))) {
9709 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009710 annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009711 if (schema->annot == NULL)
9712 schema->annot = annot;
9713 else
9714 xmlSchemaFreeAnnot(annot);
9715 } else if (IS_SCHEMA(child, "import")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009716 tmpOldErrs = ctxt->nberrors;
9717 res = xmlSchemaParseImport(ctxt, schema, child);
9718 HFAILURE;
9719 HSTOP(ctxt);
9720 if (tmpOldErrs != ctxt->nberrors)
9721 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009722 } else if (IS_SCHEMA(child, "include")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009723 tmpOldErrs = ctxt->nberrors;
9724 res = xmlSchemaParseInclude(ctxt, schema, child);
9725 HFAILURE;
9726 HSTOP(ctxt);
9727 if (tmpOldErrs != ctxt->nberrors)
9728 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009729 } else if (IS_SCHEMA(child, "redefine")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009730 tmpOldErrs = ctxt->nberrors;
9731 res = xmlSchemaParseRedefine(ctxt, schema, child);
9732 HFAILURE;
9733 HSTOP(ctxt);
9734 if (tmpOldErrs != ctxt->nberrors)
9735 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009736 }
9737 child = child->next;
9738 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009739 /*
9740 * URGENT TODO: Change the functions to return int results.
9741 * We need especially to catch internal errors.
9742 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009743 while (child != NULL) {
9744 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009745 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009746 child = child->next;
9747 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009748 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009749 child = child->next;
9750 } else if (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009751 xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009752 child = child->next;
9753 } else if (IS_SCHEMA(child, "attribute")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009754 xmlSchemaParseGlobalAttribute(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009755 child = child->next;
9756 } else if (IS_SCHEMA(child, "attributeGroup")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009757 xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009758 child = child->next;
9759 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009760 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009761 child = child->next;
9762 } else if (IS_SCHEMA(child, "notation")) {
9763 xmlSchemaParseNotation(ctxt, schema, child);
9764 child = child->next;
9765 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009766 xmlSchemaPContentErr(ctxt,
9767 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009768 NULL, child->parent, child,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009769 NULL, "((include | import | redefine | annotation)*, "
9770 "(((simpleType | complexType | group | attributeGroup) "
9771 "| element | attribute | notation), annotation*)*)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009772 child = child->next;
9773 }
9774 while (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009775 /*
9776 * TODO: We should add all annotations.
9777 */
9778 annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009779 if (schema->annot == NULL)
9780 schema->annot = annot;
9781 else
9782 xmlSchemaFreeAnnot(annot);
9783 child = child->next;
9784 }
9785 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009786exit:
Daniel Veillard01fa6152004-06-29 17:04:39 +00009787 ctxt->ctxtType = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009788 if (oldErrs != ctxt->nberrors)
9789 res = ctxt->err;
9790 return(res);
9791exit_failure:
9792 return(-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009793}
9794
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009795static xmlSchemaSchemaRelationPtr
9796xmlSchemaSchemaRelationCreate(void)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009797{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009798 xmlSchemaSchemaRelationPtr ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009799
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009800 ret = (xmlSchemaSchemaRelationPtr)
9801 xmlMalloc(sizeof(xmlSchemaSchemaRelation));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009802 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009803 xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009804 return(NULL);
9805 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009806 memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009807 return(ret);
9808}
9809
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009810#if 0
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009811static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009812xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009813{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009814 xmlFree(rel);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009815}
9816#endif
9817
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009818static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009819xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9820{
9821 xmlSchemaRedefPtr prev;
9822
9823 while (redef != NULL) {
9824 prev = redef;
9825 redef = redef->next;
9826 xmlFree(prev);
9827 }
9828}
9829
9830static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009831xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9832{
9833 /*
9834 * After the construction context has been freed, there will be
9835 * no schema graph available any more. Only the schema buckets
9836 * will stay alive, which are put into the "schemasImports" and
9837 * "includes" slots of the xmlSchema.
9838 */
9839 if (con->buckets != NULL)
9840 xmlSchemaItemListFree(con->buckets);
9841 if (con->pending != NULL)
9842 xmlSchemaItemListFree(con->pending);
9843 if (con->substGroups != NULL)
9844 xmlHashFree(con->substGroups,
9845 (xmlHashDeallocator) xmlSchemaSubstGroupFree);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009846 if (con->redefs != NULL)
9847 xmlSchemaRedefListFree(con->redefs);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009848 if (con->dict != NULL)
9849 xmlDictFree(con->dict);
9850 xmlFree(con);
9851}
9852
9853static xmlSchemaConstructionCtxtPtr
9854xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9855{
9856 xmlSchemaConstructionCtxtPtr ret;
9857
9858 ret = (xmlSchemaConstructionCtxtPtr)
9859 xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9860 if (ret == NULL) {
9861 xmlSchemaPErrMemory(NULL,
9862 "allocating schema construction context", NULL);
9863 return (NULL);
9864 }
9865 memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9866
9867 ret->buckets = xmlSchemaItemListCreate();
9868 if (ret->buckets == NULL) {
9869 xmlSchemaPErrMemory(NULL,
9870 "allocating list of schema buckets", NULL);
9871 xmlFree(ret);
9872 return (NULL);
9873 }
9874 ret->pending = xmlSchemaItemListCreate();
9875 if (ret->pending == NULL) {
9876 xmlSchemaPErrMemory(NULL,
9877 "allocating list of pending global components", NULL);
9878 xmlSchemaConstructionCtxtFree(ret);
9879 return (NULL);
9880 }
9881 ret->dict = dict;
9882 xmlDictReference(dict);
9883 return(ret);
9884}
9885
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009886static xmlSchemaParserCtxtPtr
9887xmlSchemaParserCtxtCreate(void)
9888{
9889 xmlSchemaParserCtxtPtr ret;
9890
9891 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9892 if (ret == NULL) {
9893 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9894 NULL);
9895 return (NULL);
9896 }
9897 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9898 ret->type = XML_SCHEMA_CTXT_PARSER;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009899 ret->attrProhibs = xmlSchemaItemListCreate();
9900 if (ret->attrProhibs == NULL) {
9901 xmlFree(ret);
9902 return(NULL);
9903 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009904 return(ret);
9905}
9906
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009907/**
9908 * xmlSchemaNewParserCtxtUseDict:
9909 * @URL: the location of the schema
9910 * @dict: the dictionary to be used
9911 *
9912 * Create an XML Schemas parse context for that file/resource expected
9913 * to contain an XML Schemas file.
9914 *
9915 * Returns the parser context or NULL in case of error
9916 */
9917static xmlSchemaParserCtxtPtr
9918xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9919{
9920 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009921
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009922 ret = xmlSchemaParserCtxtCreate();
9923 if (ret == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009924 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009925 ret->dict = dict;
9926 xmlDictReference(dict);
9927 if (URL != NULL)
9928 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009929 return (ret);
9930}
9931
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009932static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009933xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
9934{
9935 if (vctxt->pctxt == NULL) {
9936 if (vctxt->schema != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009937 vctxt->pctxt =
9938 xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009939 else
9940 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
9941 if (vctxt->pctxt == NULL) {
9942 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
9943 "failed to create a temp. parser context");
9944 return (-1);
9945 }
9946 /* TODO: Pass user data. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009947 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00009948 vctxt->warning, vctxt->errCtxt);
9949 xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
9950 vctxt->errCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009951 }
9952 return (0);
9953}
9954
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009955/**
9956 * xmlSchemaGetSchemaBucket:
9957 * @pctxt: the schema parser context
9958 * @schemaLocation: the URI of the schema document
9959 *
9960 * Returns a schema bucket if it was already parsed.
9961 *
9962 * Returns a schema bucket if it was already parsed from
9963 * @schemaLocation, NULL otherwise.
9964 */
9965static xmlSchemaBucketPtr
9966xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
9967 const xmlChar *schemaLocation)
9968{
9969 xmlSchemaBucketPtr cur;
9970 xmlSchemaItemListPtr list;
9971
9972 list = pctxt->constructor->buckets;
9973 if (list->nbItems == 0)
9974 return(NULL);
9975 else {
9976 int i;
9977 for (i = 0; i < list->nbItems; i++) {
9978 cur = (xmlSchemaBucketPtr) list->items[i];
9979 /* Pointer comparison! */
9980 if (cur->schemaLocation == schemaLocation)
9981 return(cur);
9982 }
9983 }
9984 return(NULL);
9985}
9986
9987static xmlSchemaBucketPtr
9988xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
9989 const xmlChar *schemaLocation,
9990 const xmlChar *targetNamespace)
9991{
9992 xmlSchemaBucketPtr cur;
9993 xmlSchemaItemListPtr list;
9994
9995 list = pctxt->constructor->buckets;
9996 if (list->nbItems == 0)
9997 return(NULL);
9998 else {
9999 int i;
10000 for (i = 0; i < list->nbItems; i++) {
10001 cur = (xmlSchemaBucketPtr) list->items[i];
10002 /* Pointer comparison! */
10003 if ((cur->origTargetNamespace == NULL) &&
10004 (cur->schemaLocation == schemaLocation) &&
10005 (cur->targetNamespace == targetNamespace))
10006 return(cur);
10007 }
10008 }
10009 return(NULL);
10010}
10011
10012
10013#define IS_BAD_SCHEMA_DOC(b) \
10014 (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10015
10016static xmlSchemaBucketPtr
10017xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10018 const xmlChar *targetNamespace,
10019 int imported)
10020{
10021 xmlSchemaBucketPtr cur;
10022 xmlSchemaItemListPtr list;
10023
10024 list = pctxt->constructor->buckets;
10025 if (list->nbItems == 0)
10026 return(NULL);
10027 else {
10028 int i;
10029 for (i = 0; i < list->nbItems; i++) {
10030 cur = (xmlSchemaBucketPtr) list->items[i];
10031 if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10032 (cur->origTargetNamespace == targetNamespace) &&
10033 ((imported && cur->imported) ||
10034 ((!imported) && (!cur->imported))))
10035 return(cur);
10036 }
10037 }
10038 return(NULL);
10039}
10040
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010041static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010042xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10043 xmlSchemaPtr schema,
10044 xmlSchemaBucketPtr bucket)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010045{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010046 int oldFlags;
10047 xmlDocPtr oldDoc;
10048 xmlNodePtr node;
10049 int ret, oldErrs;
10050 xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10051
10052 /*
10053 * Save old values; reset the *main* schema.
10054 * URGENT TODO: This is not good; move the per-document information
10055 * to the parser.
10056 */
10057 oldFlags = schema->flags;
10058 oldDoc = schema->doc;
10059 if (schema->flags != 0)
10060 xmlSchemaClearSchemaDefaults(schema);
10061 schema->doc = bucket->doc;
10062 /* !! REMOVED: schema->targetNamespace = bucket->targetNamespace; */
10063 pctxt->schema = schema;
10064 /*
10065 * Keep the current target namespace on the parser *not* on the
10066 * main schema.
10067 */
10068 pctxt->targetNamespace = bucket->targetNamespace;
10069 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010070
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010071 if ((bucket->targetNamespace != NULL) &&
10072 xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010073 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010074 * We are parsing the schema for schemas!
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010075 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010076 pctxt->isS4S = 1;
10077 }
10078 /* Mark it as parsed, even if parsing fails. */
10079 bucket->parsed++;
10080 /* Compile the schema doc. */
10081 node = xmlDocGetRootElement(bucket->doc);
10082 ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10083 if (ret != 0)
10084 goto exit;
10085 /* An empty schema; just get out. */
10086 if (node->children == NULL)
10087 goto exit;
10088 oldErrs = pctxt->nberrors;
10089 ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10090 if (ret != 0)
10091 goto exit;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010092 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010093 * TODO: Not nice, but I'm not 100% sure we will get always an error
10094 * as a result of the obove functions; so better rely on pctxt->err
10095 * as well.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010096 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010097 if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10098 ret = pctxt->err;
10099 goto exit;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010100 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010101
10102exit:
10103 WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10104 /* Restore schema values. */
10105 schema->doc = oldDoc;
10106 schema->flags = oldFlags;
10107 return(ret);
10108}
10109
10110static int
10111xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10112 xmlSchemaPtr schema,
10113 xmlSchemaBucketPtr bucket)
10114{
10115 xmlSchemaParserCtxtPtr newpctxt;
10116 int res = 0;
10117
10118 if (bucket == NULL)
10119 return(0);
10120 if (bucket->parsed) {
10121 PERROR_INT("xmlSchemaParseNewDoc",
10122 "reparsing a schema doc");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010123 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010124 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010125 if (bucket->doc == NULL) {
10126 PERROR_INT("xmlSchemaParseNewDoc",
10127 "parsing a schema doc, but there's no doc");
10128 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000010129 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010130 if (pctxt->constructor == NULL) {
10131 PERROR_INT("xmlSchemaParseNewDoc",
10132 "no constructor");
10133 return(-1);
10134 }
10135 /* Create and init the temporary parser context. */
10136 newpctxt = xmlSchemaNewParserCtxtUseDict(
10137 (const char *) bucket->schemaLocation, pctxt->dict);
10138 if (newpctxt == NULL)
10139 return(-1);
10140 newpctxt->constructor = pctxt->constructor;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010141 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010142 * TODO: Can we avoid that the parser knows about the main schema?
10143 * It would be better if he knows about the current schema bucket
10144 * only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010145 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010146 newpctxt->schema = schema;
10147 xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000010148 pctxt->errCtxt);
10149 xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10150 pctxt->errCtxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010151 newpctxt->counter = pctxt->counter;
10152
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010153
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010154 res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10155
10156 /* Channel back errors and cleanup the temporary parser context. */
10157 if (res != 0)
10158 pctxt->err = res;
10159 pctxt->nberrors += newpctxt->nberrors;
10160 pctxt->counter = newpctxt->counter;
10161 newpctxt->constructor = NULL;
10162 /* Free the parser context. */
10163 xmlSchemaFreeParserCtxt(newpctxt);
10164 return(res);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010165}
William M. Brack2f2a6632004-08-20 23:09:47 +000010166
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010167static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010168xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10169 xmlSchemaSchemaRelationPtr rel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010170{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010171 xmlSchemaSchemaRelationPtr cur = bucket->relations;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010172
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010173 if (cur == NULL) {
10174 bucket->relations = rel;
10175 return;
10176 }
10177 while (cur->next != NULL)
10178 cur = cur->next;
10179 cur->next = rel;
10180}
10181
10182
10183static const xmlChar *
10184xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10185 xmlNodePtr ctxtNode)
10186{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010187 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010188 * Build an absolue location URI.
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010189 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010190 if (location != NULL) {
10191 if (ctxtNode == NULL)
10192 return(location);
10193 else {
10194 xmlChar *base, *URI;
10195 const xmlChar *ret = NULL;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010196
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010197 base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10198 if (base == NULL) {
10199 URI = xmlBuildURI(location, ctxtNode->doc->URL);
10200 } else {
10201 URI = xmlBuildURI(location, base);
10202 xmlFree(base);
10203 }
10204 if (URI != NULL) {
10205 ret = xmlDictLookup(dict, URI, -1);
10206 xmlFree(URI);
10207 return(ret);
10208 }
10209 }
10210 }
10211 return(NULL);
10212}
10213
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010214
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010215
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010216/**
10217 * xmlSchemaAddSchemaDoc:
10218 * @pctxt: a schema validation context
10219 * @schema: the schema being built
10220 * @node: a subtree containing XML Schema informations
10221 *
10222 * Parse an included (and to-be-redefined) XML schema document.
10223 *
10224 * Returns 0 on success, a positive error code on errors and
10225 * -1 in case of an internal or API error.
10226 */
10227
10228static int
10229xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10230 int type, /* import or include or redefine */
10231 const xmlChar *schemaLocation,
10232 xmlDocPtr schemaDoc,
10233 const char *schemaBuffer,
10234 int schemaBufferLen,
10235 xmlNodePtr invokingNode,
10236 const xmlChar *sourceTargetNamespace,
10237 const xmlChar *importNamespace,
10238 xmlSchemaBucketPtr *bucket)
10239{
10240 const xmlChar *targetNamespace = NULL;
10241 xmlSchemaSchemaRelationPtr relation = NULL;
10242 xmlDocPtr doc = NULL;
10243 int res = 0, err = 0, located = 0, preserveDoc = 0;
10244 xmlSchemaBucketPtr bkt = NULL;
10245
10246 if (bucket != NULL)
10247 *bucket = NULL;
10248
10249 switch (type) {
10250 case XML_SCHEMA_SCHEMA_IMPORT:
10251 case XML_SCHEMA_SCHEMA_MAIN:
10252 err = XML_SCHEMAP_SRC_IMPORT;
10253 break;
10254 case XML_SCHEMA_SCHEMA_INCLUDE:
10255 err = XML_SCHEMAP_SRC_INCLUDE;
10256 break;
10257 case XML_SCHEMA_SCHEMA_REDEFINE:
10258 err = XML_SCHEMAP_SRC_REDEFINE;
10259 break;
10260 }
10261
10262
10263 /* Special handling for the main schema:
10264 * skip the location and relation logic and just parse the doc.
10265 * We need just a bucket to be returned in this case.
10266 */
10267 if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10268 goto doc_load;
10269
10270 /* Note that we expect the location to be an absulute URI. */
10271 if (schemaLocation != NULL) {
10272 bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10273 if ((bkt != NULL) &&
10274 (pctxt->constructor->bucket == bkt)) {
10275 /* Report self-imports/inclusions/redefinitions. */
10276
10277 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10278 invokingNode, NULL,
10279 "The schema must not import/include/redefine itself",
10280 NULL, NULL);
10281 goto exit;
10282 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010283 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010284 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010285 * Create a relation for the graph of schemas.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010286 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010287 relation = xmlSchemaSchemaRelationCreate();
10288 if (relation == NULL)
10289 return(-1);
10290 xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10291 relation);
10292 relation->type = type;
10293
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010294 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010295 * Save the namespace import information.
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010296 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010297 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010298 relation->importNamespace = importNamespace;
10299 if (schemaLocation == NULL) {
10300 /*
10301 * No location; this is just an import of the namespace.
10302 * Note that we don't assign a bucket to the relation
10303 * in this case.
10304 */
10305 goto exit;
10306 }
10307 targetNamespace = importNamespace;
10308 }
10309
10310 /* Did we already fetch the doc? */
10311 if (bkt != NULL) {
10312 /* TODO: The following nasty cases will produce an error. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010313 if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010314 /* We included/redefined and then try to import a schema. */
10315 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10316 invokingNode, NULL,
10317 "The schema document '%s' cannot be imported, since "
10318 "it was already included or redefined",
10319 schemaLocation, NULL);
10320 goto exit;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010321 } else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010322 /* We imported and then try to include/redefine a schema. */
10323 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10324 invokingNode, NULL,
10325 "The schema document '%s' cannot be included or "
10326 "redefined, since it was already imported",
10327 schemaLocation, NULL);
10328 goto exit;
10329 }
10330 }
10331
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010332 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010333 /*
10334 * Given that the schemaLocation [attribute] is only a hint, it is open
10335 * to applications to ignore all but the first <import> for a given
10336 * namespace, regardless of the ·actual value· of schemaLocation, but
10337 * such a strategy risks missing useful information when new
10338 * schemaLocations are offered.
10339 *
10340 * We will use the first <import> that comes with a location.
10341 * Further <import>s *with* a location, will result in an error.
10342 * TODO: Better would be to just report a warning here, but
10343 * we'll try it this way until someone complains.
10344 *
10345 * Schema Document Location Strategy:
10346 * 3 Based on the namespace name, identify an existing schema document,
10347 * either as a resource which is an XML document or a <schema> element
10348 * information item, in some local schema repository;
10349 * 5 Attempt to resolve the namespace name to locate such a resource.
10350 *
10351 * NOTE: (3) and (5) are not supported.
10352 */
10353 if (bkt != NULL) {
10354 relation->bucket = bkt;
10355 goto exit;
10356 }
10357 bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10358 importNamespace, 1);
10359
10360 if (bkt != NULL) {
10361 relation->bucket = bkt;
10362 if (bkt->schemaLocation == NULL) {
10363 /* First given location of the schema; load the doc. */
10364 bkt->schemaLocation = schemaLocation;
10365 } else {
10366 if (!xmlStrEqual(schemaLocation,
10367 bkt->schemaLocation)) {
10368 /*
10369 * Additional location given; just skip it.
10370 * URGENT TODO: We should report a warning here.
10371 * res = XML_SCHEMAP_SRC_IMPORT;
10372 */
10373 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10374 XML_SCHEMAP_WARN_SKIP_SCHEMA,
10375 invokingNode, NULL,
10376 "Skipping import of schema located at '%s' for the "
10377 "namespace '%s', since this namespace was already "
10378 "imported with the schema located at '%s'",
10379 schemaLocation, importNamespace, bkt->schemaLocation);
10380 }
10381 goto exit;
10382 }
10383 }
10384 /*
10385 * No bucket + first location: load the doc and create a
10386 * bucket.
10387 */
10388 } else {
10389 /* <include> and <redefine> */
10390 if (bkt != NULL) {
10391
10392 if ((bkt->origTargetNamespace == NULL) &&
10393 (bkt->targetNamespace != sourceTargetNamespace)) {
10394 xmlSchemaBucketPtr chamel;
10395
10396 /*
10397 * Chameleon include/redefine: skip loading only if it was
10398 * aleady build for the targetNamespace of the including
10399 * schema.
10400 */
10401 /*
10402 * URGENT TODO: If the schema is a chameleon-include then copy
10403 * the components into the including schema and modify the
10404 * targetNamespace of those components, do nothing otherwise.
10405 * NOTE: This is currently worked-around by compiling the
10406 * chameleon for every destinct including targetNamespace; thus
10407 * not performant at the moment.
10408 * TODO: Check when the namespace in wildcards for chameleons
10409 * needs to be converted: before we built wildcard intersections
10410 * or after.
10411 * Answer: after!
10412 */
10413 chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10414 schemaLocation, sourceTargetNamespace);
10415 if (chamel != NULL) {
10416 /* A fitting chameleon was already parsed; NOP. */
10417 relation->bucket = chamel;
10418 goto exit;
10419 }
10420 /*
10421 * We need to parse the chameleon again for a different
10422 * targetNamespace.
10423 * CHAMELEON TODO: Optimize this by only parsing the
10424 * chameleon once, and then copying the components to
10425 * the new targetNamespace.
10426 */
10427 bkt = NULL;
10428 } else {
10429 relation->bucket = bkt;
10430 goto exit;
10431 }
10432 }
10433 }
10434 if ((bkt != NULL) && (bkt->doc != NULL)) {
10435 PERROR_INT("xmlSchemaAddSchemaDoc",
10436 "trying to load a schema doc, but a doc is already "
10437 "assigned to the schema bucket");
10438 goto exit_failure;
10439 }
10440
10441doc_load:
10442 /*
10443 * Load the document.
10444 */
10445 if (schemaDoc != NULL) {
10446 doc = schemaDoc;
10447 /* Don' free this one, since it was provided by the caller. */
10448 preserveDoc = 1;
10449 /* TODO: Does the context or the doc hold the location? */
10450 if (schemaDoc->URL != NULL)
10451 schemaLocation = xmlDictLookup(pctxt->dict,
10452 schemaDoc->URL, -1);
10453
10454 } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10455 xmlParserCtxtPtr parserCtxt;
10456
10457 parserCtxt = xmlNewParserCtxt();
10458 if (parserCtxt == NULL) {
10459 xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10460 "allocating a parser context", NULL);
10461 goto exit_failure;
10462 }
10463 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10464 /*
10465 * TODO: Do we have to burden the schema parser dict with all
10466 * the content of the schema doc?
10467 */
10468 xmlDictFree(parserCtxt->dict);
10469 parserCtxt->dict = pctxt->dict;
10470 xmlDictReference(parserCtxt->dict);
10471 }
10472 if (schemaLocation != NULL) {
10473 /* Parse from file. */
10474 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10475 NULL, SCHEMAS_PARSE_OPTIONS);
10476 } else if (schemaBuffer != NULL) {
10477 /* Parse from memory buffer. */
10478 doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10479 NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10480 schemaLocation = xmlStrdup(BAD_CAST "in_memory_buffer");
10481 if (doc != NULL)
10482 doc->URL = schemaLocation;
10483 }
10484 /*
10485 * For <import>:
10486 * 2.1 The referent is (a fragment of) a resource which is an
10487 * XML document (see clause 1.1), which in turn corresponds to
10488 * a <schema> element information item in a well-formed information
10489 * set, which in turn corresponds to a valid schema.
10490 * TODO: (2.1) fragments of XML documents are not supported.
10491 *
10492 * 2.2 The referent is a <schema> element information item in
10493 * a well-formed information set, which in turn corresponds
10494 * to a valid schema.
10495 * TODO: (2.2) is not supported.
10496 */
10497 if (doc == NULL) {
10498 xmlErrorPtr lerr;
10499 lerr = xmlGetLastError();
10500 /*
10501 * Check if this a parser error, or if the document could
10502 * just not be located.
10503 * TODO: Try to find specific error codes to react only on
10504 * localisation failures.
10505 */
10506 if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10507 /*
10508 * We assume a parser error here.
10509 */
10510 located = 1;
10511 /* TODO: Error code ?? */
10512 res = XML_SCHEMAP_SRC_IMPORT_2_1;
10513 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10514 invokingNode, NULL,
10515 "Failed to parse the XML resource '%s'",
10516 schemaLocation, NULL);
10517 }
10518 }
10519 xmlFreeParserCtxt(parserCtxt);
10520 if ((doc == NULL) && located)
10521 goto exit_error;
10522 } else {
10523 xmlSchemaPErr(pctxt, NULL,
10524 XML_SCHEMAP_NOTHING_TO_PARSE,
10525 "No information for parsing was provided with the "
10526 "given schema parser context.\n",
10527 NULL, NULL);
10528 goto exit_failure;
10529 }
10530 /*
10531 * Preprocess the document.
10532 */
10533 if (doc != NULL) {
10534 xmlNodePtr docElem = NULL;
10535
10536 located = 1;
10537 docElem = xmlDocGetRootElement(doc);
10538 if (docElem == NULL) {
10539 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10540 invokingNode, NULL,
10541 "The document '%s' has no document element",
10542 schemaLocation, NULL);
10543 xmlFreeDoc(doc);
10544 doc = NULL;
10545 goto exit_error;
10546 }
10547 /*
10548 * Remove all the blank text nodes.
10549 */
10550 xmlSchemaCleanupDoc(pctxt, docElem);
10551 /*
10552 * Check the schema's top level element.
10553 */
10554 if (!IS_SCHEMA(docElem, "schema")) {
10555 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10556 invokingNode, NULL,
10557 "The XML document '%s' is not a schema document",
10558 schemaLocation, NULL);
10559 xmlFreeDoc(doc);
10560 doc = NULL;
10561 goto exit_error;
10562 }
10563 /*
10564 * Note that we don't apply a type check for the
10565 * targetNamespace value here.
10566 */
10567 targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10568 "targetNamespace");
10569 }
10570
10571/* after_doc_loading: */
10572 if ((bkt == NULL) && located) {
10573 /* Only create a bucket if the schema was located. */
10574 bkt = xmlSchemaBucketCreate(pctxt, type,
10575 targetNamespace);
10576 if (bkt == NULL)
10577 goto exit_failure;
10578 }
10579 if (bkt != NULL) {
10580 bkt->schemaLocation = schemaLocation;
10581 bkt->located = located;
10582 if (doc != NULL) {
10583 bkt->doc = doc;
10584 bkt->targetNamespace = targetNamespace;
10585 bkt->origTargetNamespace = targetNamespace;
10586 if (preserveDoc)
10587 bkt->preserveDoc = 1;
10588 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010589 if (WXS_IS_BUCKET_IMPMAIN(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010590 bkt->imported++;
10591 /*
10592 * Add it to the graph of schemas.
10593 */
10594 if (relation != NULL)
10595 relation->bucket = bkt;
10596 }
10597
10598exit:
10599 /*
10600 * Return the bucket explicitely; this is needed for the
10601 * main schema.
10602 */
10603 if (bucket != NULL)
10604 *bucket = bkt;
10605 return (0);
10606
10607exit_error:
10608 if ((doc != NULL) && (! preserveDoc)) {
10609 xmlFreeDoc(doc);
10610 if (bkt != NULL)
10611 bkt->doc = NULL;
10612 }
10613 return(pctxt->err);
10614
10615exit_failure:
10616 if ((doc != NULL) && (! preserveDoc)) {
10617 xmlFreeDoc(doc);
10618 if (bkt != NULL)
10619 bkt->doc = NULL;
10620 }
10621 return (-1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010622}
10623
William M. Brack2f2a6632004-08-20 23:09:47 +000010624/**
10625 * xmlSchemaParseImport:
10626 * @ctxt: a schema validation context
10627 * @schema: the schema being built
10628 * @node: a subtree containing XML Schema informations
10629 *
10630 * parse a XML schema Import definition
10631 * *WARNING* this interface is highly subject to change
10632 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010633 * Returns 0 in case of success, a positive error code if
10634 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +000010635 */
10636static int
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010637xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +000010638 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010639{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010640 xmlNodePtr child;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010641 const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10642 const xmlChar *thisTargetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +000010643 xmlAttrPtr attr;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010644 int ret = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010645 xmlSchemaBucketPtr bucket = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000010646
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010647 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
William M. Brack2f2a6632004-08-20 23:09:47 +000010648 return (-1);
10649
10650 /*
10651 * Check for illegal attributes.
10652 */
10653 attr = node->properties;
10654 while (attr != NULL) {
10655 if (attr->ns == NULL) {
10656 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10657 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10658 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010659 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010660 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010661 }
10662 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010663 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010664 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010665 }
10666 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010667 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010668 /*
10669 * Extract and validate attributes.
10670 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010671 if (xmlSchemaPValAttr(pctxt, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010672 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010673 &namespaceName) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010674 xmlSchemaPSimpleTypeErr(pctxt,
10675 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010676 NULL, node,
10677 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010678 NULL, namespaceName, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010679 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010680 }
10681
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010682 if (xmlSchemaPValAttr(pctxt, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010683 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +000010684 &schemaLocation) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010685 xmlSchemaPSimpleTypeErr(pctxt,
10686 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010687 NULL, node,
10688 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010689 NULL, namespaceName, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010690 return (pctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010691 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010692 /*
10693 * And now for the children...
10694 */
10695 child = node->children;
10696 if (IS_SCHEMA(child, "annotation")) {
10697 /*
10698 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010699 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +000010700 */
10701 child = child->next;
10702 }
10703 if (child != NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010704 xmlSchemaPContentErr(pctxt,
10705 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010706 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010707 "(annotation?)");
10708 }
10709 /*
10710 * Apply additional constraints.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010711 *
10712 * Note that it is important to use the original @targetNamespace
10713 * (or none at all), to rule out imports of schemas _with_ a
10714 * @targetNamespace if the importing schema is a chameleon schema
10715 * (with no @targetNamespace).
William M. Brack2f2a6632004-08-20 23:09:47 +000010716 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010717 thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010718 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000010719 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010720 * 1.1 If the namespace [attribute] is present, then its ·actual value·
10721 * must not match the ·actual value· of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +000010722 * targetNamespace [attribute].
10723 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010724 if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010725 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000010726 XML_SCHEMAP_SRC_IMPORT_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010727 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +000010728 "The value of the attribute 'namespace' must not match "
10729 "the target namespace '%s' of the importing schema",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010730 thisTargetNamespace);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010731 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010732 }
10733 } else {
10734 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010735 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +000010736 * <schema> must have a targetNamespace [attribute].
10737 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010738 if (thisTargetNamespace == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010739 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000010740 XML_SCHEMAP_SRC_IMPORT_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010741 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +000010742 "The attribute 'namespace' must be existent if "
10743 "the importing schema has no target namespace",
10744 NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010745 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010746 }
10747 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010748 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000010749 * Locate and acquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +000010750 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010751 if (schemaLocation != NULL)
10752 schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10753 schemaLocation, node);
10754 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010755 schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010756 namespaceName, &bucket);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010757
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010758 if (ret != 0)
10759 return(ret);
10760
10761 /*
10762 * For <import>: "It is *not* an error for the application
10763 * schema reference strategy to fail."
10764 * So just don't parse if no schema document was found.
10765 * Note that we will get no bucket if the schema could not be
10766 * located or if there was no schemaLocation.
10767 */
10768 if ((bucket == NULL) && (schemaLocation != NULL)) {
10769 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10770 XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10771 node, NULL,
10772 "Failed to locate a schema at location '%s'. "
10773 "Skipping the import", schemaLocation, NULL, NULL);
10774 }
10775
10776 if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10777 ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10778 }
10779
10780 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000010781}
10782
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010783static int
10784xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10785 xmlSchemaPtr schema,
10786 xmlNodePtr node,
10787 xmlChar **schemaLocation,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010788 int type)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010789{
10790 xmlAttrPtr attr;
10791
10792 if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10793 (schemaLocation == NULL))
10794 return (-1);
10795
10796 *schemaLocation = NULL;
10797 /*
10798 * Check for illegal attributes.
10799 * Applies for both <include> and <redefine>.
10800 */
10801 attr = node->properties;
10802 while (attr != NULL) {
10803 if (attr->ns == NULL) {
10804 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10805 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10806 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010807 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010808 }
10809 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10810 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010811 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010812 }
10813 attr = attr->next;
10814 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010815 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010816 /*
10817 * Preliminary step, extract the URI-Reference and make an URI
10818 * from the base.
10819 */
10820 /*
10821 * Attribute "schemaLocation" is mandatory.
10822 */
10823 attr = xmlSchemaGetPropNode(node, "schemaLocation");
10824 if (attr != NULL) {
10825 xmlChar *base = NULL;
10826 xmlChar *uri = NULL;
10827
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010828 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010829 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10830 (const xmlChar **) schemaLocation) != 0)
10831 goto exit_error;
10832 base = xmlNodeGetBase(node->doc, node);
10833 if (base == NULL) {
10834 uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10835 } else {
10836 uri = xmlBuildURI(*schemaLocation, base);
10837 xmlFree(base);
10838 }
10839 if (uri == NULL) {
10840 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10841 "could not build an URI from the schemaLocation")
10842 goto exit_failure;
10843 }
10844 (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10845 xmlFree(uri);
10846 } else {
10847 xmlSchemaPMissingAttrErr(pctxt,
10848 XML_SCHEMAP_S4S_ATTR_MISSING,
10849 NULL, node, "schemaLocation", NULL);
10850 goto exit_error;
10851 }
10852 /*
10853 * Report self-inclusion and self-redefinition.
10854 */
10855 if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010856 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010857 xmlSchemaPCustomErr(pctxt,
10858 XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010859 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010860 "The schema document '%s' cannot redefine itself.",
10861 *schemaLocation);
10862 } else {
10863 xmlSchemaPCustomErr(pctxt,
10864 XML_SCHEMAP_SRC_INCLUDE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010865 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010866 "The schema document '%s' cannot include itself.",
10867 *schemaLocation);
10868 }
10869 goto exit_error;
10870 }
10871
10872 return(0);
10873exit_error:
10874 return(pctxt->err);
10875exit_failure:
10876 return(-1);
10877}
10878
10879static int
10880xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10881 xmlSchemaPtr schema,
10882 xmlNodePtr node,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010883 int type)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010884{
10885 xmlNodePtr child = NULL;
10886 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000010887 int res = 0; /* hasRedefinitions = 0 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010888 int isChameleon = 0, wasChameleon = 0;
10889 xmlSchemaBucketPtr bucket = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010890
10891 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10892 return (-1);
10893
10894 /*
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010895 * Parse attributes. Note that the returned schemaLocation will
10896 * be already converted to an absolute URI.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010897 */
10898 res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010899 node, (xmlChar **) (&schemaLocation), type);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010900 if (res != 0)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010901 return(res);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010902 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010903 * Load and add the schema document.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010904 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010905 res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10906 NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010907 if (res != 0)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010908 return(res);
10909 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010910 * If we get no schema bucket back, then this means that the schema
10911 * document could not be located or was broken XML or was not
10912 * a schema document.
10913 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010914 if ((bucket == NULL) || (bucket->doc == NULL)) {
10915 if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10916 /*
10917 * WARNING for <include>:
10918 * We will raise an error if the schema cannot be located
10919 * for inclusions, since the that was the feedback from the
10920 * schema people. I.e. the following spec piece will *not* be
10921 * satisfied:
10922 * SPEC src-include: "It is not an error for the ·actual value· of the
10923 * schemaLocation [attribute] to fail to resolve it all, in which
10924 * case no corresponding inclusion is performed.
10925 * So do we need a warning report here?"
10926 */
10927 res = XML_SCHEMAP_SRC_INCLUDE;
10928 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10929 node, NULL,
10930 "Failed to load the document '%s' for inclusion",
10931 schemaLocation, NULL);
10932 } else {
10933 /*
10934 * NOTE: This was changed to raise an error even if no redefinitions
10935 * are specified.
10936 *
10937 * SPEC src-redefine (1)
10938 * "If there are any element information items among the [children]
10939 * other than <annotation> then the ·actual value· of the
10940 * schemaLocation [attribute] must successfully resolve."
10941 * TODO: Ask the WG if a the location has always to resolve
10942 * here as well!
10943 */
10944 res = XML_SCHEMAP_SRC_REDEFINE;
10945 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10946 node, NULL,
10947 "Failed to load the document '%s' for redefinition",
10948 schemaLocation, NULL);
10949 }
10950 } else {
10951 /*
10952 * Check targetNamespace sanity before parsing the new schema.
10953 * TODO: Note that we won't check further content if the
10954 * targetNamespace was bad.
10955 */
10956 if (bucket->origTargetNamespace != NULL) {
10957 /*
10958 * SPEC src-include (2.1)
10959 * "SII has a targetNamespace [attribute], and its ·actual
10960 * value· is identical to the ·actual value· of the targetNamespace
10961 * [attribute] of SIIÂ’ (which must have such an [attribute])."
10962 */
10963 if (pctxt->targetNamespace == NULL) {
10964 xmlSchemaCustomErr(ACTXT_CAST pctxt,
10965 XML_SCHEMAP_SRC_INCLUDE,
10966 node, NULL,
10967 "The target namespace of the included/redefined schema "
10968 "'%s' has to be absent, since the including/redefining "
10969 "schema has no target namespace",
10970 schemaLocation, NULL);
10971 goto exit_error;
10972 } else if (!xmlStrEqual(bucket->origTargetNamespace,
10973 pctxt->targetNamespace)) {
10974 /* TODO: Change error function. */
10975 xmlSchemaPCustomErrExt(pctxt,
10976 XML_SCHEMAP_SRC_INCLUDE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010977 NULL, node,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010978 "The target namespace '%s' of the included/redefined "
10979 "schema '%s' differs from '%s' of the "
10980 "including/redefining schema",
10981 bucket->origTargetNamespace, schemaLocation,
10982 pctxt->targetNamespace);
10983 goto exit_error;
10984 }
10985 } else if (pctxt->targetNamespace != NULL) {
10986 /*
10987 * Chameleons: the original target namespace will
10988 * differ from the resulting namespace.
10989 */
10990 isChameleon = 1;
10991 if (bucket->parsed &&
10992 (bucket->targetNamespace != pctxt->targetNamespace)) {
10993 /*
10994 * This is a sanity check, I dunno yet if this can happen.
10995 */
10996 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10997 "trying to use an already parsed schema for a "
10998 "different targetNamespace");
10999 return(-1);
11000 }
11001 bucket->targetNamespace = pctxt->targetNamespace;
11002 }
11003 }
11004 /*
11005 * Parse the schema.
11006 */
11007 if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11008 if (isChameleon) {
11009 /* TODO: Get rid of this flag on the schema itself. */
11010 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11011 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11012 } else
11013 wasChameleon = 1;
11014 }
11015 xmlSchemaParseNewDoc(pctxt, schema, bucket);
11016 /* Restore chameleon flag. */
11017 if (isChameleon && (!wasChameleon))
11018 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11019 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011020 /*
11021 * And now for the children...
11022 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011023 child = node->children;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011024 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011025 /*
11026 * Parse (simpleType | complexType | group | attributeGroup))*
11027 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011028 pctxt->redefined = bucket;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011029 /*
11030 * How to proceed if the redefined schema was not located?
11031 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011032 pctxt->isRedefine = 1;
11033 while (IS_SCHEMA(child, "annotation") ||
11034 IS_SCHEMA(child, "simpleType") ||
11035 IS_SCHEMA(child, "complexType") ||
11036 IS_SCHEMA(child, "group") ||
11037 IS_SCHEMA(child, "attributeGroup")) {
11038 if (IS_SCHEMA(child, "annotation")) {
11039 /*
11040 * TODO: discard or not?
11041 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011042 } else if (IS_SCHEMA(child, "simpleType")) {
11043 xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11044 } else if (IS_SCHEMA(child, "complexType")) {
11045 xmlSchemaParseComplexType(pctxt, schema, child, 1);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011046 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011047 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011048 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011049 xmlSchemaParseModelGroupDefinition(pctxt,
11050 schema, child);
11051 } else if (IS_SCHEMA(child, "attributeGroup")) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011052 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011053 xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11054 child);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011055 }
11056 child = child->next;
11057 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011058 pctxt->redefined = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011059 pctxt->isRedefine = 0;
11060 } else {
11061 if (IS_SCHEMA(child, "annotation")) {
11062 /*
11063 * TODO: discard or not?
11064 */
11065 child = child->next;
11066 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011067 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011068 if (child != NULL) {
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011069 res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011070 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11071 xmlSchemaPContentErr(pctxt, res,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011072 NULL, node, child, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011073 "(annotation | (simpleType | complexType | group | attributeGroup))*");
11074 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011075 xmlSchemaPContentErr(pctxt, res,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011076 NULL, node, child, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011077 "(annotation?)");
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011078 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011079 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011080 return(res);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011081
11082exit_error:
11083 return(pctxt->err);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011084}
11085
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011086static int
11087xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11088 xmlNodePtr node)
11089{
11090 int res;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011091#ifndef ENABLE_REDEFINE
11092 TODO
11093 return(0);
11094#endif
11095 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11096 XML_SCHEMA_SCHEMA_REDEFINE);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011097 if (res != 0)
11098 return(res);
11099 return(0);
11100}
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011101
11102static int
11103xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11104 xmlNodePtr node)
11105{
11106 int res;
11107
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011108 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11109 XML_SCHEMA_SCHEMA_INCLUDE);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011110 if (res != 0)
11111 return(res);
11112 return(0);
11113}
11114
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011115/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011116 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011117 * @ctxt: a schema validation context
11118 * @schema: the schema being built
11119 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011120 * @type: the "compositor" type
11121 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +000011122 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011123 * parse a XML schema Sequence definition.
11124 * Applies parts of:
11125 * Schema Representation Constraint:
11126 * Redefinition Constraints and Semantics (src-redefine)
11127 * (6.1), (6.1.1), (6.1.2)
11128 *
11129 * Schema Component Constraint:
11130 * All Group Limited (cos-all-limited) (2)
11131 * TODO: Actually this should go to component-level checks,
11132 * but is done here due to performance. Move it to an other layer
11133 * is schema construction via an API is implemented.
11134 *
Daniel Veillard4255d502002-04-16 15:50:10 +000011135 * *WARNING* this interface is highly subject to change
11136 *
William M. Bracke7091952004-05-11 15:09:58 +000011137 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +000011138 * 1 in case of success.
11139 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011140static xmlSchemaTreeItemPtr
11141xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11142 xmlNodePtr node, xmlSchemaTypeType type,
11143 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +000011144{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011145 xmlSchemaModelGroupPtr item;
11146 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011147 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000011148 xmlAttrPtr attr;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011149 int min = 1, max = 1, isElemRef, hasRefs = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000011150
11151 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011152 return (NULL);
11153 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011154 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +000011155 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011156 item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011157 if (item == NULL)
11158 return (NULL);
11159
11160 if (withParticle) {
11161 if (type == XML_SCHEMA_TYPE_ALL) {
11162 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011163 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011164 } else {
11165 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011166 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11167 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11168 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011169 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011170 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11171 /*
11172 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011173 */
11174 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
11175 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011176 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011177 particle->children = (xmlSchemaTreeItemPtr) item;
11178 /*
11179 * Check for illegal attributes.
11180 */
11181 attr = node->properties;
11182 while (attr != NULL) {
11183 if (attr->ns == NULL) {
11184 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11185 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11186 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011187 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011188 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011189 }
11190 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011191 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011192 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011193 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011194 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000011195 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011196 } else {
11197 /*
11198 * Check for illegal attributes.
11199 */
11200 attr = node->properties;
11201 while (attr != NULL) {
11202 if (attr->ns == NULL) {
11203 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011204 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011205 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011206 }
11207 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011208 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011209 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011210 }
11211 attr = attr->next;
11212 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011213 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011214
William M. Brack2f2a6632004-08-20 23:09:47 +000011215 /*
11216 * Extract and validate attributes.
11217 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011218 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000011219 /*
11220 * And now for the children...
11221 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011222 child = node->children;
11223 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011224 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011225 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011226 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011227 if (type == XML_SCHEMA_TYPE_ALL) {
11228 xmlSchemaParticlePtr part, last = NULL;
11229
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011230 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011231 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011232 schema, child, &isElemRef, 0);
11233 /*
11234 * SPEC cos-all-limited (2)
11235 * "The {max occurs} of all the particles in the {particles}
11236 * of the ('all') group must be 0 or 1.
11237 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011238 if (part != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011239 if (isElemRef)
11240 hasRefs++;
11241 if (part->minOccurs > 1) {
11242 xmlSchemaPCustomErr(ctxt,
11243 XML_SCHEMAP_COS_ALL_LIMITED,
11244 NULL, child,
11245 "Invalid value for minOccurs (must be 0 or 1)",
11246 NULL);
11247 /* Reset to 1. */
11248 part->minOccurs = 1;
11249 }
11250 if (part->maxOccurs > 1) {
11251 xmlSchemaPCustomErr(ctxt,
11252 XML_SCHEMAP_COS_ALL_LIMITED,
11253 NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011254 "Invalid value for maxOccurs (must be 0 or 1)",
11255 NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011256 /* Reset to 1. */
11257 part->maxOccurs = 1;
11258 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011259 if (last == NULL)
11260 item->children = (xmlSchemaTreeItemPtr) part;
11261 else
11262 last->next = (xmlSchemaTreeItemPtr) part;
11263 last = part;
11264 }
11265 child = child->next;
11266 }
11267 if (child != NULL) {
11268 xmlSchemaPContentErr(ctxt,
11269 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011270 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011271 "(annotation?, (annotation?, element*)");
11272 }
11273 } else {
11274 /* choice + sequence */
11275 xmlSchemaTreeItemPtr part = NULL, last = NULL;
11276
11277 while ((IS_SCHEMA(child, "element")) ||
11278 (IS_SCHEMA(child, "group")) ||
11279 (IS_SCHEMA(child, "any")) ||
11280 (IS_SCHEMA(child, "choice")) ||
11281 (IS_SCHEMA(child, "sequence"))) {
11282
11283 if (IS_SCHEMA(child, "element")) {
11284 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011285 xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11286 if (part && isElemRef)
11287 hasRefs++;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011288 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011289 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011290 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011291 if (part != NULL)
11292 hasRefs++;
11293 /*
11294 * Handle redefinitions.
11295 */
11296 if (ctxt->isRedefine && ctxt->redef &&
11297 (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11298 part && part->children)
11299 {
11300 if ((xmlSchemaGetQNameRefName(part->children) ==
11301 ctxt->redef->refName) &&
11302 (xmlSchemaGetQNameRefTargetNs(part->children) ==
11303 ctxt->redef->refTargetNs))
11304 {
11305 /*
11306 * SPEC src-redefine:
11307 * (6.1) "If it has a <group> among its contents at
11308 * some level the ·actual value· of whose ref
11309 * [attribute] is the same as the ·actual value· of
11310 * its own name attribute plus target namespace, then
11311 * all of the following must be true:"
11312 * (6.1.1) "It must have exactly one such group."
11313 */
11314 if (ctxt->redefCounter != 0) {
11315 xmlChar *str = NULL;
11316
11317 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11318 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11319 "The redefining model group definition "
11320 "'%s' must not contain more than one "
11321 "reference to the redefined definition",
11322 xmlSchemaFormatQName(&str,
11323 ctxt->redef->refTargetNs,
11324 ctxt->redef->refName),
11325 NULL);
11326 FREE_AND_NULL(str)
11327 part = NULL;
11328 } else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11329 ((WXS_PARTICLE(part))->maxOccurs != 1))
11330 {
11331 xmlChar *str = NULL;
11332 /*
11333 * SPEC src-redefine:
11334 * (6.1.2) "The ·actual value· of both that
11335 * group's minOccurs and maxOccurs [attribute]
11336 * must be 1 (or ·absent·).
11337 */
11338 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11339 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11340 "The redefining model group definition "
11341 "'%s' must not contain a reference to the "
11342 "redefined definition with a "
11343 "maxOccurs/minOccurs other than 1",
11344 xmlSchemaFormatQName(&str,
11345 ctxt->redef->refTargetNs,
11346 ctxt->redef->refName),
11347 NULL);
11348 FREE_AND_NULL(str)
11349 part = NULL;
11350 }
11351 ctxt->redef->reference = WXS_BASIC_CAST part;
11352 ctxt->redefCounter++;
11353 }
11354 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011355 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011356 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011357 xmlSchemaParseAny(ctxt, schema, child);
11358 } else if (IS_SCHEMA(child, "choice")) {
11359 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11360 XML_SCHEMA_TYPE_CHOICE, 1);
11361 } else if (IS_SCHEMA(child, "sequence")) {
11362 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11363 XML_SCHEMA_TYPE_SEQUENCE, 1);
11364 }
11365 if (part != NULL) {
11366 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011367 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011368 else
11369 last->next = part;
11370 last = part;
11371 }
11372 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011373 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011374 if (child != NULL) {
11375 xmlSchemaPContentErr(ctxt,
11376 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011377 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011378 "(annotation?, (element | group | choice | sequence | any)*)");
11379 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011380 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011381 if ((max == 0) && (min == 0))
11382 return (NULL);
11383 if (hasRefs) {
11384 /*
11385 * We need to resolve references.
11386 */
11387 WXS_ADD_PENDING(ctxt, item);
11388 }
11389 if (withParticle)
11390 return ((xmlSchemaTreeItemPtr) particle);
11391 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011392 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +000011393}
11394
11395/**
11396 * xmlSchemaParseRestriction:
11397 * @ctxt: a schema validation context
11398 * @schema: the schema being built
11399 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +000011400 *
11401 * parse a XML schema Restriction definition
11402 * *WARNING* this interface is highly subject to change
11403 *
11404 * Returns the type definition or NULL in case of error
11405 */
11406static xmlSchemaTypePtr
11407xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011408 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000011409{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011410 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011411 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000011412 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011413
11414 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11415 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011416 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011417 type = ctxt->ctxtType;
11418 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011419
11420 /*
William M. Brack2f2a6632004-08-20 23:09:47 +000011421 * Check for illegal attributes.
11422 */
11423 attr = node->properties;
11424 while (attr != NULL) {
11425 if (attr->ns == NULL) {
11426 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11427 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011428 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011429 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011430 }
11431 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011432 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011433 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011434 }
11435 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011436 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011437 /*
11438 * Extract and validate attributes.
11439 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011440 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000011441 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011442 * Attribute
William M. Brack2f2a6632004-08-20 23:09:47 +000011443 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011444 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011445 * Extract the base type. The "base" attribute is mandatory if inside
11446 * a complex type or if redefining.
11447 *
11448 * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011449 * among its [children]), the simple type definition which is
11450 * the {content type} of the type definition ·resolved· to by
11451 * the ·actual value· of the base [attribute]"
11452 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011453 if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011454 &(type->baseNs), &(type->base)) == 0)
11455 {
11456 if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11457 xmlSchemaPMissingAttrErr(ctxt,
11458 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011459 NULL, node, "base", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011460 } else if ((ctxt->isRedefine) &&
11461 (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11462 {
11463 if (type->base == NULL) {
11464 xmlSchemaPMissingAttrErr(ctxt,
11465 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011466 NULL, node, "base", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011467 } else if ((! xmlStrEqual(type->base, type->name)) ||
11468 (! xmlStrEqual(type->baseNs, type->targetNamespace)))
11469 {
11470 xmlChar *str1 = NULL, *str2 = NULL;
11471 /*
11472 * REDEFINE: SPEC src-redefine (5)
11473 * "Within the [children], each <simpleType> must have a
11474 * <restriction> among its [children] ... the ·actual value· of
11475 * whose base [attribute] must be the same as the ·actual value·
11476 * of its own name attribute plus target namespace;"
11477 */
11478 xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011479 NULL, node, "This is a redefinition, but the QName "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011480 "value '%s' of the 'base' attribute does not match the "
11481 "type's designation '%s'",
11482 xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11483 xmlSchemaFormatQName(&str1, type->targetNamespace,
11484 type->name), NULL);
11485 FREE_AND_NULL(str1);
11486 FREE_AND_NULL(str2);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011487 /* Avoid confusion and erase the values. */
11488 type->base = NULL;
11489 type->baseNs = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011490 }
11491 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011492 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011493 /*
11494 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011495 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011496 child = node->children;
11497 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011498 /*
11499 * Add the annotation to the simple type ancestor.
11500 */
11501 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011502 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011503 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011504 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011505 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11506 /*
11507 * Corresponds to <simpleType><restriction><simpleType>.
11508 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011509 if (IS_SCHEMA(child, "simpleType")) {
11510 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011511 /*
William M. Brack2f2a6632004-08-20 23:09:47 +000011512 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011513 * Either the base [attribute] or the simpleType [child] of the
11514 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +000011515 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011516 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000011517 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011518 NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +000011519 "The attribute 'base' and the <simpleType> child are "
11520 "mutually exclusive", NULL);
11521 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011522 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +000011523 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011524 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011525 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011526 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011527 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011528 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011529 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011530 "Either the attribute 'base' or a <simpleType> child "
11531 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000011532 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011533 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11534 /*
11535 * Corresponds to <complexType><complexContent><restriction>...
11536 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011537 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011538 * Model groups <all>, <choice> and <sequence>.
11539 */
11540 if (IS_SCHEMA(child, "all")) {
11541 type->subtypes = (xmlSchemaTypePtr)
11542 xmlSchemaParseModelGroup(ctxt, schema, child,
11543 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011544 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011545 } else if (IS_SCHEMA(child, "choice")) {
11546 type->subtypes = (xmlSchemaTypePtr)
11547 xmlSchemaParseModelGroup(ctxt,
11548 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11549 child = child->next;
11550 } else if (IS_SCHEMA(child, "sequence")) {
11551 type->subtypes = (xmlSchemaTypePtr)
11552 xmlSchemaParseModelGroup(ctxt, schema, child,
11553 XML_SCHEMA_TYPE_SEQUENCE, 1);
11554 child = child->next;
11555 /*
11556 * Model group reference <group>.
11557 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011558 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011559 type->subtypes = (xmlSchemaTypePtr)
11560 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011561 /*
11562 * Note that the reference will be resolved in
11563 * xmlSchemaResolveTypeReferences();
11564 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011565 child = child->next;
11566 }
11567 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011568 /*
11569 * Corresponds to <complexType><simpleContent><restriction>...
11570 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011571 * "1.1 the simple type definition corresponding to the <simpleType>
11572 * among the [children] of <restriction> if there is one;"
11573 */
11574 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011575 /*
11576 * We will store the to-be-restricted simple type in
11577 * type->contentTypeDef *temporarily*.
11578 */
11579 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011580 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011581 if ( type->contentTypeDef == NULL)
11582 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011583 child = child->next;
11584 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011585 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011586
11587 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011588 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011589 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011590 /*
11591 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011592 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011593 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011594
Daniel Veillard01fa6152004-06-29 17:04:39 +000011595 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011596 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011597 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011598 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011599 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11600 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +000011601 * *Single Facet Value*
11602 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011603 while ((IS_SCHEMA(child, "minInclusive")) ||
11604 (IS_SCHEMA(child, "minExclusive")) ||
11605 (IS_SCHEMA(child, "maxInclusive")) ||
11606 (IS_SCHEMA(child, "maxExclusive")) ||
11607 (IS_SCHEMA(child, "totalDigits")) ||
11608 (IS_SCHEMA(child, "fractionDigits")) ||
11609 (IS_SCHEMA(child, "pattern")) ||
11610 (IS_SCHEMA(child, "enumeration")) ||
11611 (IS_SCHEMA(child, "whiteSpace")) ||
11612 (IS_SCHEMA(child, "length")) ||
11613 (IS_SCHEMA(child, "maxLength")) ||
11614 (IS_SCHEMA(child, "minLength"))) {
11615 facet = xmlSchemaParseFacet(ctxt, schema, child);
11616 if (facet != NULL) {
11617 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011618 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011619 else
11620 lastfacet->next = facet;
11621 lastfacet = facet;
11622 lastfacet->next = NULL;
11623 }
11624 child = child->next;
11625 }
11626 /*
11627 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011628 */
11629 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011630 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11631
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011632 facet = type->facets;
11633 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011634 facetLink = (xmlSchemaFacetLinkPtr)
11635 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +000011636 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011637 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011638 xmlFree(facetLink);
11639 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011640 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011641 facetLink->facet = facet;
11642 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011643 if (lastFacetLink == NULL)
11644 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011645 else
11646 lastFacetLink->next = facetLink;
11647 lastFacetLink = facetLink;
11648 facet = facet->next;
11649 } while (facet != NULL);
11650 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011651 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011652 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11653 /*
11654 * Attribute uses/declarations.
11655 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011656 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11657 (xmlSchemaItemListPtr *) &(type->attrUses),
11658 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11659 return(NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011660 /*
11661 * Attribute wildcard.
11662 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011663 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011664 type->attributeWildcard =
11665 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011666 child = child->next;
11667 }
11668 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011669 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011670 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11671 xmlSchemaPContentErr(ctxt,
11672 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011673 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011674 "annotation?, (group | all | choice | sequence)?, "
11675 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011676 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011677 xmlSchemaPContentErr(ctxt,
11678 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011679 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011680 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11681 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11682 "length | minLength | maxLength | enumeration | whiteSpace | "
11683 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11684 } else {
11685 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011686 xmlSchemaPContentErr(ctxt,
11687 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011688 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011689 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11690 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11691 "length | minLength | maxLength | enumeration | whiteSpace | "
11692 "pattern)*))");
11693 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011694 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011695 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011696}
11697
11698/**
11699 * xmlSchemaParseExtension:
11700 * @ctxt: a schema validation context
11701 * @schema: the schema being built
11702 * @node: a subtree containing XML Schema informations
11703 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011704 * Parses an <extension>, which is found inside a
11705 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011706 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000011707 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011708 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000011709 */
11710static xmlSchemaTypePtr
11711xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011712 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000011713{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011714 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011715 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011716 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011717
11718 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11719 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011720 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011721 type = ctxt->ctxtType;
11722 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000011723
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011724 /*
11725 * Check for illegal attributes.
11726 */
11727 attr = node->properties;
11728 while (attr != NULL) {
11729 if (attr->ns == NULL) {
11730 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11731 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011732 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011733 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011734 }
11735 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011736 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011737 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011738 }
11739 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011740 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011741
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011742 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011743
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011744 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011745 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011746 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011747 if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11748 "base", &(type->baseNs), &(type->base)) == 0) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011749 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011750 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011751 XML_SCHEMAP_S4S_ATTR_MISSING,
11752 NULL, node, "base", NULL);
11753 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011754 /*
11755 * And now for the children...
11756 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011757 child = node->children;
11758 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011759 /*
11760 * Add the annotation to the type ancestor.
11761 */
11762 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011763 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011764 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011765 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011766 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11767 /*
11768 * Corresponds to <complexType><complexContent><extension>... and:
11769 *
11770 * Model groups <all>, <choice>, <sequence> and <group>.
11771 */
11772 if (IS_SCHEMA(child, "all")) {
11773 type->subtypes = (xmlSchemaTypePtr)
11774 xmlSchemaParseModelGroup(ctxt, schema,
11775 child, XML_SCHEMA_TYPE_ALL, 1);
11776 child = child->next;
11777 } else if (IS_SCHEMA(child, "choice")) {
11778 type->subtypes = (xmlSchemaTypePtr)
11779 xmlSchemaParseModelGroup(ctxt, schema,
11780 child, XML_SCHEMA_TYPE_CHOICE, 1);
11781 child = child->next;
11782 } else if (IS_SCHEMA(child, "sequence")) {
11783 type->subtypes = (xmlSchemaTypePtr)
11784 xmlSchemaParseModelGroup(ctxt, schema,
11785 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11786 child = child->next;
11787 } else if (IS_SCHEMA(child, "group")) {
11788 type->subtypes = (xmlSchemaTypePtr)
11789 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011790 /*
11791 * Note that the reference will be resolved in
11792 * xmlSchemaResolveTypeReferences();
11793 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011794 child = child->next;
11795 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011796 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011797 if (child != NULL) {
11798 /*
11799 * Attribute uses/declarations.
11800 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011801 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11802 (xmlSchemaItemListPtr *) &(type->attrUses),
11803 XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11804 return(NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011805 /*
11806 * Attribute wildcard.
11807 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011808 if (IS_SCHEMA(child, "anyAttribute")) {
11809 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011810 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11811 child = child->next;
11812 }
11813 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011814 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011815 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11816 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011817 xmlSchemaPContentErr(ctxt,
11818 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011819 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011820 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011821 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011822 } else {
11823 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011824 xmlSchemaPContentErr(ctxt,
11825 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011826 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011827 "(annotation?, ((attribute | attributeGroup)*, "
11828 "anyAttribute?))");
11829 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011830 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011831 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011832}
11833
11834/**
11835 * xmlSchemaParseSimpleContent:
11836 * @ctxt: a schema validation context
11837 * @schema: the schema being built
11838 * @node: a subtree containing XML Schema informations
11839 *
11840 * parse a XML schema SimpleContent definition
11841 * *WARNING* this interface is highly subject to change
11842 *
11843 * Returns the type definition or NULL in case of error
11844 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011845static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011846xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011847 xmlSchemaPtr schema, xmlNodePtr node,
11848 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000011849{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011850 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011851 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011852 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011853
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011854 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11855 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011856 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011857 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011858 /* Not a component, don't create it. */
11859 type = ctxt->ctxtType;
11860 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11861 /*
11862 * Check for illegal attributes.
11863 */
11864 attr = node->properties;
11865 while (attr != NULL) {
11866 if (attr->ns == NULL) {
11867 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011868 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011869 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011870 }
11871 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011872 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011873 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011874 }
11875 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011876 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011877
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011878 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000011879
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011880 /*
11881 * And now for the children...
11882 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011883 child = node->children;
11884 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011885 /*
11886 * Add the annotation to the complex type ancestor.
11887 */
11888 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011889 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011890 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011891 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011892 if (child == NULL) {
11893 xmlSchemaPContentErr(ctxt,
11894 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011895 NULL, node, NULL, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011896 "(annotation?, (restriction | extension))");
11897 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011898 if (child == NULL) {
11899 xmlSchemaPContentErr(ctxt,
11900 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011901 NULL, node, NULL, NULL,
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011902 "(annotation?, (restriction | extension))");
11903 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011904 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011905 xmlSchemaParseRestriction(ctxt, schema, child,
11906 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011907 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011908 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011909 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011910 xmlSchemaParseExtension(ctxt, schema, child,
11911 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011912 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011913 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011914 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011915 if (child != NULL) {
11916 xmlSchemaPContentErr(ctxt,
11917 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011918 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011919 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000011920 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011921 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000011922}
11923
11924/**
11925 * xmlSchemaParseComplexContent:
11926 * @ctxt: a schema validation context
11927 * @schema: the schema being built
11928 * @node: a subtree containing XML Schema informations
11929 *
11930 * parse a XML schema ComplexContent definition
11931 * *WARNING* this interface is highly subject to change
11932 *
11933 * Returns the type definition or NULL in case of error
11934 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011935static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011936xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011937 xmlSchemaPtr schema, xmlNodePtr node,
11938 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000011939{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011940 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011941 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011942 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011943
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011944 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11945 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011946 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011947 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011948 /* Not a component, don't create it. */
11949 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011950 /*
11951 * Check for illegal attributes.
11952 */
11953 attr = node->properties;
11954 while (attr != NULL) {
11955 if (attr->ns == NULL) {
11956 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011957 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011958 {
11959 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011960 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011961 }
11962 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11963 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011964 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011965 }
11966 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011967 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011968
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011969 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011970
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011971 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011972 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011973 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011974 if (xmlGetBooleanProp(ctxt, node, "mixed", 0)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011975 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
11976 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011977 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011978 child = node->children;
11979 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011980 /*
11981 * Add the annotation to the complex type ancestor.
11982 */
11983 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011984 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011985 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011986 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011987 if (child == NULL) {
11988 xmlSchemaPContentErr(ctxt,
11989 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011990 NULL, node, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011991 NULL, "(annotation?, (restriction | extension))");
11992 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011993 if (child == NULL) {
11994 xmlSchemaPContentErr(ctxt,
11995 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011996 NULL, node, NULL,
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011997 NULL, "(annotation?, (restriction | extension))");
11998 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011999 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012000 xmlSchemaParseRestriction(ctxt, schema, child,
12001 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012002 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012003 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012004 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012005 xmlSchemaParseExtension(ctxt, schema, child,
12006 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012007 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012008 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012009 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012010 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012011 xmlSchemaPContentErr(ctxt,
12012 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012013 NULL, node, child,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012014 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000012015 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012016 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000012017}
12018
12019/**
12020 * xmlSchemaParseComplexType:
12021 * @ctxt: a schema validation context
12022 * @schema: the schema being built
12023 * @node: a subtree containing XML Schema informations
12024 *
12025 * parse a XML schema Complex Type definition
12026 * *WARNING* this interface is highly subject to change
12027 *
12028 * Returns the type definition or NULL in case of error
12029 */
12030static xmlSchemaTypePtr
12031xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000012032 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000012033{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012034 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000012035 xmlNodePtr child = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012036 const xmlChar *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012037 xmlAttrPtr attr;
12038 const xmlChar *attrValue;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012039#ifdef ENABLE_NAMED_LOCALS
Daniel Veillard1a380b82004-10-21 16:00:06 +000012040 char buf[40];
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012041#endif
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012042 int final = 0, block = 0, hasRestrictionOrExtension = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000012043
Daniel Veillard4255d502002-04-16 15:50:10 +000012044
12045 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12046 return (NULL);
12047
Daniel Veillard01fa6152004-06-29 17:04:39 +000012048 ctxtType = ctxt->ctxtType;
12049
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012050 if (topLevel) {
12051 attr = xmlSchemaGetPropNode(node, "name");
12052 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012053 xmlSchemaPMissingAttrErr(ctxt,
12054 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012055 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012056 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012057 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12058 return (NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012059 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012060 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012061
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012062 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012063 /*
12064 * Parse as local complex type definition.
12065 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012066#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000012067 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012068 type = xmlSchemaAddType(ctxt, schema,
12069 XML_SCHEMA_TYPE_COMPLEX,
12070 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012071 ctxt->targetNamespace, node, 0);
12072#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012073 type = xmlSchemaAddType(ctxt, schema,
12074 XML_SCHEMA_TYPE_COMPLEX,
12075 NULL, ctxt->targetNamespace, node, 0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012076#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012077 if (type == NULL)
12078 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012079 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012080 type->node = node;
12081 type->type = XML_SCHEMA_TYPE_COMPLEX;
12082 /*
12083 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012084 */
12085 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012086 /*
12087 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012088 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012089 type = xmlSchemaAddType(ctxt, schema,
12090 XML_SCHEMA_TYPE_COMPLEX,
12091 name, ctxt->targetNamespace, node, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012092 if (type == NULL)
12093 return (NULL);
12094 type->node = node;
12095 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012096 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000012097 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012098 type->targetNamespace = ctxt->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012099 /*
12100 * Handle attributes.
12101 */
12102 attr = node->properties;
12103 while (attr != NULL) {
12104 if (attr->ns == NULL) {
12105 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12106 /*
12107 * Attribute "id".
12108 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012109 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012110 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12111 /*
12112 * Attribute "mixed".
12113 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012114 if (xmlSchemaPGetBoolNodeValue(ctxt,
12115 NULL, (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012116 type->flags |= XML_SCHEMAS_TYPE_MIXED;
12117 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012118 /*
12119 * Attributes of global complex type definitions.
12120 */
12121 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12122 /* Pass. */
12123 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12124 /*
12125 * Attribute "abstract".
12126 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012127 if (xmlSchemaPGetBoolNodeValue(ctxt,
12128 NULL, (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012129 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12130 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12131 /*
12132 * Attribute "final".
12133 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012134 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012135 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012136 if (xmlSchemaPValAttrBlockFinal(attrValue,
12137 &(type->flags),
12138 -1,
12139 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12140 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12141 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012142 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012143 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012144 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012145 NULL, (xmlNodePtr) attr, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012146 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012147 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012148 } else
12149 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012150 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12151 /*
12152 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012153 */
12154 attrValue = xmlSchemaGetNodeContent(ctxt,
12155 (xmlNodePtr) attr);
12156 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012157 -1,
12158 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012159 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012160 -1, -1, -1) != 0) {
12161 xmlSchemaPSimpleTypeErr(ctxt,
12162 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012163 NULL, (xmlNodePtr) attr, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012164 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012165 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012166 } else
12167 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012168 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012169 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012170 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012171 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012172 } else {
12173 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012174 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012175 }
12176 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012177 xmlSchemaPIllegalAttrErr(ctxt,
12178 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012179 }
12180 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012181 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012182 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000012183 /*
12184 * Apply default "block" values.
12185 */
12186 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12187 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12188 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12189 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12190 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012191 if (! final) {
12192 /*
12193 * Apply default "block" values.
12194 */
12195 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12196 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12197 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12198 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12199 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012200 /*
12201 * And now for the children...
12202 */
Daniel Veillard4255d502002-04-16 15:50:10 +000012203 child = node->children;
12204 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012205 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012206 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012207 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012208 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000012209 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012210 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012211 * <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012212 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012213 * Specifying mixed='true' when the <simpleContent>
12214 * alternative is chosen has no effect
12215 */
William M. Bracke7091952004-05-11 15:09:58 +000012216 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12217 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012218 xmlSchemaParseSimpleContent(ctxt, schema, child,
12219 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012220 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012221 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012222 /*
12223 * <complexType><complexContent>...
12224 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012225 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012226 xmlSchemaParseComplexContent(ctxt, schema, child,
12227 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012228 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012229 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012230 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012231 * E.g <complexType><sequence>... or <complexType><attribute>... etc.
12232 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012233 * SPEC
12234 * "...the third alternative (neither <simpleContent> nor
12235 * <complexContent>) is chosen. This case is understood as shorthand
12236 * for complex content restricting the ·ur-type definition·, and the
12237 * details of the mappings should be modified as necessary.
12238 */
12239 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12240 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012241 /*
12242 * Parse model groups.
12243 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012244 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012245 type->subtypes = (xmlSchemaTypePtr)
12246 xmlSchemaParseModelGroup(ctxt, schema, child,
12247 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012248 child = child->next;
12249 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012250 type->subtypes = (xmlSchemaTypePtr)
12251 xmlSchemaParseModelGroup(ctxt, schema, child,
12252 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012253 child = child->next;
12254 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012255 type->subtypes = (xmlSchemaTypePtr)
12256 xmlSchemaParseModelGroup(ctxt, schema, child,
12257 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012258 child = child->next;
12259 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012260 type->subtypes = (xmlSchemaTypePtr)
12261 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012262 /*
12263 * Note that the reference will be resolved in
12264 * xmlSchemaResolveTypeReferences();
12265 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012266 child = child->next;
12267 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012268 /*
12269 * Parse attribute decls/refs.
12270 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012271 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12272 (xmlSchemaItemListPtr *) &(type->attrUses),
12273 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12274 return(NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012275 /*
12276 * Parse attribute wildcard.
12277 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012278 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012279 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12280 child = child->next;
12281 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012282 }
12283 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012284 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012285 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012286 NULL, node, child,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012287 NULL, "(annotation?, (simpleContent | complexContent | "
12288 "((group | all | choice | sequence)?, ((attribute | "
12289 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000012290 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012291 /*
12292 * REDEFINE: SPEC src-redefine (5)
12293 */
12294 if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12295 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012296 NULL, node, "This is a redefinition, thus the "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012297 "<complexType> must have a <restriction> or <extension> "
12298 "grand-child", NULL);
12299 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012300 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000012301 return (type);
12302}
12303
Daniel Veillard4255d502002-04-16 15:50:10 +000012304/************************************************************************
12305 * *
12306 * Validating using Schemas *
12307 * *
12308 ************************************************************************/
12309
12310/************************************************************************
12311 * *
12312 * Reading/Writing Schemas *
12313 * *
12314 ************************************************************************/
12315
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012316#if 0 /* Will be enabled if it is clear what options are needed. */
12317/**
12318 * xmlSchemaParserCtxtSetOptions:
12319 * @ctxt: a schema parser context
12320 * @options: a combination of xmlSchemaParserOption
12321 *
12322 * Sets the options to be used during the parse.
12323 *
12324 * Returns 0 in case of success, -1 in case of an
12325 * API error.
12326 */
12327static int
12328xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12329 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012330
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012331{
12332 int i;
12333
12334 if (ctxt == NULL)
12335 return (-1);
12336 /*
12337 * WARNING: Change the start value if adding to the
12338 * xmlSchemaParseOption.
12339 */
12340 for (i = 1; i < (int) sizeof(int) * 8; i++) {
12341 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012342 return (-1);
12343 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012344 }
12345 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012346 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012347}
12348
12349/**
12350 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012351 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012352 *
12353 * Returns the option combination of the parser context.
12354 */
12355static int
12356xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012357
12358{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012359 if (ctxt == NULL)
12360 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012361 else
12362 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012363}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012364#endif
12365
Daniel Veillard4255d502002-04-16 15:50:10 +000012366/**
12367 * xmlSchemaNewParserCtxt:
12368 * @URL: the location of the schema
12369 *
12370 * Create an XML Schemas parse context for that file/resource expected
12371 * to contain an XML Schemas file.
12372 *
12373 * Returns the parser context or NULL in case of error
12374 */
12375xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012376xmlSchemaNewParserCtxt(const char *URL)
12377{
Daniel Veillard4255d502002-04-16 15:50:10 +000012378 xmlSchemaParserCtxtPtr ret;
12379
12380 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012381 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000012382
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012383 ret = xmlSchemaParserCtxtCreate();
12384 if (ret == NULL)
12385 return(NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012386 ret->dict = xmlDictCreate();
12387 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012388 return (ret);
12389}
12390
12391/**
Daniel Veillard6045c902002-10-09 21:13:59 +000012392 * xmlSchemaNewMemParserCtxt:
12393 * @buffer: a pointer to a char array containing the schemas
12394 * @size: the size of the array
12395 *
12396 * Create an XML Schemas parse context for that memory buffer expected
12397 * to contain an XML Schemas file.
12398 *
12399 * Returns the parser context or NULL in case of error
12400 */
12401xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012402xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12403{
Daniel Veillard6045c902002-10-09 21:13:59 +000012404 xmlSchemaParserCtxtPtr ret;
12405
12406 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012407 return (NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012408 ret = xmlSchemaParserCtxtCreate();
12409 if (ret == NULL)
12410 return(NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000012411 ret->buffer = buffer;
12412 ret->size = size;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012413 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000012414 return (ret);
12415}
12416
12417/**
Daniel Veillard9d751502003-10-29 13:21:47 +000012418 * xmlSchemaNewDocParserCtxt:
12419 * @doc: a preparsed document tree
12420 *
12421 * Create an XML Schemas parse context for that document.
12422 * NB. The document may be modified during the parsing process.
12423 *
12424 * Returns the parser context or NULL in case of error
12425 */
12426xmlSchemaParserCtxtPtr
12427xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12428{
12429 xmlSchemaParserCtxtPtr ret;
12430
12431 if (doc == NULL)
12432 return (NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012433 ret = xmlSchemaParserCtxtCreate();
12434 if (ret == NULL)
12435 return(NULL);
Daniel Veillard9d751502003-10-29 13:21:47 +000012436 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000012437 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000012438 /* The application has responsibility for the document */
12439 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000012440
12441 return (ret);
12442}
12443
12444/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012445 * xmlSchemaFreeParserCtxt:
12446 * @ctxt: the schema parser context
12447 *
12448 * Free the resources associated to the schema parser context
12449 */
12450void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012451xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12452{
Daniel Veillard4255d502002-04-16 15:50:10 +000012453 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012454 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000012455 if (ctxt->doc != NULL && !ctxt->preserve)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012456 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012457 if (ctxt->vctxt != NULL) {
12458 xmlSchemaFreeValidCtxt(ctxt->vctxt);
12459 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012460 if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12461 xmlSchemaConstructionCtxtFree(ctxt->constructor);
12462 ctxt->constructor = NULL;
12463 ctxt->ownsConstructor = 0;
12464 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012465 if (ctxt->attrProhibs != NULL)
12466 xmlSchemaItemListFree(ctxt->attrProhibs);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012467 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000012468 xmlFree(ctxt);
12469}
12470
12471/************************************************************************
12472 * *
12473 * Building the content models *
12474 * *
12475 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012476
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012477static void
12478xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012479 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012480{
Daniel Veillarda980bef2005-07-18 21:34:03 +000012481 xmlAutomataStatePtr start, tmp;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012482 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012483 xmlSchemaSubstGroupPtr substGroup;
12484 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012485
12486 elemDecl = (xmlSchemaElementPtr) particle->children;
12487 /*
12488 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012489 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012490 start = pctxt->state;
Daniel Veillarda980bef2005-07-18 21:34:03 +000012491 if (end == NULL)
12492 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012493 substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012494 if (substGroup == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012495 xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012496 XML_SCHEMAP_INTERNAL,
12497 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12498 "declaration is marked having a subst. group but none "
12499 "available.\n", elemDecl->name, NULL);
12500 return;
12501 }
Daniel Veillarda980bef2005-07-18 21:34:03 +000012502 if (counter >= 0) {
12503 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012504 * NOTE that we put the declaration in, even if it's abstract.
12505 * However, an error will be raised during *validation* if an element
12506 * information item shall be validated against an abstract element
12507 * declaration.
Daniel Veillarda980bef2005-07-18 21:34:03 +000012508 */
12509 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12510 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12511 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12512 /*
12513 * Add subst. group members.
12514 */
12515 for (i = 0; i < substGroup->members->nbItems; i++) {
12516 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12517 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12518 member->name, member->targetNamespace, member);
12519 }
12520 } else if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012521 /*
12522 * NOTE that we put the declaration in, even if it's abstract,
12523 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012524 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012525 xmlAutomataNewTransition2(pctxt->am,
12526 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012527 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12528 /*
12529 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012530 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012531 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012532 member = (xmlSchemaElementPtr) substGroup->members->items[i];
Daniel Veillarda980bef2005-07-18 21:34:03 +000012533 tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12534 member->name, member->targetNamespace,
12535 1, 1, member);
12536 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012537 }
12538 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012539 xmlAutomataStatePtr hop;
12540 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12541 UNBOUNDED : particle->maxOccurs - 1;
12542 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12543
12544 counter =
12545 xmlAutomataNewCounter(pctxt->am, minOccurs,
12546 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012547 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012548
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012549 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012550 xmlAutomataNewTransition2(pctxt->am,
12551 start, NULL,
12552 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012553 hop);
12554 /*
Daniel Veillarda980bef2005-07-18 21:34:03 +000012555 * Add subst. group members.
12556 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012557 for (i = 0; i < substGroup->members->nbItems; i++) {
12558 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12559 xmlAutomataNewEpsilon(pctxt->am,
12560 xmlAutomataNewTransition2(pctxt->am,
12561 start, NULL,
12562 member->name, member->targetNamespace, member),
12563 hop);
12564 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012565 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12566 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12567 }
12568 if (particle->minOccurs == 0)
12569 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012570 pctxt->state = end;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012571}
12572
12573static void
12574xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12575 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012576{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012577 if (((xmlSchemaElementPtr) particle->children)->flags &
12578 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012579 /*
12580 * Substitution groups.
12581 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000012582 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012583 } else {
12584 xmlSchemaElementPtr elemDecl;
12585 xmlAutomataStatePtr start;
12586
12587 elemDecl = (xmlSchemaElementPtr) particle->children;
12588
12589 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012590 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012591 if (particle->maxOccurs == 1) {
12592 start = ctxt->state;
12593 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012594 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12595 } else if ((particle->maxOccurs >= UNBOUNDED) &&
12596 (particle->minOccurs < 2)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012597 /* Special case. */
12598 start = ctxt->state;
12599 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12600 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012601 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, start);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012602 } else {
12603 int counter;
12604 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12605 UNBOUNDED : particle->maxOccurs - 1;
12606 int minOccurs = particle->minOccurs < 1 ?
12607 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012608
12609 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012610 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12611 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12612 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12613 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12614 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12615 NULL, counter);
12616 }
12617 if (particle->minOccurs == 0)
12618 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12619 }
12620}
12621
Daniel Veillard4255d502002-04-16 15:50:10 +000012622/**
12623 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000012624 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012625 * @particle: the particle component
12626 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000012627 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012628 * Create the automaton for the {content type} of a complex type.
12629 *
Daniel Veillard4255d502002-04-16 15:50:10 +000012630 */
12631static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012632xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012633 xmlSchemaParticlePtr particle)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012634{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012635 if (particle == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012636 PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012637 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000012638 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012639 if (particle->children == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012640 /*
12641 * Just return in this case. A missing "term" of the particle
12642 * might arise due to an invalid "term" component.
12643 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012644 return;
12645 }
12646
12647 switch (particle->children->type) {
12648 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012649 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012650 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012651 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000012652
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012653 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012654
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012655 start = pctxt->state;
12656 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012657
12658 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012659 if (wild->any == 1) {
12660 /*
12661 * We need to add both transitions:
12662 *
12663 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012664 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012665 pctxt->state =
12666 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012667 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012668 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012669 /*
12670 * 2. the {"*"} for elements in no namespace.
12671 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012672 pctxt->state =
12673 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012674 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012675 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012676
12677 } else if (wild->nsSet != NULL) {
12678 ns = wild->nsSet;
12679 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012680 pctxt->state = start;
12681 pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12682 pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12683 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012684 ns = ns->next;
12685 } while (ns != NULL);
12686
12687 } else if (wild->negNsSet != NULL) {
Daniel Veillard6e65e152005-08-09 11:09:52 +000012688 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12689 start, end, BAD_CAST "*", wild->negNsSet->value,
12690 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012691 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012692 } else {
12693 int counter;
12694 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012695 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012696 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012697 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012698 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012699
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012700 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12701 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012702 if (wild->any == 1) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012703 pctxt->state =
12704 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012705 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012706 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12707 pctxt->state =
12708 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012709 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012710 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012711 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012712 ns = wild->nsSet;
12713 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012714 pctxt->state =
12715 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012716 start, NULL, BAD_CAST "*", ns->value, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012717 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012718 ns = ns->next;
12719 } while (ns != NULL);
12720
12721 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012722 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
Daniel Veillard9efc4762005-07-19 14:33:55 +000012723 start, hop, BAD_CAST "*", wild->negNsSet->value,
12724 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012725 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012726 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12727 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012728 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012729 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012730 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012731 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012732 pctxt->state = end;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012733 break;
12734 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012735 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012736 xmlSchemaBuildContentModelForElement(pctxt, particle);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012737 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012738 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012739 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012740
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012741 /*
12742 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012743 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012744 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012745 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12746 sub = particle->children->children;
12747 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012748 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012749 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012750 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012751 }
12752 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012753 xmlAutomataStatePtr oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012754
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012755 if (particle->maxOccurs >= UNBOUNDED) {
12756 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012757 xmlAutomataStatePtr tmp;
12758 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012759
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012760 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012761 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012762 oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012763
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012764 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012765 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000012766
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012767 sub = particle->children->children;
12768 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012769 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012770 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012771 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012772 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012773 tmp = pctxt->state;
12774 xmlAutomataNewCountedTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012775 oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012776 pctxt->state =
12777 xmlAutomataNewCounterTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012778 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000012779
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012780 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012781 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Daniel Veillardafc05b62005-07-17 06:11:19 +000012782 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012783 oldstate = pctxt->state;
Daniel Veillardafc05b62005-07-17 06:11:19 +000012784
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012785 sub = particle->children->children;
12786 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012787 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012788 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012789 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012790 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012791 xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012792 oldstate);
Daniel Veillardafc05b62005-07-17 06:11:19 +000012793 /*
12794 * epsilon needed to block previous trans from
12795 * being allowed to enter back from another
12796 * construct
12797 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012798 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12799 pctxt->state, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012800 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012801 xmlAutomataNewEpsilon(pctxt->am,
12802 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012803 }
12804 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012805 } else if ((particle->maxOccurs > 1)
12806 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012807 xmlAutomataStatePtr tmp;
12808 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012809
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012810 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012811 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012812 oldstate = pctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000012813
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012814 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012815 particle->minOccurs - 1,
12816 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012817
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012818 sub = particle->children->children;
12819 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012820 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012821 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012822 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012823 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012824 tmp = pctxt->state;
12825 xmlAutomataNewCountedTrans(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012826 tmp, oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012827 pctxt->state =
12828 xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012829 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012830 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012831 xmlAutomataNewEpsilon(pctxt->am,
12832 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012833 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012834 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012835 sub = particle->children->children;
12836 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012837 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012838 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012839 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012840 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012841 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012842 xmlAutomataNewEpsilon(pctxt->am, oldstate,
12843 pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012844 }
12845 }
12846 }
12847 break;
12848 }
12849 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012850 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012851 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000012852
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012853 start = pctxt->state;
12854 end = xmlAutomataNewState(pctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000012855
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012856 /*
12857 * iterate over the subtypes and remerge the end with an
12858 * epsilon transition
12859 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012860 if (particle->maxOccurs == 1) {
12861 sub = particle->children->children;
12862 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012863 pctxt->state = start;
12864 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012865 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012866 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012867 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012868 }
12869 } else {
12870 int counter;
Daniel Veillardafc05b62005-07-17 06:11:19 +000012871 xmlAutomataStatePtr hop, base;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012872 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12873 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012874 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012875 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000012876
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012877 /*
12878 * use a counter to keep track of the number of transtions
12879 * which went through the choice.
12880 */
12881 counter =
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012882 xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12883 hop = xmlAutomataNewState(pctxt->am);
12884 base = xmlAutomataNewState(pctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000012885
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012886 sub = particle->children->children;
12887 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012888 pctxt->state = base;
12889 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012890 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012891 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012892 sub = sub->next;
Daniel Veillarda980bef2005-07-18 21:34:03 +000012893 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012894 xmlAutomataNewEpsilon(pctxt->am, start, base);
12895 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
12896 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012897 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012898 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012899 xmlAutomataNewEpsilon(pctxt->am, start, end);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012900 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012901 pctxt->state = end;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012902 break;
12903 }
12904 case XML_SCHEMA_TYPE_ALL:{
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +000012905 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012906 xmlSchemaParticlePtr sub;
12907 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012908 int lax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012909
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012910 sub = (xmlSchemaParticlePtr) particle->children->children;
12911 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012912 break;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012913 start = pctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012914 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012915 pctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012916
12917 elemDecl = (xmlSchemaElementPtr) sub->children;
12918 if (elemDecl == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012919 PERROR_INT("xmlSchemaBuildAContentModel",
12920 "<element> particle has no term");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012921 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012922 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012923 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012924 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000012925 * {particles} of the group must be 0 or 1; this is
12926 * already ensured during the parse of the content of
12927 * <all>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012928 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000012929 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12930 int counter;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012931
Daniel Veillarda980bef2005-07-18 21:34:03 +000012932 /*
12933 * This is an abstract group, we need to share
12934 * the same counter for all the element transitions
12935 * derived from the group
12936 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012937 counter = xmlAutomataNewCounter(pctxt->am,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012938 sub->minOccurs, sub->maxOccurs);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012939 xmlSchemaBuildContentModelForSubstGroup(pctxt,
12940 sub, counter, pctxt->state);
Daniel Veillarda980bef2005-07-18 21:34:03 +000012941 } else {
12942 if ((sub->minOccurs == 1) &&
12943 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012944 xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
12945 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012946 elemDecl->name,
12947 elemDecl->targetNamespace,
12948 1, 1, elemDecl);
12949 } else if ((sub->minOccurs == 0) &&
12950 (sub->maxOccurs == 1)) {
12951
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012952 xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
12953 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012954 elemDecl->name,
12955 elemDecl->targetNamespace,
12956 0,
12957 1,
12958 elemDecl);
12959 }
12960 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012961 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012962 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012963 lax = particle->minOccurs == 0;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012964 pctxt->state =
12965 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012966 break;
12967 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012968 case XML_SCHEMA_TYPE_GROUP:
12969 /*
12970 * If we hit a model group definition, then this means that
12971 * it was empty, thus was not substituted for the containing
12972 * model group. Just do nothing in this case.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012973 * TODO: But the group should be substituted and not occur at
12974 * all in the content model at this point. Fix this.
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012975 */
12976 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012977 default:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012978 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
12979 "xmlSchemaBuildAContentModel",
12980 "found unexpected term of type '%s' in content model",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012981 WXS_ITEM_TYPE_NAME(particle->children), NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012982 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000012983 }
12984}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012985
Daniel Veillard4255d502002-04-16 15:50:10 +000012986/**
12987 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000012988 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012989 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000012990 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000012991 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012992 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000012993 */
12994static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012995xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012996 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012997{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012998 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
12999 (type->contModel != NULL) ||
13000 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13001 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013002 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013003
13004#ifdef DEBUG_CONTENT
13005 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013006 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013007#endif
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013008 ctxt->am = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013009 ctxt->am = xmlNewAutomata();
13010 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013011 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013012 "Cannot create automata for complex type %s\n", type->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013013 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000013014 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000013015 ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013016 /*
13017 * Build the automaton.
13018 */
13019 xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
Daniel Veillard4255d502002-04-16 15:50:10 +000013020 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013021 type->contModel = xmlAutomataCompile(ctxt->am);
13022 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013023 xmlSchemaPCustomErr(ctxt,
13024 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013025 WXS_BASIC_CAST type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013026 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013027 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013028 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013029 XML_SCHEMAP_NOT_DETERMINISTIC,
13030 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013031 WXS_BASIC_CAST type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013032 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000013033 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000013034#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013035 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013036 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013037 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000013038#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000013039 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000013040 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013041 xmlFreeAutomata(ctxt->am);
13042 ctxt->am = NULL;
13043}
13044
13045/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013046 * xmlSchemaResolveElementReferences:
Daniel Veillard4255d502002-04-16 15:50:10 +000013047 * @elem: the schema element context
13048 * @ctxt: the schema parser context
13049 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000013050 * Resolves the references of an element declaration
13051 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013052 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000013053 */
13054static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013055xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13056 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000013057{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013058 if ((ctxt == NULL) || (elemDecl == NULL) ||
13059 ((elemDecl != NULL) &&
13060 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013061 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013062 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013063
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013064 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013065 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013066
13067 /* (type definition) ... otherwise the type definition ·resolved·
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013068 * to by the ·actual value· of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013069 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013070 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013071 elemDecl->namedTypeNs);
13072 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013073 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013074 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013075 WXS_BASIC_CAST elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013076 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013077 XML_SCHEMA_TYPE_BASIC, "type definition");
13078 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013079 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013080 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013081 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013082 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013083
Daniel Veillardc0826a72004-08-10 14:17:33 +000013084 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013085 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013086 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000013087 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013088 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13089 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013090 if (substHead == NULL) {
13091 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013092 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013093 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013094 "substitutionGroup", elemDecl->substGroup,
13095 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013096 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013097 xmlSchemaResolveElementReferences(substHead, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013098 /*
13099 * Set the "substitution group affiliation".
13100 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013101 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013102 WXS_SUBST_HEAD(elemDecl) = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013103 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013104 * The type definitions is set to:
13105 * SPEC "...the {type definition} of the element
13106 * declaration ·resolved· to by the ·actual value·
13107 * of the substitutionGroup [attribute], if present"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013108 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013109 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013110 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013111 }
13112 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013113 /*
13114 * SPEC "The definition of anyType serves as the default type definition
13115 * for element declarations whose XML representation does not specify one."
13116 */
13117 if ((elemDecl->subtypes == NULL) &&
13118 (elemDecl->namedType == NULL) &&
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013119 (elemDecl->substGroup == NULL))
13120 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000013121}
13122
13123/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013124 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000013125 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013126 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000013127 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013128 * Checks and builds the "member type definitions" property of the union
13129 * simple type. This handles part (1), part (2) is done in
13130 * xmlSchemaFinishMemberTypeDefinitionsProperty()
13131 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000013132 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000013133 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013134static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013135xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13136 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000013137{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013138
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013139 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013140 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000013141
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013142 /*
13143 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13144 * define the explicit members as the type definitions ·resolved·
13145 * to by the items in the ·actual value· of the memberTypes [attribute],
13146 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013147 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000013148 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013149 /*
13150 * Resolve references.
13151 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013152 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013153 lastLink = NULL;
13154 while (link != NULL) {
13155 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013156
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013157 name = ((xmlSchemaQNameRefPtr) link->type)->name;
13158 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13159
13160 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013161 if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013162 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013163 WXS_BASIC_CAST type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013164 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13165 /*
13166 * Remove the member type link.
13167 */
13168 if (lastLink == NULL)
13169 type->memberTypes = link->next;
13170 else
13171 lastLink->next = link->next;
13172 newLink = link;
13173 link = link->next;
13174 xmlFree(newLink);
13175 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013176 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013177 lastLink = link;
13178 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013179 }
13180 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013181 /*
13182 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013183 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013184 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013185 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013186 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13187 if (link == NULL) {
13188 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13189 return (-1);
13190 }
13191 link->type = memberType;
13192 link->next = NULL;
13193 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013194 type->memberTypes = link;
13195 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000013196 lastLink->next = link;
13197 lastLink = link;
13198 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013199 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013200 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000013201}
13202
Daniel Veillard4255d502002-04-16 15:50:10 +000013203/**
Daniel Veillard3646d642004-06-02 19:19:14 +000013204 * xmlSchemaIsDerivedFromBuiltInType:
13205 * @ctxt: the schema parser context
13206 * @type: the type definition
13207 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013208 *
Daniel Veillard3646d642004-06-02 19:19:14 +000013209 *
13210 * Returns 1 if the type has the given value type, or
13211 * is derived from such a type.
13212 */
William M. Brack803812b2004-06-03 02:11:24 +000013213static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013214xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000013215{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013216 if (type == NULL)
13217 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013218 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013219 return (0);
13220 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13221 if (type->builtInType == valType)
13222 return(1);
13223 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13224 (type->builtInType == XML_SCHEMAS_ANYTYPE))
13225 return (0);
13226 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard6a0baa02005-12-10 11:11:12 +000013227 }
13228 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000013229}
13230
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013231#if 0
13232/**
13233 * xmlSchemaIsDerivedFromBuiltInType:
13234 * @ctxt: the schema parser context
13235 * @type: the type definition
13236 * @valType: the value type
13237 *
13238 *
13239 * Returns 1 if the type has the given value type, or
13240 * is derived from such a type.
13241 */
13242static int
13243xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13244{
13245 if (type == NULL)
13246 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013247 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013248 return (0);
13249 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13250 if (type->builtInType == valType)
13251 return(1);
13252 return (0);
13253 } else
13254 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13255
13256 return (0);
13257}
13258#endif
13259
13260static xmlSchemaTypePtr
13261xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13262{
13263 if (type == NULL)
13264 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013265 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013266 return (NULL);
13267 if (type->type == XML_SCHEMA_TYPE_BASIC)
Daniel Veillard6a0baa02005-12-10 11:11:12 +000013268 return(type);
13269 return(xmlSchemaQueryBuiltInType(type->subtypes));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013270}
13271
Daniel Veillard3646d642004-06-02 19:19:14 +000013272/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013273 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013274 * @type: the simpleType definition
13275 *
13276 * Returns the primitive type of the given type or
13277 * NULL in case of error.
13278 */
13279static xmlSchemaTypePtr
13280xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13281{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013282
Daniel Veillard01fa6152004-06-29 17:04:39 +000013283 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013284 /*
13285 * Note that anySimpleType is actually not a primitive type
13286 * but we need that here.
13287 */
13288 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13289 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013290 return (type);
13291 type = type->baseType;
13292 }
13293
13294 return (NULL);
13295}
13296
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013297#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013298/**
13299 * xmlSchemaGetBuiltInTypeAncestor:
13300 * @type: the simpleType definition
13301 *
13302 * Returns the primitive type of the given type or
13303 * NULL in case of error.
13304 */
13305static xmlSchemaTypePtr
13306xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13307{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013308 if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013309 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013310 while (type != NULL) {
13311 if (type->type == XML_SCHEMA_TYPE_BASIC)
13312 return (type);
13313 type = type->baseType;
13314 }
13315
13316 return (NULL);
13317}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013318#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013319
Daniel Veillard01fa6152004-06-29 17:04:39 +000013320/**
Daniel Veillard50355f02004-06-08 17:52:16 +000013321 * xmlSchemaCloneWildcardNsConstraints:
13322 * @ctxt: the schema parser context
13323 * @dest: the destination wildcard
13324 * @source: the source wildcard
13325 *
13326 * Clones the namespace constraints of source
13327 * and assignes them to dest.
13328 * Returns -1 on internal error, 0 otherwise.
13329 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013330static int
13331xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013332 xmlSchemaWildcardPtr dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013333 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000013334{
13335 xmlSchemaWildcardNsPtr cur, tmp, last;
13336
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013337 if ((source == NULL) || (dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013338 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013339 dest->any = source->any;
Daniel Veillard3646d642004-06-02 19:19:14 +000013340 cur = source->nsSet;
13341 last = NULL;
13342 while (cur != NULL) {
13343 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13344 if (tmp == NULL)
13345 return(-1);
13346 tmp->value = cur->value;
13347 if (last == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013348 dest->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013349 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013350 last->next = tmp;
13351 last = tmp;
13352 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013353 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013354 if (dest->negNsSet != NULL)
13355 xmlSchemaFreeWildcardNsSet(dest->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000013356 if (source->negNsSet != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013357 dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13358 if (dest->negNsSet == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013359 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013360 dest->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000013361 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013362 dest->negNsSet = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000013363 return(0);
13364}
13365
Daniel Veillard50355f02004-06-08 17:52:16 +000013366/**
13367 * xmlSchemaUnionWildcards:
13368 * @ctxt: the schema parser context
13369 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013370 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013371 *
13372 * Unions the namespace constraints of the given wildcards.
13373 * @completeWild will hold the resulting union.
13374 * Returns a positive error code on failure, -1 in case of an
13375 * internal error, 0 otherwise.
13376 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013377static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013378xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000013379 xmlSchemaWildcardPtr completeWild,
13380 xmlSchemaWildcardPtr curWild)
13381{
13382 xmlSchemaWildcardNsPtr cur, curB, tmp;
13383
13384 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013385 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013386 * value.
13387 */
13388 if ((completeWild->any == curWild->any) &&
13389 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13390 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013391
Daniel Veillard3646d642004-06-02 19:19:14 +000013392 if ((completeWild->negNsSet == NULL) ||
13393 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013394
Daniel Veillard3646d642004-06-02 19:19:14 +000013395 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000013396 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013397
13398 /*
13399 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000013400 */
13401 cur = completeWild->nsSet;
13402 while (cur != NULL) {
13403 found = 0;
13404 curB = curWild->nsSet;
13405 while (curB != NULL) {
13406 if (cur->value == curB->value) {
13407 found = 1;
13408 break;
13409 }
13410 curB = curB->next;
13411 }
13412 if (!found)
13413 break;
13414 cur = cur->next;
13415 }
13416 if (found)
13417 return(0);
13418 } else
13419 return(0);
13420 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013421 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013422 /*
13423 * 2 If either O1 or O2 is any, then any must be the value
13424 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013425 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013426 if (completeWild->any == 0) {
13427 completeWild->any = 1;
13428 if (completeWild->nsSet != NULL) {
13429 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13430 completeWild->nsSet = NULL;
13431 }
13432 if (completeWild->negNsSet != NULL) {
13433 xmlFree(completeWild->negNsSet);
13434 completeWild->negNsSet = NULL;
13435 }
13436 }
Daniel Veillard50355f02004-06-08 17:52:16 +000013437 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013438 }
13439 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013440 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000013441 * then the union of those sets must be the value.
13442 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013443 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013444 int found;
13445 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013446
Daniel Veillard3646d642004-06-02 19:19:14 +000013447 cur = curWild->nsSet;
13448 start = completeWild->nsSet;
13449 while (cur != NULL) {
13450 found = 0;
13451 curB = start;
13452 while (curB != NULL) {
13453 if (cur->value == curB->value) {
13454 found = 1;
13455 break;
13456 }
13457 curB = curB->next;
13458 }
13459 if (!found) {
13460 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013461 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013462 return (-1);
13463 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013464 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000013465 completeWild->nsSet = tmp;
13466 }
13467 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013468 }
13469
Daniel Veillard3646d642004-06-02 19:19:14 +000013470 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013471 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013472 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013473 * 4 If the two are negations of different values (namespace names
Daniel Veillard3646d642004-06-02 19:19:14 +000013474 * or ·absent·), then a pair of not and ·absent· must be the value.
13475 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013476 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013477 (curWild->negNsSet != NULL) &&
13478 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
13479 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000013480
13481 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013482 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013483 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013484 * 5.
13485 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013486 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013487 (completeWild->negNsSet->value != NULL) &&
13488 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013489 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013490 (curWild->negNsSet->value != NULL) &&
13491 (completeWild->nsSet != NULL))) {
13492
13493 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013494
Daniel Veillard3646d642004-06-02 19:19:14 +000013495 if (completeWild->nsSet != NULL) {
13496 cur = completeWild->nsSet;
13497 curB = curWild->negNsSet;
13498 } else {
13499 cur = curWild->nsSet;
13500 curB = completeWild->negNsSet;
13501 }
13502 nsFound = 0;
13503 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013504 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013505 absentFound = 1;
13506 else if (cur->value == curB->value)
13507 nsFound = 1;
13508 if (nsFound && absentFound)
13509 break;
13510 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013511 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013512
13513 if (nsFound && absentFound) {
13514 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013515 * 5.1 If the set S includes both the negated namespace
Daniel Veillard3646d642004-06-02 19:19:14 +000013516 * name and ·absent·, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013517 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013518 completeWild->any = 1;
13519 if (completeWild->nsSet != NULL) {
13520 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13521 completeWild->nsSet = NULL;
13522 }
13523 if (completeWild->negNsSet != NULL) {
13524 xmlFree(completeWild->negNsSet);
13525 completeWild->negNsSet = NULL;
13526 }
13527 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013528 /*
13529 * 5.2 If the set S includes the negated namespace name
13530 * but not ·absent·, then a pair of not and ·absent· must
Daniel Veillard3646d642004-06-02 19:19:14 +000013531 * be the value.
13532 */
13533 if (completeWild->nsSet != NULL) {
13534 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13535 completeWild->nsSet = NULL;
13536 }
13537 if (completeWild->negNsSet == NULL) {
13538 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13539 if (completeWild->negNsSet == NULL)
13540 return (-1);
13541 }
13542 completeWild->negNsSet->value = NULL;
13543 } else if ((!nsFound) && absentFound) {
13544 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013545 * 5.3 If the set S includes ·absent· but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000013546 * namespace name, then the union is not expressible.
13547 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013548 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000013549 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013550 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013551 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000013552 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000013553 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013554 /*
13555 * 5.4 If the set S does not include either the negated namespace
13556 * name or ·absent·, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000013557 * and a namespace name must be the value.
13558 */
13559 if (completeWild->negNsSet == NULL) {
13560 if (completeWild->nsSet != NULL) {
13561 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13562 completeWild->nsSet = NULL;
13563 }
13564 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13565 if (completeWild->negNsSet == NULL)
13566 return (-1);
13567 completeWild->negNsSet->value = curWild->negNsSet->value;
13568 }
13569 }
13570 return (0);
13571 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013572 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013573 * 6.
13574 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013575 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013576 (completeWild->negNsSet->value == NULL) &&
13577 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013578 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013579 (curWild->negNsSet->value == NULL) &&
13580 (completeWild->nsSet != NULL))) {
13581
13582 if (completeWild->nsSet != NULL) {
13583 cur = completeWild->nsSet;
13584 } else {
13585 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013586 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013587 while (cur != NULL) {
13588 if (cur->value == NULL) {
13589 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013590 * 6.1 If the set S includes ·absent·, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013591 * value.
13592 */
13593 completeWild->any = 1;
13594 if (completeWild->nsSet != NULL) {
13595 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13596 completeWild->nsSet = NULL;
13597 }
13598 if (completeWild->negNsSet != NULL) {
13599 xmlFree(completeWild->negNsSet);
13600 completeWild->negNsSet = NULL;
13601 }
13602 return (0);
13603 }
13604 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013605 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013606 if (completeWild->negNsSet == NULL) {
13607 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013608 * 6.2 If the set S does not include ·absent·, then a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000013609 * and ·absent· must be the value.
13610 */
13611 if (completeWild->nsSet != NULL) {
13612 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13613 completeWild->nsSet = NULL;
13614 }
13615 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13616 if (completeWild->negNsSet == NULL)
13617 return (-1);
13618 completeWild->negNsSet->value = NULL;
13619 }
13620 return (0);
13621 }
13622 return (0);
13623
13624}
13625
Daniel Veillard50355f02004-06-08 17:52:16 +000013626/**
13627 * xmlSchemaIntersectWildcards:
13628 * @ctxt: the schema parser context
13629 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013630 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013631 *
13632 * Intersects the namespace constraints of the given wildcards.
13633 * @completeWild will hold the resulting intersection.
13634 * Returns a positive error code on failure, -1 in case of an
13635 * internal error, 0 otherwise.
13636 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013637static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013638xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000013639 xmlSchemaWildcardPtr completeWild,
13640 xmlSchemaWildcardPtr curWild)
13641{
William M. Brack803812b2004-06-03 02:11:24 +000013642 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013643
13644 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013645 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013646 * value.
13647 */
13648 if ((completeWild->any == curWild->any) &&
13649 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13650 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013651
Daniel Veillard3646d642004-06-02 19:19:14 +000013652 if ((completeWild->negNsSet == NULL) ||
13653 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013654
Daniel Veillard3646d642004-06-02 19:19:14 +000013655 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000013656 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013657
13658 /*
13659 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000013660 */
13661 cur = completeWild->nsSet;
13662 while (cur != NULL) {
13663 found = 0;
13664 curB = curWild->nsSet;
13665 while (curB != NULL) {
13666 if (cur->value == curB->value) {
13667 found = 1;
13668 break;
13669 }
13670 curB = curB->next;
13671 }
13672 if (!found)
13673 break;
13674 cur = cur->next;
13675 }
13676 if (found)
13677 return(0);
13678 } else
13679 return(0);
13680 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013681 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013682 /*
13683 * 2 If either O1 or O2 is any, then the other must be the value.
13684 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013685 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013686 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013687 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000013688 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013689 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013690 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013691 * 3 If either O1 or O2 is a pair of not and a value (a namespace
13692 * name or ·absent·) and the other is a set of (namespace names or
13693 * ·absent·), then that set, minus the negated value if it was in
Daniel Veillard3646d642004-06-02 19:19:14 +000013694 * the set, minus ·absent· if it was in the set, must be the value.
13695 */
13696 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13697 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13698 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013699
Daniel Veillard3646d642004-06-02 19:19:14 +000013700 if (completeWild->nsSet == NULL) {
13701 neg = completeWild->negNsSet->value;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013702 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
Daniel Veillard3646d642004-06-02 19:19:14 +000013703 return(-1);
13704 } else
13705 neg = curWild->negNsSet->value;
13706 /*
13707 * Remove absent and negated.
13708 */
13709 prev = NULL;
13710 cur = completeWild->nsSet;
13711 while (cur != NULL) {
13712 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013713 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013714 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013715 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013716 prev->next = cur->next;
13717 xmlFree(cur);
13718 break;
13719 }
13720 prev = cur;
13721 cur = cur->next;
13722 }
13723 if (neg != NULL) {
13724 prev = NULL;
13725 cur = completeWild->nsSet;
13726 while (cur != NULL) {
13727 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013728 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013729 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013730 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013731 prev->next = cur->next;
13732 xmlFree(cur);
13733 break;
13734 }
13735 prev = cur;
13736 cur = cur->next;
13737 }
13738 }
13739
13740 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013741 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013742 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013743 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000013744 * then the intersection of those sets must be the value.
13745 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013746 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013747 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013748
Daniel Veillard3646d642004-06-02 19:19:14 +000013749 cur = completeWild->nsSet;
13750 prev = NULL;
13751 while (cur != NULL) {
13752 found = 0;
13753 curB = curWild->nsSet;
13754 while (curB != NULL) {
13755 if (cur->value == curB->value) {
13756 found = 1;
13757 break;
13758 }
13759 curB = curB->next;
13760 }
13761 if (!found) {
13762 if (prev == NULL)
13763 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013764 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013765 prev->next = cur->next;
13766 tmp = cur->next;
13767 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013768 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013769 continue;
13770 }
13771 prev = cur;
13772 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013773 }
13774
Daniel Veillard3646d642004-06-02 19:19:14 +000013775 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013776 }
13777 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000013778 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013779 */
13780 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013781 (curWild->negNsSet != NULL) &&
13782 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013783 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013784 (curWild->negNsSet->value != NULL)) {
13785
13786 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013787 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013788 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000013789 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013790 }
13791 /*
13792 * 6 If the one is a negation of a namespace name and the other
13793 * is a negation of ·absent·, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000013794 * of a namespace name must be the value.
13795 */
13796 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13797 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013798 (completeWild->negNsSet->value == NULL)) {
13799 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000013800 }
13801 return(0);
13802}
13803
Daniel Veillard50355f02004-06-08 17:52:16 +000013804/**
13805 * xmlSchemaIsWildcardNsConstraintSubset:
13806 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013807 * @sub: the first wildcard
13808 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013809 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013810 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13811 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013812 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013813 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000013814 */
13815static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013816xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13817 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013818{
Daniel Veillard50355f02004-06-08 17:52:16 +000013819 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013820 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000013821 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013822 if (super->any)
13823 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000013824 /*
13825 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
13826 * 2.2 super must be a pair of not and the same value.
13827 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013828 if ((sub->negNsSet != NULL) &&
13829 (super->negNsSet != NULL) &&
13830 (sub->negNsSet->value == sub->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013831 return (0);
13832 /*
13833 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
Daniel Veillard50355f02004-06-08 17:52:16 +000013834 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013835 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013836 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013837 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000013838 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013839 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013840 xmlSchemaWildcardNsPtr cur, curB;
13841 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013842
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013843 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000013844 while (cur != NULL) {
13845 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013846 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000013847 while (curB != NULL) {
13848 if (cur->value == curB->value) {
13849 found = 1;
13850 break;
13851 }
13852 curB = curB->next;
13853 }
13854 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013855 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013856 cur = cur->next;
13857 }
13858 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013859 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013860 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013861 xmlSchemaWildcardNsPtr cur;
13862 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013863 * 3.2.2 super must be a pair of not and a namespace name or
13864 * ·absent· and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000013865 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013866 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013867 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013868 if (cur->value == super->negNsSet->value)
13869 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013870 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013871 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013872 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000013873 }
13874 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013875 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013876}
13877
Daniel Veillard50355f02004-06-08 17:52:16 +000013878static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013879xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013880 int *fixed,
13881 const xmlChar **value,
13882 xmlSchemaValPtr *val)
13883{
13884 *fixed = 0;
13885 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013886 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013887 *val = NULL;
13888
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013889 if (attruse->defValue != NULL) {
13890 *value = attruse->defValue;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000013891 if (val != NULL)
13892 *val = attruse->defVal;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013893 if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013894 *fixed = 1;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013895 return(1);
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000013896 } else if ((attruse->attrDecl != NULL) &&
13897 (attruse->attrDecl->defValue != NULL)) {
13898 *value = attruse->attrDecl->defValue;
13899 if (val != NULL)
13900 *val = attruse->attrDecl->defVal;
13901 if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013902 *fixed = 1;
13903 return(1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013904 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013905 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013906}
Daniel Veillard3646d642004-06-02 19:19:14 +000013907/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013908 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000013909 * @wild: the wildcard
13910 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013911 *
13912 * Validation Rule: Wildcard allows Namespace Name
13913 * (cvc-wildcard-namespace)
13914 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013915 * Returns 0 if the given namespace matches the wildcard,
13916 * 1 otherwise and -1 on API errors.
Daniel Veillard3646d642004-06-02 19:19:14 +000013917 */
13918static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013919xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
13920 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000013921{
13922 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013923 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000013924
13925 if (wild->any)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013926 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013927 else if (wild->nsSet != NULL) {
13928 xmlSchemaWildcardNsPtr cur;
13929
13930 cur = wild->nsSet;
13931 while (cur != NULL) {
13932 if (xmlStrEqual(cur->value, ns))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013933 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013934 cur = cur->next;
13935 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013936 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013937 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013938 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013939
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013940 return(1);
13941}
13942
13943#define XML_SCHEMA_ACTION_DERIVE 0
13944#define XML_SCHEMA_ACTION_REDEFINE 1
13945
13946#define WXS_ACTION_STR(a) \
13947((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
13948
13949/*
13950* Schema Component Constraint:
13951* Derivation Valid (Restriction, Complex)
13952* derivation-ok-restriction (2) - (4)
13953*
13954* ATTENTION:
13955* In XML Schema 1.1 this will be:
13956* Validation Rule:
13957* Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
13958*
13959*/
13960static int
13961xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
13962 int action,
13963 xmlSchemaBasicItemPtr item,
13964 xmlSchemaBasicItemPtr baseItem,
13965 xmlSchemaItemListPtr uses,
13966 xmlSchemaItemListPtr baseUses,
13967 xmlSchemaWildcardPtr wild,
13968 xmlSchemaWildcardPtr baseWild)
13969{
13970 xmlSchemaAttributeUsePtr cur = NULL, bcur;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000013971 int i, j, found; /* err = 0; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013972 const xmlChar *bEffValue;
13973 int effFixed;
13974
13975 if (uses != NULL) {
13976 for (i = 0; i < uses->nbItems; i++) {
13977 cur = uses->items[i];
13978 found = 0;
13979 if (baseUses == NULL)
13980 goto not_found;
13981 for (j = 0; j < baseUses->nbItems; j++) {
13982 bcur = baseUses->items[j];
13983 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
13984 WXS_ATTRUSE_DECL_NAME(bcur)) &&
13985 (WXS_ATTRUSE_DECL_TNS(cur) ==
13986 WXS_ATTRUSE_DECL_TNS(bcur)))
13987 {
13988 /*
13989 * (2.1) "If there is an attribute use in the {attribute
13990 * uses} of the {base type definition} (call this B) whose
13991 * {attribute declaration} has the same {name} and {target
13992 * namespace}, then all of the following must be true:"
13993 */
13994 found = 1;
13995
13996 if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
13997 (bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
13998 {
13999 xmlChar *str = NULL;
14000 /*
14001 * (2.1.1) "one of the following must be true:"
14002 * (2.1.1.1) "B's {required} is false."
14003 * (2.1.1.2) "R's {required} is true."
14004 */
14005 xmlSchemaPAttrUseErr4(pctxt,
14006 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14007 WXS_ITEM_NODE(item), item, cur,
14008 "The 'optional' attribute use is inconsistent "
14009 "with the corresponding 'required' attribute use of "
14010 "the %s %s",
14011 WXS_ACTION_STR(action),
14012 xmlSchemaGetComponentDesignation(&str, baseItem),
14013 NULL, NULL);
14014 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014015 /* err = pctxt->err; */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014016 } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014017 WXS_ATTRUSE_TYPEDEF(cur),
14018 WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14019 {
14020 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14021
14022 /*
14023 * SPEC (2.1.2) "R's {attribute declaration}'s
14024 * {type definition} must be validly derived from
14025 * B's {type definition} given the empty set as
14026 * defined in Type Derivation OK (Simple) (§3.14.6)."
14027 */
14028 xmlSchemaPAttrUseErr4(pctxt,
14029 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14030 WXS_ITEM_NODE(item), item, cur,
14031 "The attribute declaration's %s "
14032 "is not validly derived from "
14033 "the corresponding %s of the "
14034 "attribute declaration in the %s %s",
14035 xmlSchemaGetComponentDesignation(&strA,
14036 WXS_ATTRUSE_TYPEDEF(cur)),
14037 xmlSchemaGetComponentDesignation(&strB,
14038 WXS_ATTRUSE_TYPEDEF(bcur)),
14039 WXS_ACTION_STR(action),
14040 xmlSchemaGetComponentDesignation(&strC, baseItem));
14041 /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14042 FREE_AND_NULL(strA);
14043 FREE_AND_NULL(strB);
14044 FREE_AND_NULL(strC);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014045 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014046 } else {
14047 /*
14048 * 2.1.3 [Definition:] Let the effective value
14049 * constraint of an attribute use be its {value
14050 * constraint}, if present, otherwise its {attribute
14051 * declaration}'s {value constraint} .
14052 */
14053 xmlSchemaGetEffectiveValueConstraint(bcur,
14054 &effFixed, &bEffValue, NULL);
14055 /*
14056 * 2.1.3 ... one of the following must be true
14057 *
14058 * 2.1.3.1 B's ·effective value constraint· is
14059 * ·absent· or default.
14060 */
14061 if ((bEffValue != NULL) &&
14062 (effFixed == 1)) {
14063 const xmlChar *rEffValue = NULL;
14064
14065 xmlSchemaGetEffectiveValueConstraint(bcur,
14066 &effFixed, &rEffValue, NULL);
14067 /*
14068 * 2.1.3.2 R's ·effective value constraint· is
14069 * fixed with the same string as B's.
14070 * MAYBE TODO: Compare the computed values.
14071 * Hmm, it says "same string" so
14072 * string-equality might really be sufficient.
14073 */
14074 if ((effFixed == 0) ||
14075 (! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14076 {
14077 xmlChar *str = NULL;
14078
14079 xmlSchemaPAttrUseErr4(pctxt,
14080 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14081 WXS_ITEM_NODE(item), item, cur,
14082 "The effective value constraint of the "
14083 "attribute use is inconsistent with "
14084 "its correspondent in the %s %s",
14085 WXS_ACTION_STR(action),
14086 xmlSchemaGetComponentDesignation(&str,
14087 baseItem),
14088 NULL, NULL);
14089 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014090 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014091 }
14092 }
14093 }
14094 break;
14095 }
14096 }
14097not_found:
14098 if (!found) {
14099 /*
14100 * (2.2) "otherwise the {base type definition} must have an
14101 * {attribute wildcard} and the {target namespace} of the
14102 * R's {attribute declaration} must be ·valid· with respect
14103 * to that wildcard, as defined in Wildcard allows Namespace
14104 * Name (§3.10.4)."
14105 */
14106 if ((baseWild == NULL) ||
14107 (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14108 (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14109 {
14110 xmlChar *str = NULL;
14111
14112 xmlSchemaPAttrUseErr4(pctxt,
14113 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14114 WXS_ITEM_NODE(item), item, cur,
14115 "Neither a matching attribute use, "
14116 "nor a matching wildcard exists in the %s %s",
14117 WXS_ACTION_STR(action),
14118 xmlSchemaGetComponentDesignation(&str, baseItem),
14119 NULL, NULL);
14120 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014121 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014122 }
14123 }
14124 }
14125 }
14126 /*
14127 * SPEC derivation-ok-restriction (3):
14128 * (3) "For each attribute use in the {attribute uses} of the {base type
14129 * definition} whose {required} is true, there must be an attribute
14130 * use with an {attribute declaration} with the same {name} and
14131 * {target namespace} as its {attribute declaration} in the {attribute
14132 * uses} of the complex type definition itself whose {required} is true.
14133 */
14134 if (baseUses != NULL) {
14135 for (j = 0; j < baseUses->nbItems; j++) {
14136 bcur = baseUses->items[j];
14137 if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14138 continue;
14139 found = 0;
14140 if (uses != NULL) {
14141 for (i = 0; i < uses->nbItems; i++) {
14142 cur = uses->items[i];
14143 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14144 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14145 (WXS_ATTRUSE_DECL_TNS(cur) ==
14146 WXS_ATTRUSE_DECL_TNS(bcur))) {
14147 found = 1;
14148 break;
14149 }
14150 }
14151 }
14152 if (!found) {
14153 xmlChar *strA = NULL, *strB = NULL;
14154
14155 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14156 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14157 NULL, item,
14158 "A matching attribute use for the "
14159 "'required' %s of the %s %s is missing",
14160 xmlSchemaGetComponentDesignation(&strA, bcur),
14161 WXS_ACTION_STR(action),
14162 xmlSchemaGetComponentDesignation(&strB, baseItem),
14163 NULL);
14164 FREE_AND_NULL(strA);
14165 FREE_AND_NULL(strB);
14166 }
14167 }
14168 }
14169 /*
14170 * derivation-ok-restriction (4)
14171 */
14172 if (wild != NULL) {
14173 /*
14174 * (4) "If there is an {attribute wildcard}, all of the
14175 * following must be true:"
14176 */
14177 if (baseWild == NULL) {
14178 xmlChar *str = NULL;
14179
14180 /*
14181 * (4.1) "The {base type definition} must also have one."
14182 */
14183 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14184 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14185 NULL, item,
14186 "The %s has an attribute wildcard, "
14187 "but the %s %s '%s' does not have one",
14188 WXS_ITEM_TYPE_NAME(item),
14189 WXS_ACTION_STR(action),
14190 WXS_ITEM_TYPE_NAME(baseItem),
14191 xmlSchemaGetComponentQName(&str, baseItem));
14192 FREE_AND_NULL(str);
14193 return(pctxt->err);
14194 } else if ((baseWild->any == 0) &&
14195 xmlSchemaCheckCOSNSSubset(wild, baseWild))
14196 {
14197 xmlChar *str = NULL;
14198 /*
14199 * (4.2) "The complex type definition's {attribute wildcard}'s
14200 * {namespace constraint} must be a subset of the {base type
14201 * definition}'s {attribute wildcard}'s {namespace constraint},
14202 * as defined by Wildcard Subset (§3.10.6)."
14203 */
14204 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14205 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14206 NULL, item,
14207 "The attribute wildcard is not a valid "
14208 "subset of the wildcard in the %s %s '%s'",
14209 WXS_ACTION_STR(action),
14210 WXS_ITEM_TYPE_NAME(baseItem),
14211 xmlSchemaGetComponentQName(&str, baseItem),
14212 NULL);
14213 FREE_AND_NULL(str);
14214 return(pctxt->err);
14215 }
14216 /* 4.3 Unless the {base type definition} is the ·ur-type
14217 * definition·, the complex type definition's {attribute
14218 * wildcard}'s {process contents} must be identical to or
14219 * stronger than the {base type definition}'s {attribute
14220 * wildcard}'s {process contents}, where strict is stronger
14221 * than lax is stronger than skip.
14222 */
14223 if ((! WXS_IS_ANYTYPE(baseItem)) &&
14224 (wild->processContents < baseWild->processContents)) {
14225 xmlChar *str = NULL;
14226 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14227 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14228 NULL, baseItem,
14229 "The {process contents} of the attribute wildcard is "
14230 "weaker than the one in the %s %s '%s'",
14231 WXS_ACTION_STR(action),
14232 WXS_ITEM_TYPE_NAME(baseItem),
14233 xmlSchemaGetComponentQName(&str, baseItem),
14234 NULL);
14235 FREE_AND_NULL(str)
14236 return(pctxt->err);
14237 }
14238 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014239 return(0);
14240}
14241
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014242
14243static int
14244xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14245 xmlSchemaBasicItemPtr item,
14246 xmlSchemaWildcardPtr *completeWild,
14247 xmlSchemaItemListPtr list,
14248 xmlSchemaItemListPtr prohibs);
Daniel Veillard3646d642004-06-02 19:19:14 +000014249/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014250 * xmlSchemaFixupTypeAttributeUses:
Daniel Veillard3646d642004-06-02 19:19:14 +000014251 * @ctxt: the schema parser context
14252 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014253 *
Daniel Veillard3646d642004-06-02 19:19:14 +000014254 *
14255 * Builds the wildcard and the attribute uses on the given complex type.
14256 * Returns -1 if an internal error occurs, 0 otherwise.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014257 *
14258 * ATTENTION TODO: Experimantally this uses pointer comparisons for
14259 * strings, so recheck this if we start to hardcode some schemata, since
14260 * they might not be in the same dict.
14261 * NOTE: It is allowed to "extend" the xs:anyType type.
Daniel Veillard3646d642004-06-02 19:19:14 +000014262 */
14263static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014264xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014265 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000014266{
14267 xmlSchemaTypePtr baseType = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014268 xmlSchemaAttributeUsePtr use;
14269 xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000014270
Daniel Veillard01fa6152004-06-29 17:04:39 +000014271 if (type->baseType == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014272 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014273 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014274 return (-1);
14275 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014276 baseType = type->baseType;
14277 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014278 if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014279 return(-1);
14280
14281 uses = type->attrUses;
14282 baseUses = baseType->attrUses;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014283 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014284 * Expand attribute group references. And build the 'complete'
14285 * wildcard, i.e. intersect multiple wildcards.
14286 * Move attribute prohibitions into a separate list.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014287 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014288 if (uses != NULL) {
14289 if (WXS_IS_RESTRICTION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014290 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014291 * This one will transfer all attr. prohibitions
14292 * into pctxt->attrProhibs.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014293 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014294 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14295 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14296 pctxt->attrProhibs) == -1)
14297 {
14298 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14299 "failed to expand attributes");
14300 }
14301 if (pctxt->attrProhibs->nbItems != 0)
14302 prohibs = pctxt->attrProhibs;
14303 } else {
14304 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14305 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14306 NULL) == -1)
14307 {
14308 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14309 "failed to expand attributes");
14310 }
14311 }
14312 }
14313 /*
14314 * Inherit the attribute uses of the base type.
14315 */
14316 if (baseUses != NULL) {
14317 int i, j;
14318 xmlSchemaAttributeUseProhibPtr pro;
14319
14320 if (WXS_IS_RESTRICTION(type)) {
14321 int usesCount;
14322 xmlSchemaAttributeUsePtr tmp;
14323
14324 if (uses != NULL)
14325 usesCount = uses->nbItems;
14326 else
14327 usesCount = 0;
14328
14329 /* Restriction. */
14330 for (i = 0; i < baseUses->nbItems; i++) {
14331 use = baseUses->items[i];
14332 if (prohibs) {
14333 /*
14334 * Filter out prohibited uses.
14335 */
14336 for (j = 0; j < prohibs->nbItems; j++) {
14337 pro = prohibs->items[j];
14338 if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14339 (WXS_ATTRUSE_DECL_TNS(use) ==
14340 pro->targetNamespace))
14341 {
14342 goto inherit_next;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014343 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014344 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014345 }
14346 if (usesCount) {
14347 /*
14348 * Filter out existing uses.
14349 */
14350 for (j = 0; j < usesCount; j++) {
14351 tmp = uses->items[j];
14352 if ((WXS_ATTRUSE_DECL_NAME(use) ==
14353 WXS_ATTRUSE_DECL_NAME(tmp)) &&
14354 (WXS_ATTRUSE_DECL_TNS(use) ==
14355 WXS_ATTRUSE_DECL_TNS(tmp)))
14356 {
14357 goto inherit_next;
14358 }
14359 }
14360 }
14361 if (uses == NULL) {
14362 type->attrUses = xmlSchemaItemListCreate();
14363 if (type->attrUses == NULL)
14364 goto exit_failure;
14365 uses = type->attrUses;
14366 }
14367 xmlSchemaItemListAddSize(uses, 2, use);
14368inherit_next: {}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014369 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014370 } else {
14371 /* Extension. */
14372 for (i = 0; i < baseUses->nbItems; i++) {
14373 use = baseUses->items[i];
14374 if (uses == NULL) {
14375 type->attrUses = xmlSchemaItemListCreate();
14376 if (type->attrUses == NULL)
14377 goto exit_failure;
14378 uses = type->attrUses;
14379 }
14380 xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14381 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014382 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014383 }
14384 /*
14385 * Shrink attr. uses.
14386 */
14387 if (uses) {
14388 if (uses->nbItems == 0) {
14389 xmlSchemaItemListFree(uses);
14390 type->attrUses = NULL;
14391 }
14392 /*
14393 * TODO: We could shrink the size of the array
14394 * to fit the actual number of items.
14395 */
14396 }
14397 /*
14398 * Compute the complete wildcard.
14399 */
14400 if (WXS_IS_EXTENSION(type)) {
14401 if (baseType->attributeWildcard != NULL) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014402 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014403 * (3.2.2.1) "If the ·base wildcard· is non-·absent·, then
14404 * the appropriate case among the following:"
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014405 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014406 if (type->attributeWildcard != NULL) {
14407 /*
14408 * Union the complete wildcard with the base wildcard.
14409 * SPEC {attribute wildcard}
14410 * (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14411 * and {annotation} are those of the ·complete wildcard·,
14412 * and whose {namespace constraint} is the intensional union
14413 * of the {namespace constraint} of the ·complete wildcard·
14414 * and of the ·base wildcard·, as defined in Attribute
14415 * Wildcard Union (§3.10.6)."
14416 */
14417 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14418 baseType->attributeWildcard) == -1)
14419 goto exit_failure;
14420 } else {
14421 /*
14422 * (3.2.2.1.1) "If the ·complete wildcard· is ·absent·,
14423 * then the ·base wildcard·."
14424 */
14425 type->attributeWildcard = baseType->attributeWildcard;
14426 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014427 } else {
14428 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014429 * (3.2.2.2) "otherwise (the ·base wildcard· is ·absent·) the
14430 * ·complete wildcard"
14431 * NOOP
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014432 */
Daniel Veillard50355f02004-06-08 17:52:16 +000014433 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014434 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014435 /*
14436 * SPEC {attribute wildcard}
14437 * (3.1) "If the <restriction> alternative is chosen, then the
14438 * ·complete wildcard·;"
14439 * NOOP
14440 */
Daniel Veillard50355f02004-06-08 17:52:16 +000014441 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014442
Daniel Veillard3646d642004-06-02 19:19:14 +000014443 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014444
14445exit_failure:
14446 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000014447}
14448
14449/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000014450 * xmlSchemaTypeFinalContains:
14451 * @schema: the schema
14452 * @type: the type definition
14453 * @final: the final
14454 *
14455 * Evaluates if a type definition contains the given "final".
14456 * This does take "finalDefault" into account as well.
14457 *
14458 * Returns 1 if the type does containt the given "final",
14459 * 0 otherwise.
14460 */
14461static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014462xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014463{
Daniel Veillard01fa6152004-06-29 17:04:39 +000014464 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014465 return (0);
14466 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014467 return (1);
14468 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014469 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014470}
14471
14472/**
14473 * xmlSchemaGetUnionSimpleTypeMemberTypes:
14474 * @type: the Union Simple Type
14475 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014476 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014477 * returns NULL otherwise.
14478 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014479static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000014480xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14481{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014482 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014483 if (type->memberTypes != NULL)
14484 return (type->memberTypes);
14485 else
14486 type = type->baseType;
14487 }
14488 return (NULL);
14489}
14490
14491/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014492 * xmlSchemaGetParticleTotalRangeMin:
14493 * @particle: the particle
14494 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014495 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014496 * (all and sequence) + (choice)
14497 *
14498 * Returns the minimun Effective Total Range.
14499 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014500static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014501xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014502{
14503 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014504 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014505 return (0);
14506 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014507 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014508 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014509 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014510
14511 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014512 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014513 while (part != NULL) {
14514 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14515 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014516 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014517 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014518 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014519 if (cur == 0)
14520 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014521 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014522 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014523 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014524 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014525 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014526 } else {
14527 /* <all> and <sequence> */
14528 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014529 xmlSchemaParticlePtr part =
14530 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014531
14532 if (part == NULL)
14533 return (0);
14534 do {
14535 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14536 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014537 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014538 else
14539 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014540 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014541 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014542 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014543 }
14544}
14545
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014546/**
14547 * xmlSchemaGetParticleTotalRangeMax:
14548 * @particle: the particle
14549 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014550 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014551 * (all and sequence) + (choice)
14552 *
14553 * Returns the maximum Effective Total Range.
14554 */
14555static int
14556xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14557{
14558 if ((particle->children == NULL) ||
14559 (particle->children->children == NULL))
14560 return (0);
14561 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14562 int max = -1, cur;
14563 xmlSchemaParticlePtr part =
14564 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014565
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014566 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14567 if (part->children == NULL)
14568 continue;
14569 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14570 (part->children->type == XML_SCHEMA_TYPE_ANY))
14571 cur = part->maxOccurs;
14572 else
14573 cur = xmlSchemaGetParticleTotalRangeMax(part);
14574 if (cur == UNBOUNDED)
14575 return (UNBOUNDED);
14576 if ((max < cur) || (max == -1))
14577 max = cur;
14578 }
14579 /* TODO: Handle overflows? */
14580 return (particle->maxOccurs * max);
14581 } else {
14582 /* <all> and <sequence> */
14583 int sum = 0, cur;
14584 xmlSchemaParticlePtr part =
14585 (xmlSchemaParticlePtr) particle->children->children;
14586
14587 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14588 if (part->children == NULL)
14589 continue;
14590 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14591 (part->children->type == XML_SCHEMA_TYPE_ANY))
14592 cur = part->maxOccurs;
14593 else
14594 cur = xmlSchemaGetParticleTotalRangeMax(part);
14595 if (cur == UNBOUNDED)
14596 return (UNBOUNDED);
14597 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14598 return (UNBOUNDED);
14599 sum += cur;
14600 }
14601 /* TODO: Handle overflows? */
14602 return (particle->maxOccurs * sum);
14603 }
14604}
14605
14606/**
14607 * xmlSchemaIsParticleEmptiable:
14608 * @particle: the particle
14609 *
14610 * Schema Component Constraint: Particle Emptiable
14611 * Checks whether the given particle is emptiable.
14612 *
14613 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014614 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014615static int
14616xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14617{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014618 /*
14619 * SPEC (1) "Its {min occurs} is 0."
14620 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014621 if ((particle == NULL) || (particle->minOccurs == 0) ||
14622 (particle->children == NULL))
14623 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014624 /*
14625 * SPEC (2) "Its {term} is a group and the minimum part of the
14626 * effective total range of that group, [...] is 0."
14627 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014628 if (WXS_IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014629 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014630 return (1);
14631 }
14632 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014633}
14634
14635/**
14636 * xmlSchemaCheckCOSSTDerivedOK:
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014637 * @actxt: a context
Daniel Veillard01fa6152004-06-29 17:04:39 +000014638 * @type: the derived simple type definition
14639 * @baseType: the base type definition
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014640 * @subset: the subset of ('restriction', ect.)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014641 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014642 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014643 * Type Derivation OK (Simple) (cos-st-derived-OK)
14644 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014645 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000014646 * derived from @baseType.
14647 *
14648 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014649 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014650static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014651xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014652 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014653 xmlSchemaTypePtr baseType,
14654 int subset)
14655{
Daniel Veillard01fa6152004-06-29 17:04:39 +000014656 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014657 * 1 They are the same type definition.
14658 * TODO: The identy check might have to be more complex than this.
14659 */
14660 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014661 return (0);
14662 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014663 * 2.1 restriction is not in the subset, or in the {final}
14664 * of its own {base type definition};
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014665 *
14666 * NOTE that this will be used also via "xsi:type".
14667 *
14668 * TODO: Revise this, it looks strange. How can the "type"
14669 * not be fixed or *in* fixing?
Daniel Veillard01fa6152004-06-29 17:04:39 +000014670 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014671 if (WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014672 if (xmlSchemaTypeFixup(type, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014673 return(-1);
14674 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014675 if (xmlSchemaTypeFixup(baseType, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014676 return(-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014677 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014678 (xmlSchemaTypeFinalContains(type->baseType,
14679 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14680 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014681 }
14682 /* 2.2 */
14683 if (type->baseType == baseType) {
14684 /*
14685 * 2.2.1 D's ·base type definition· is B.
14686 */
14687 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014688 }
14689 /*
14690 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
14691 * and is validly derived from B given the subset, as defined by this
14692 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014693 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014694 if ((! WXS_IS_ANYTYPE(type->baseType)) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014695 (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014696 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014697 return (0);
14698 }
14699 /*
14700 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
Daniel Veillard01fa6152004-06-29 17:04:39 +000014701 * definition·.
14702 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014703 if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14704 (WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014705 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014706 }
14707 /*
14708 * 2.2.4 B's {variety} is union and D is validly derived from a type
14709 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000014710 * defined by this constraint.
14711 *
14712 * NOTE: This seems not to involve built-in types, since there is no
14713 * built-in Union Simple Type.
14714 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014715 if (WXS_IS_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014716 xmlSchemaTypeLinkPtr cur;
14717
14718 cur = baseType->memberTypes;
14719 while (cur != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014720 if (WXS_IS_TYPE_NOT_FIXED(cur->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014721 if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014722 return(-1);
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014723 if (xmlSchemaCheckCOSSTDerivedOK(actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014724 type, cur->type, subset) == 0)
14725 {
14726 /*
14727 * It just has to be validly derived from at least one
14728 * member-type.
14729 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014730 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014731 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014732 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014733 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014734 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014735 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14736}
14737
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014738/**
14739 * xmlSchemaCheckTypeDefCircularInternal:
14740 * @pctxt: the schema parser context
14741 * @ctxtType: the type definition
14742 * @ancestor: an ancestor of @ctxtType
14743 *
14744 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014745 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014746 *
14747 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14748 * circular, 0 otherwise.
14749 */
14750static int
14751xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14752 xmlSchemaTypePtr ctxtType,
14753 xmlSchemaTypePtr ancestor)
14754{
14755 int ret;
14756
14757 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14758 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014759
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014760 if (ctxtType == ancestor) {
14761 xmlSchemaPCustomErr(pctxt,
14762 XML_SCHEMAP_ST_PROPS_CORRECT_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014763 WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014764 "The definition is circular", NULL);
14765 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14766 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014767 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14768 /*
14769 * Avoid inifinite recursion on circular types not yet checked.
14770 */
14771 return (0);
14772 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014773 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14774 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14775 ancestor->baseType);
14776 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14777 return (ret);
14778}
14779
14780/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014781 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014782 * @item: the complex/simple type definition
14783 * @ctxt: the parser context
14784 * @name: the name
14785 *
14786 * Checks for circular type definitions.
14787 */
14788static void
14789xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014790 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014791{
14792 if ((item == NULL) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014793 (item->type == XML_SCHEMA_TYPE_BASIC) ||
14794 (item->baseType == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014795 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014796 xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14797 item->baseType);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014798}
Daniel Veillard01fa6152004-06-29 17:04:39 +000014799
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014800/*
14801* Simple Type Definition Representation OK (src-simple-type) 4
14802*
14803* "4 Circular union type definition is disallowed. That is, if the
14804* <union> alternative is chosen, there must not be any entries in the
14805* memberTypes [attribute] at any depth which resolve to the component
14806* corresponding to the <simpleType>."
14807*
14808* Note that this should work on the *representation* of a component,
14809* thus assumes any union types in the member types not being yet
14810* substituted. At this stage we need the variety of the types
14811* to be already computed.
14812*/
14813static int
14814xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14815 xmlSchemaTypePtr ctxType,
14816 xmlSchemaTypeLinkPtr members)
14817{
14818 xmlSchemaTypeLinkPtr member;
14819 xmlSchemaTypePtr memberType;
14820
14821 member = members;
14822 while (member != NULL) {
14823 memberType = member->type;
14824 while ((memberType != NULL) &&
14825 (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14826 if (memberType == ctxType) {
14827 xmlSchemaPCustomErr(pctxt,
14828 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014829 WXS_BASIC_CAST ctxType, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014830 "The union type definition is circular", NULL);
14831 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14832 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014833 if ((WXS_IS_UNION(memberType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014834 ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14835 {
14836 int res;
14837 memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14838 res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
14839 ctxType,
14840 xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
14841 memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
14842 if (res != 0)
14843 return(res);
14844 }
14845 memberType = memberType->baseType;
14846 }
14847 member = member->next;
14848 }
14849 return(0);
14850}
14851
14852static int
14853xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
14854 xmlSchemaTypePtr type)
14855{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014856 if (! WXS_IS_UNION(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014857 return(0);
14858 return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
14859 type->memberTypes));
14860}
14861
Daniel Veillard01fa6152004-06-29 17:04:39 +000014862/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014863 * xmlSchemaResolveTypeReferences:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014864 * @item: the complex/simple type definition
14865 * @ctxt: the parser context
14866 * @name: the name
14867 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014868 * Resolvese type definition references
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014869 */
14870static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014871xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014872 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014873{
14874 if (typeDef == NULL)
14875 return;
14876
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014877 /*
14878 * Resolve the base type.
14879 */
14880 if (typeDef->baseType == NULL) {
14881 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
14882 typeDef->base, typeDef->baseNs);
14883 if (typeDef->baseType == NULL) {
14884 xmlSchemaPResCompAttrErr(ctxt,
14885 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014886 WXS_BASIC_CAST typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014887 "base", typeDef->base, typeDef->baseNs,
14888 XML_SCHEMA_TYPE_SIMPLE, NULL);
14889 return;
14890 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014891 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014892 if (WXS_IS_SIMPLE(typeDef)) {
14893 if (WXS_IS_UNION(typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014894 /*
14895 * Resolve the memberTypes.
14896 */
14897 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
14898 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014899 } else if (WXS_IS_LIST(typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014900 /*
14901 * Resolve the itemType.
14902 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014903 if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
14904
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014905 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014906 typeDef->base, typeDef->baseNs);
14907
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014908 if ((typeDef->subtypes == NULL) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014909 (! WXS_IS_SIMPLE(typeDef->subtypes)))
14910 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014911 typeDef->subtypes = NULL;
14912 xmlSchemaPResCompAttrErr(ctxt,
14913 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014914 WXS_BASIC_CAST typeDef, typeDef->node,
14915 "itemType", typeDef->base, typeDef->baseNs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014916 XML_SCHEMA_TYPE_SIMPLE, NULL);
14917 }
14918 }
14919 return;
14920 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014921 }
14922 /*
14923 * The ball of letters below means, that if we have a particle
14924 * which has a QName-helper component as its {term}, we want
14925 * to resolve it...
14926 */
14927 else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
14928 ((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
14929 XML_SCHEMA_TYPE_PARTICLE) &&
14930 (WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
14931 ((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
14932 XML_SCHEMA_EXTRA_QNAMEREF))
14933 {
14934 xmlSchemaQNameRefPtr ref =
14935 WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
14936 xmlSchemaModelGroupDefPtr groupDef;
14937
14938 /*
14939 * URGENT TODO: Test this.
14940 */
14941 WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
14942 /*
14943 * Resolve the MG definition reference.
14944 */
14945 groupDef =
14946 WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
14947 ref->itemType, ref->name, ref->targetNamespace);
14948 if (groupDef == NULL) {
14949 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
14950 NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
14951 "ref", ref->name, ref->targetNamespace, ref->itemType,
14952 NULL);
14953 /* Remove the particle. */
14954 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
14955 } else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
14956 /* Remove the particle. */
14957 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
14958 else {
14959 /*
14960 * Assign the MG definition's {model group} to the
14961 * particle's {term}.
14962 */
14963 WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
14964
14965 if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
14966 /*
14967 * SPEC cos-all-limited (1.2)
14968 * "1.2 the {term} property of a particle with
14969 * {max occurs}=1 which is part of a pair which constitutes
14970 * the {content type} of a complex type definition."
14971 */
14972 if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
14973 xmlSchemaCustomErr(ACTXT_CAST ctxt,
14974 /* TODO: error code */
14975 XML_SCHEMAP_COS_ALL_LIMITED,
14976 WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
14977 "The particle's {max occurs} must be 1, since the "
14978 "reference resolves to an 'all' model group",
14979 NULL, NULL);
14980 }
14981 }
14982 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014983 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014984}
14985
14986
14987
14988/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000014989 * xmlSchemaCheckSTPropsCorrect:
14990 * @ctxt: the schema parser context
14991 * @type: the simple type definition
14992 *
14993 * Checks st-props-correct.
14994 *
14995 * Returns 0 if the properties are correct,
14996 * if not, a positive error code and -1 on internal
14997 * errors.
14998 */
14999static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015000xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015001 xmlSchemaTypePtr type)
15002{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015003 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015004 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015005
Daniel Veillardc0826a72004-08-10 14:17:33 +000015006 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015007 /*
15008 * Schema Component Constraint: Simple Type Definition Properties Correct
15009 *
15010 * NOTE: This is somehow redundant, since we actually built a simple type
15011 * to have all the needed information; this acts as an self test.
15012 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015013 /* Base type: If the datatype has been ·derived· by ·restriction·
15014 * then the Simple Type Definition component from which it is ·derived·,
15015 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000015016 */
15017 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015018 /*
15019 * TODO: Think about: "modulo the impact of Missing
15020 * Sub-components (§5.3)."
15021 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015022 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015023 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015024 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015025 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015026 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015027
Daniel Veillard01fa6152004-06-29 17:04:39 +000015028 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015029 if (! WXS_IS_SIMPLE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015030 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015031 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015032 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015033 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015034 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015035 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015036 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15037 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015038 if ( (WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015039 (WXS_IS_RESTRICTION(type) == 0) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015040 (! WXS_IS_ANY_SIMPLE_TYPE(baseType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015041 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015042 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015043 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015044 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015045 "the simple ur-type definition as base type, not '%s'",
15046 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015047 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015048 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15049 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015050 /*
15051 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015052 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015053 if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15054 (! WXS_IS_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015055 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015056 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015057 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015058 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015059 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15060 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015061 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015062
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015063 /*
15064 * 3 The {final} of the {base type definition} must not contain restriction.
15065 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015066 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015067 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15068 xmlSchemaPCustomErr(ctxt,
15069 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015070 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015071 "The 'final' of its base type '%s' must not contain "
15072 "'restriction'",
15073 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015074 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015075 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015076 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015077
15078 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015079 * 2 All simple type definitions must be derived ultimately from the ·simple
15080 * ur-type definition (so· circular definitions are disallowed). That is, it
15081 * must be possible to reach a built-in primitive datatype or the ·simple
15082 * ur-type definition· by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015083 *
15084 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000015085 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015086 return (0);
15087}
15088
15089/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015090 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000015091 * @ctxt: the schema parser context
15092 * @type: the simple type definition
15093 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015094 * Schema Component Constraint:
15095 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15096
15097 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015098 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000015099 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015100 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015101 * a positive error code otherwise.
15102 */
15103static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015104xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015105 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015106{
Daniel Veillardc0826a72004-08-10 14:17:33 +000015107 xmlChar *str = NULL;
15108
Daniel Veillard01fa6152004-06-29 17:04:39 +000015109 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015110 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15111 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015112 return (-1);
15113 }
15114
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015115 if (WXS_IS_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015116 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015117 /*
15118 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000015119 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015120 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015121 if (! WXS_IS_ATOMIC(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015122 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015123 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015124 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015125 "The base type '%s' is not an atomic simple type",
15126 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015127 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015128 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15129 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015130 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000015131 * restriction.
15132 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015133 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015134 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015135 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015136 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015137 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015138 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015139 "The final of its base type '%s' must not contain 'restriction'",
15140 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015141 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015142 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15143 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015144
15145 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000015146 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015147 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000015148 * Primitive datatypes.
15149 */
15150 if (type->facets != NULL) {
15151 xmlSchemaFacetPtr facet;
15152 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015153
Daniel Veillard01fa6152004-06-29 17:04:39 +000015154 primitive = xmlSchemaGetPrimitiveType(type);
15155 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015156 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15157 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015158 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015159 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015160 facet = type->facets;
15161 do {
15162 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015163 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015164 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015165 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015166 type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015167 }
15168 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015169 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015170 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015171 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015172 }
15173 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015174 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15175 * of the {base type definition} (call this BF),then the DF's {value}
15176 * must be a valid restriction of BF's {value} as defined in
15177 * [XML Schemas: Datatypes]."
15178 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015179 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015180 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015181 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015182 } else if (WXS_IS_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015183 xmlSchemaTypePtr itemType = NULL;
15184
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015185 itemType = type->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015186 if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015187 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15188 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015189 return (-1);
15190 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015191 if (WXS_IS_TYPE_NOT_FIXED(itemType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015192 xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015193 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015194 * 2.1 The {item type definition} must have a {variety} of atomic or
15195 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000015196 * must be atomic).
15197 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015198 if ((! WXS_IS_ATOMIC(itemType)) &&
15199 (! WXS_IS_UNION(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015200 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015201 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015202 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015203 "The item type '%s' does not have a variety of atomic or union",
15204 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015205 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015206 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015207 } else if (WXS_IS_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015208 xmlSchemaTypeLinkPtr member;
15209
15210 member = itemType->memberTypes;
15211 while (member != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015212 if (! WXS_IS_ATOMIC(member->type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015213 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015214 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015215 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015216 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015217 "member type '%s' of this item type is not atomic",
15218 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015219 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015220 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15221 }
15222 member = member->next;
15223 }
15224 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015225
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015226 if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015227 xmlSchemaFacetPtr facet;
15228 /*
15229 * This is the case if we have: <simpleType><list ..
15230 */
15231 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015232 * 2.3.1
15233 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000015234 * contain list.
15235 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015236 if (xmlSchemaTypeFinalContains(itemType,
15237 XML_SCHEMAS_TYPE_FINAL_LIST)) {
15238 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015239 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015240 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015241 "The final of its item type '%s' must not contain 'list'",
15242 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015243 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015244 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15245 }
15246 /*
15247 * 2.3.1.2 The {facets} must only contain the whiteSpace
15248 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015249 * OPTIMIZE TODO: the S4S already disallows any facet
15250 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015251 */
15252 if (type->facets != NULL) {
15253 facet = type->facets;
15254 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015255 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015256 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015257 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015258 type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015259 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15260 }
15261 facet = facet->next;
15262 } while (facet != NULL);
15263 }
15264 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015265 * MAYBE TODO: (Hmm, not really) Datatypes states:
15266 * A ·list· datatype can be ·derived· from an ·atomic· datatype
15267 * whose ·lexical space· allows space (such as string or anyURI)or
15268 * a ·union· datatype any of whose {member type definitions}'s
Daniel Veillard01fa6152004-06-29 17:04:39 +000015269 * ·lexical space· allows space.
15270 */
15271 } else {
15272 /*
15273 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015274 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015275 */
15276 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015277 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000015278 * 2.3.2.1 The {base type definition} must have a {variety} of list.
15279 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015280 if (! WXS_IS_LIST(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015281 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015282 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015283 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015284 "The base type '%s' must be a list type",
15285 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015286 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015287 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15288 }
15289 /*
15290 * 2.3.2.2 The {final} of the {base type definition} must not
15291 * contain restriction.
15292 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015293 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015294 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015295 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015296 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015297 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015298 "The 'final' of the base type '%s' must not contain 'restriction'",
15299 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015300 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015301 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15302 }
15303 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015304 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000015305 * from the {base type definition}'s {item type definition} given
15306 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
15307 */
15308 {
15309 xmlSchemaTypePtr baseItemType;
15310
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015311 baseItemType = type->baseType->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015312 if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015313 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15314 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015315 return (-1);
15316 }
15317 if ((itemType != baseItemType) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015318 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015319 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015320 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015321 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015322 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015323 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015324 "The item type '%s' is not validly derived from "
15325 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015326 xmlSchemaGetComponentQName(&str, itemType),
15327 xmlSchemaGetComponentQName(&strBIT, baseItemType),
15328 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015329
15330 FREE_AND_NULL(str)
15331 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015332 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015333 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15334 }
15335 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015336
Daniel Veillard01fa6152004-06-29 17:04:39 +000015337 if (type->facets != NULL) {
15338 xmlSchemaFacetPtr facet;
15339 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015340 /*
15341 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000015342 * and enumeration facet components are allowed among the {facets}.
15343 */
15344 facet = type->facets;
15345 do {
15346 switch (facet->type) {
15347 case XML_SCHEMA_FACET_LENGTH:
15348 case XML_SCHEMA_FACET_MINLENGTH:
15349 case XML_SCHEMA_FACET_MAXLENGTH:
15350 case XML_SCHEMA_FACET_WHITESPACE:
15351 /*
15352 * TODO: 2.5.1.2 List datatypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015353 * The value of ·whiteSpace· is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015354 */
15355 case XML_SCHEMA_FACET_PATTERN:
15356 case XML_SCHEMA_FACET_ENUMERATION:
15357 break;
15358 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015359 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015360 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015361 type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015362 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015363 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000015364 * invalid facets.
15365 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015366 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015367 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015368 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015369 facet = facet->next;
15370 } while (facet != NULL);
15371 if (ok == 0)
15372 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15373 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015374 * SPEC (2.3.2.5) (same as 1.3.2)
15375 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015376 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015377 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015378 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015379 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015380 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015381 } else if (WXS_IS_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015382 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015383 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000015384 * atomic or list.
15385 */
15386 xmlSchemaTypeLinkPtr member;
15387
15388 member = type->memberTypes;
15389 while (member != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015390 if (WXS_IS_TYPE_NOT_FIXED(member->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015391 xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015392
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015393 if ((! WXS_IS_ATOMIC(member->type)) &&
15394 (! WXS_IS_LIST(member->type))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015395 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015396 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015397 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015398 "The member type '%s' is neither an atomic, nor a list type",
15399 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015400 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015401 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15402 }
15403 member = member->next;
15404 }
15405 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015406 * 3.3.1 If the {base type definition} is the ·simple ur-type
15407 * definition·
Daniel Veillard01fa6152004-06-29 17:04:39 +000015408 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015409 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015410 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015411 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000015412 * {final} which does not contain union.
15413 */
15414 member = type->memberTypes;
15415 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015416 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015417 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015418 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015419 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015420 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015421 "The 'final' of member type '%s' contains 'union'",
15422 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015423 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015424 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15425 }
15426 member = member->next;
15427 }
15428 /*
15429 * 3.3.1.2 The {facets} must be empty.
15430 */
15431 if (type->facetSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015432 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015433 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015434 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015435 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015436 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15437 }
15438 } else {
15439 /*
15440 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015441 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015442 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015443 if (! WXS_IS_UNION(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015444 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015445 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015446 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015447 "The base type '%s' is not a union type",
15448 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015449 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015450 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15451 }
15452 /*
15453 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15454 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015455 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015456 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015457 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015458 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015459 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015460 "The 'final' of its base type '%s' must not contain 'restriction'",
15461 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015462 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015463 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15464 }
15465 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015466 * 3.3.2.3 The {member type definitions}, in order, must be validly
15467 * derived from the corresponding type definitions in the {base
15468 * type definition}'s {member type definitions} given the empty set,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015469 * as defined in Type Derivation OK (Simple) (§3.14.6).
15470 */
15471 {
15472 xmlSchemaTypeLinkPtr baseMember;
15473
15474 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015475 * OPTIMIZE: if the type is restricting, it has no local defined
15476 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015477 * thus a check for equality can be skipped.
15478 */
15479 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015480 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015481 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000015482 * types of it's base type. This check seems not necessary with
15483 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015484 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015485 */
15486 if (type->memberTypes != NULL) {
15487 member = type->memberTypes;
15488 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015489 if ((member == NULL) && (baseMember != NULL)) {
15490 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15491 "different number of member types in base");
15492 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015493 while (member != NULL) {
15494 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015495 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15496 "different number of member types in base");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015497 }
15498 if ((member->type != baseMember->type) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015499 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015500 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015501 xmlChar *strBMT = NULL, *strBT = NULL;
15502
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015503 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015504 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015505 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015506 "The member type %s is not validly "
15507 "derived from its corresponding member "
15508 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015509 xmlSchemaGetComponentQName(&str, member->type),
15510 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15511 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015512 FREE_AND_NULL(str)
15513 FREE_AND_NULL(strBMT)
15514 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015515 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015516 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015517 member = member->next;
15518 baseMember = baseMember->next;
15519 }
15520 }
15521 }
15522 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015523 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000015524 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015525 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015526 if (type->facets != NULL) {
15527 xmlSchemaFacetPtr facet;
15528 int ok = 1;
15529
15530 facet = type->facets;
15531 do {
15532 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15533 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015534 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015535 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015536 type, facet);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015537 ok = 0;
15538 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015539 facet = facet->next;
15540 } while (facet != NULL);
15541 if (ok == 0)
15542 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015543
Daniel Veillard01fa6152004-06-29 17:04:39 +000015544 }
15545 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015546 * SPEC (3.3.2.5) (same as 1.3.2)
15547 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015548 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015549 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015550 */
15551 }
15552 }
15553
15554 return (0);
15555}
15556
15557/**
15558 * xmlSchemaCheckSRCSimpleType:
15559 * @ctxt: the schema parser context
15560 * @type: the simple type definition
15561 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015562 * Checks crc-simple-type constraints.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015563 *
15564 * Returns 0 if the constraints are satisfied,
15565 * if not a positive error code and -1 on internal
15566 * errors.
15567 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015568#if 0
Daniel Veillard01fa6152004-06-29 17:04:39 +000015569static int
15570xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15571 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015572{
15573 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000015574 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015575 * must satisfy the conditions set out in Constraints on Simple Type
15576 * Definition Schema Components (§3.14.6).
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015577 */
15578 if (WXS_IS_RESTRICTION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015579 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015580 * src-simple-type.2 "If the <restriction> alternative is chosen,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015581 * either it must have a base [attribute] or a <simpleType> among its
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015582 * [children], but not both."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015583 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015584 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015585 /*
15586 *
15587 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015588 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015589 /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015590 * an itemType [attribute] or a <simpleType> among its [children],
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015591 * but not both."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015592 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015593 * NOTE: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015594 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015595 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015596 /*
15597 * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015598 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015599 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015600 return (0);
15601}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015602#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000015603
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015604static int
15605xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15606{
15607 if (ctxt->vctxt == NULL) {
15608 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15609 if (ctxt->vctxt == NULL) {
15610 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015611 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015612 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015613 "failed to create a temp. validation context.\n",
15614 NULL, NULL);
15615 return (-1);
15616 }
15617 /* TODO: Pass user data. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015618 xmlSchemaSetValidErrors(ctxt->vctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000015619 ctxt->error, ctxt->warning, ctxt->errCtxt);
15620 xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15621 ctxt->serror, ctxt->errCtxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015622 }
15623 return (0);
15624}
15625
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015626static int
15627xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15628 xmlNodePtr node,
15629 xmlSchemaTypePtr type,
15630 const xmlChar *value,
15631 xmlSchemaValPtr *retVal,
15632 int fireErrors,
15633 int normalize,
15634 int isNormalized);
15635
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015636/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015637 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015638 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015639 * @type: the simple type definition
15640 * @value: the default value
15641 * @node: an optional node (the holder of the value)
15642 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015643 * Schema Component Constraint: Element Default Valid (Immediate)
15644 * (cos-valid-default)
15645 * This will be used by the parser only. For the validator there's
15646 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015647 *
15648 * Returns 0 if the constraints are satisfied,
15649 * if not, a positive error code and -1 on internal
15650 * errors.
15651 */
15652static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015653xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15654 xmlNodePtr node,
15655 xmlSchemaTypePtr type,
15656 const xmlChar *value,
15657 xmlSchemaValPtr *val)
15658{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015659 int ret = 0;
15660
15661 /*
15662 * cos-valid-default:
15663 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015664 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015665 * definition the appropriate case among the following must be true:
15666 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015667 if WXS_IS_COMPLEX(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015668 /*
15669 * Complex type.
15670 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015671 * SPEC (2.1) "its {content type} must be a simple type definition
15672 * or mixed."
15673 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015674 * type}'s particle must be ·emptiable· as defined by
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015675 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000015676 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015677 if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15678 ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015679 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015680 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015681 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015682 WXS_BASIC_CAST type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015683 "For a string to be a valid default, the type definition "
15684 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015685 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015686 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15687 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015688 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015689 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015690 * 1 If the type definition is a simple type definition, then the string
15691 * must be ·valid· with respect to that definition as defined by String
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015692 * Valid (§3.14.4).
15693 *
15694 * AND
15695 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015696 * 2.2.1 If the {content type} is a simple type definition, then the
15697 * string must be ·valid· with respect to that simple type definition
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015698 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015699 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015700 if (WXS_IS_SIMPLE(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015701 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015702 type, value, val, 1, 1, 0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015703 else if (WXS_HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015704 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015705 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015706 else
15707 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015708
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015709 if (ret < 0) {
15710 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15711 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015712 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015713
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015714 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000015715}
15716
15717/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015718 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000015719 * @ctxt: the schema parser context
15720 * @type: the complex type definition
15721 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015722 *.(4.6) Constraints on Complex Type Definition Schema Components
15723 * Schema Component Constraint:
15724 * Complex Type Definition Properties Correct (ct-props-correct)
15725 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000015726 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015727 * Returns 0 if the constraints are satisfied, a positive
15728 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000015729 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015730static int
15731xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15732 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000015733{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015734 /*
15735 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15736 *
15737 * SPEC (1) "The values of the properties of a complex type definition must
15738 * be as described in the property tableau in The Complex Type Definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015739 * Schema Component (§3.4.1), modulo the impact of Missing
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015740 * Sub-components (§5.3)."
15741 */
15742 if ((type->baseType != NULL) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015743 (WXS_IS_SIMPLE(type->baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015744 (WXS_IS_EXTENSION(type) == 0)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015745 /*
15746 * SPEC (2) "If the {base type definition} is a simple type definition,
15747 * the {derivation method} must be extension."
15748 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015749 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015750 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015751 NULL, WXS_BASIC_CAST type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015752 "If the base type is a simple type, the derivation method must be "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015753 "'extension'", NULL, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015754 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015755 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015756 /*
15757 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
15758 * definition·. That is, it must be possible to reach the ·ur-type
15759 * definition by repeatedly following the {base type definition}."
15760 *
15761 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015762 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015763 /*
15764 * NOTE that (4) and (5) need the following:
15765 * - attribute uses need to be already inherited (apply attr. prohibitions)
15766 * - attribute group references need to be expanded already
15767 * - simple types need to be typefixed already
15768 */
15769 if (type->attrUses &&
15770 (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15771 {
15772 xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15773 xmlSchemaAttributeUsePtr use, tmp;
15774 int i, j, hasId = 0;
15775
15776 for (i = uses->nbItems -1; i >= 0; i--) {
15777 use = uses->items[i];
15778
15779 /*
15780 * SPEC ct-props-correct
15781 * (4) "Two distinct attribute declarations in the
15782 * {attribute uses} must not have identical {name}s and
15783 * {target namespace}s."
15784 */
15785 if (i > 0) {
15786 for (j = i -1; j >= 0; j--) {
15787 tmp = uses->items[j];
15788 if ((WXS_ATTRUSE_DECL_NAME(use) ==
15789 WXS_ATTRUSE_DECL_NAME(tmp)) &&
15790 (WXS_ATTRUSE_DECL_TNS(use) ==
15791 WXS_ATTRUSE_DECL_TNS(tmp)))
15792 {
15793 xmlChar *str = NULL;
15794
15795 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15796 XML_SCHEMAP_AG_PROPS_CORRECT,
15797 NULL, WXS_BASIC_CAST type,
15798 "Duplicate %s",
15799 xmlSchemaGetComponentDesignation(&str, use),
15800 NULL);
15801 FREE_AND_NULL(str);
15802 /*
15803 * Remove the duplicate.
15804 */
15805 if (xmlSchemaItemListRemove(uses, i) == -1)
15806 goto exit_failure;
15807 goto next_use;
15808 }
15809 }
15810 }
15811 /*
15812 * SPEC ct-props-correct
15813 * (5) "Two distinct attribute declarations in the
15814 * {attribute uses} must not have {type definition}s which
15815 * are or are derived from ID."
15816 */
15817 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15818 if (xmlSchemaIsDerivedFromBuiltInType(
15819 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15820 {
15821 if (hasId) {
15822 xmlChar *str = NULL;
15823
15824 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15825 XML_SCHEMAP_AG_PROPS_CORRECT,
15826 NULL, WXS_BASIC_CAST type,
15827 "There must not exist more than one attribute "
15828 "declaration of type 'xs:ID' "
15829 "(or derived from 'xs:ID'). The %s violates this "
15830 "constraint",
15831 xmlSchemaGetComponentDesignation(&str, use),
15832 NULL);
15833 FREE_AND_NULL(str);
15834 if (xmlSchemaItemListRemove(uses, i) == -1)
15835 goto exit_failure;
15836 }
15837
15838 hasId = 1;
15839 }
15840 }
15841next_use: {}
15842 }
15843 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015844 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015845exit_failure:
15846 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +000015847}
15848
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015849static int
15850xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
15851 xmlSchemaTypePtr typeB)
15852{
15853 /*
15854 * TODO: This should implement component-identity
15855 * in the future.
15856 */
15857 if ((typeA == NULL) || (typeB == NULL))
15858 return (0);
15859 return (typeA == typeB);
15860}
15861
15862/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015863 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015864 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015865 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015866 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015867 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015868 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015869 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015870 * Type Derivation OK (Complex) (cos-ct-derived-ok)
15871 *
15872 * STATUS: completed
15873 *
15874 * Returns 0 if the constraints are satisfied, or 1
15875 * if not.
15876 */
15877static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015878xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015879 xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015880 xmlSchemaTypePtr baseType,
15881 int set)
15882{
15883 int equal = xmlSchemaAreEqualTypes(type, baseType);
15884 /* TODO: Error codes. */
15885 /*
15886 * SPEC "For a complex type definition (call it D, for derived)
15887 * to be validly derived from a type definition (call this
15888 * B, for base) given a subset of {extension, restriction}
15889 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015890 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015891 if (! equal) {
15892 /*
15893 * SPEC (1) "If B and D are not the same type definition, then the
15894 * {derivation method} of D must not be in the subset."
15895 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015896 if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
15897 ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015898 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015899 } else {
15900 /*
15901 * SPEC (2.1) "B and D must be the same type definition."
15902 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015903 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015904 }
15905 /*
15906 * SPEC (2.2) "B must be D's {base type definition}."
15907 */
15908 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015909 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015910 /*
15911 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
15912 * definition·."
15913 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015914 if (WXS_IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015915 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015916
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015917 if (WXS_IS_COMPLEX(type->baseType)) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015918 /*
15919 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
15920 * must be validly derived from B given the subset as defined by this
15921 * constraint."
15922 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015923 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015924 baseType, set));
15925 } else {
15926 /*
15927 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
15928 * must be validly derived from B given the subset as defined in Type
15929 * Derivation OK (Simple) (§3.14.6).
15930 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015931 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015932 baseType, set));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015933 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015934}
15935
15936/**
15937 * xmlSchemaCheckCOSDerivedOK:
15938 * @type: the derived simple type definition
15939 * @baseType: the base type definition
15940 *
15941 * Calls:
15942 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015943 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015944 * Checks wheter @type can be validly derived from @baseType.
15945 *
15946 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015947 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015948static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015949xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015950 xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015951 xmlSchemaTypePtr baseType,
15952 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015953{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015954 if (WXS_IS_SIMPLE(type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015955 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015956 else
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015957 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015958}
15959
William M. Brack2f2a6632004-08-20 23:09:47 +000015960/**
15961 * xmlSchemaCheckCOSCTExtends:
15962 * @ctxt: the schema parser context
15963 * @type: the complex type definition
15964 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015965 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015966 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015967 * Derivation Valid (Extension) (cos-ct-extends)
15968 *
15969 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015970 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015971 * (1.5)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015972 * (1.4.3.2.2.2) "Particle Valid (Extension)"
William M. Brack2f2a6632004-08-20 23:09:47 +000015973 *
15974 * Returns 0 if the constraints are satisfied, a positive
15975 * error code if not and -1 if an internal error occured.
15976 */
15977static int
15978xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
15979 xmlSchemaTypePtr type)
15980{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015981 xmlSchemaTypePtr base = type->baseType;
15982 /*
15983 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
15984 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000015985 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015986 /*
15987 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015988 * then all of the following must be true:"
15989 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015990 if (WXS_IS_COMPLEX(base)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015991 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015992 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015993 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000015994 */
15995 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
15996 xmlSchemaPCustomErr(ctxt,
15997 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015998 WXS_BASIC_CAST type, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000015999 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016000 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000016001 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16002 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016003
16004 /*
16005 * ATTENTION: The constrains (1.2) and (1.3) are not applied,
16006 * since they are automatically satisfied through the
16007 * inheriting mechanism.
16008 * Note that even if redefining components, the inheriting mechanism
16009 * is used.
16010 */
16011#if 0
William M. Brack2f2a6632004-08-20 23:09:47 +000016012 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016013 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016014 * uses}
16015 * of the complex type definition itself, that is, for every attribute
16016 * use in the {attribute uses} of the {base type definition}, there
16017 * must be an attribute use in the {attribute uses} of the complex
16018 * type definition itself whose {attribute declaration} has the same
16019 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016020 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000016021 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016022 if (base->attrUses != NULL) {
16023 int i, j, found;
16024 xmlSchemaAttributeUsePtr use, buse;
William M. Brack2f2a6632004-08-20 23:09:47 +000016025
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016026 for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16027 buse = (WXS_LIST_CAST base->attrUses)->items[i];
16028 found = 0;
16029 if (type->attrUses != NULL) {
16030 use = (WXS_LIST_CAST type->attrUses)->items[j];
16031 for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16032 {
16033 if ((WXS_ATTRUSE_DECL_NAME(use) ==
16034 WXS_ATTRUSE_DECL_NAME(buse)) &&
16035 (WXS_ATTRUSE_DECL_TNS(use) ==
16036 WXS_ATTRUSE_DECL_TNS(buse)) &&
16037 (WXS_ATTRUSE_TYPEDEF(use) ==
16038 WXS_ATTRUSE_TYPEDEF(buse))
16039 {
16040 found = 1;
16041 break;
16042 }
16043 }
16044 }
16045 if (! found) {
16046 xmlChar *str = NULL;
16047
16048 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16049 XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16050 NULL, WXS_BASIC_CAST type,
16051 /*
16052 * TODO: The report does not indicate that also the
16053 * type needs to be the same.
16054 */
16055 "This type is missing a matching correspondent "
16056 "for its {base type}'s %s in its {attribute uses}",
16057 xmlSchemaGetComponentDesignation(&str,
16058 buse->children),
16059 NULL);
16060 FREE_AND_NULL(str)
16061 }
16062 }
16063 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016064 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016065 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16066 * definition must also have one, and the base type definition's
16067 * {attribute wildcard}'s {namespace constraint} must be a subset
16068 * of the complex type definition's {attribute wildcard}'s {namespace
16069 * constraint}, as defined by Wildcard Subset (§3.10.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016070 */
16071
16072 /*
16073 * MAYBE TODO: Enable if ever needed. But this will be needed only
16074 * if created the type via a schema construction API.
16075 */
16076 if (base->attributeWildcard != NULL) {
16077 if (type->attributeWilcard == NULL) {
16078 xmlChar *str = NULL;
16079
16080 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16081 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16082 NULL, type,
16083 "The base %s has an attribute wildcard, "
16084 "but this type is missing an attribute wildcard",
16085 xmlSchemaGetComponentDesignation(&str, base));
16086 FREE_AND_NULL(str)
16087
16088 } else if (xmlSchemaCheckCOSNSSubset(
16089 base->attributeWildcard, type->attributeWildcard))
16090 {
16091 xmlChar *str = NULL;
16092
16093 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16094 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16095 NULL, type,
16096 "The attribute wildcard is not a valid "
16097 "superset of the one in the base %s",
16098 xmlSchemaGetComponentDesignation(&str, base));
16099 FREE_AND_NULL(str)
16100 }
16101 }
16102#endif
16103 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016104 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000016105 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016106 if ((type->contentTypeDef != NULL) &&
16107 (type->contentTypeDef == base->contentTypeDef)) {
16108 /*
16109 * SPEC (1.4.1) "The {content type} of the {base type definition}
16110 * and the {content type} of the complex type definition itself
16111 * must be the same simple type definition"
16112 * PASS
16113 */
16114 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16115 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16116 /*
16117 * SPEC (1.4.2) "The {content type} of both the {base type
16118 * definition} and the complex type definition itself must
16119 * be empty."
16120 * PASS
16121 */
16122 } else {
16123 /*
16124 * SPEC (1.4.3) "All of the following must be true:"
16125 */
16126 if (type->subtypes == NULL) {
16127 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016128 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016129 * definition itself must specify a particle.
16130 */
16131 xmlSchemaPCustomErr(ctxt,
16132 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016133 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016134 "The content type must specify a particle", NULL);
16135 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16136 }
16137 /*
16138 * SPEC (1.4.3.2) "One of the following must be true:"
16139 */
16140 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16141 /*
16142 * SPEC (1.4.3.2.1) "The {content type} of the {base type
16143 * definition} must be empty.
16144 * PASS
16145 */
16146 } else {
16147 /*
16148 * SPEC (1.4.3.2.2) "All of the following must be true:"
16149 */
16150 if ((type->contentType != base->contentType) ||
16151 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16152 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16153 /*
16154 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16155 * or both must be element-only."
16156 */
16157 xmlSchemaPCustomErr(ctxt,
16158 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016159 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016160 "The content type of both, the type and its base "
16161 "type, must either 'mixed' or 'element-only'", NULL);
16162 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016163 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016164 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016165 * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016166 * complex type definition must be a ·valid extension·
16167 * of the {base type definition}'s particle, as defined
16168 * in Particle Valid (Extension) (§3.9.6)."
16169 *
16170 * NOTE that we won't check "Particle Valid (Extension)",
16171 * since it is ensured by the derivation process in
16172 * xmlSchemaTypeFixup(). We need to implement this when heading
16173 * for a construction API
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016174 * TODO: !! This is needed to be checked if redefining a type !!
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016175 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016176 }
16177 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016178 * URGENT TODO (1.5)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016179 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016180 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016181 } else {
16182 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016183 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016184 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000016185 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016186 if (type->contentTypeDef != base) {
16187 /*
16188 * SPEC (2.1) "The {content type} must be the same simple type
16189 * definition."
16190 */
16191 xmlSchemaPCustomErr(ctxt,
16192 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016193 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016194 "The content type must be the simple base type", NULL);
16195 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16196 }
16197 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16198 /*
16199 * SPEC (2.2) "The {final} of the {base type definition} must not
16200 * contain extension"
16201 * NOTE that this is the same as (1.1).
16202 */
16203 xmlSchemaPCustomErr(ctxt,
16204 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016205 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016206 "The 'final' of the base type definition "
16207 "contains 'extension'", NULL);
16208 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016209 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016210 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016211 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016212}
16213
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016214/**
16215 * xmlSchemaCheckDerivationOKRestriction:
16216 * @ctxt: the schema parser context
16217 * @type: the complex type definition
16218 *
16219 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016220 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016221 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16222 *
16223 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016224 * missing:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016225 * (5.4.2) ???
16226 *
16227 * ATTENTION:
16228 * In XML Schema 1.1 this will be:
16229 * Validation Rule: Checking complex type subsumption
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016230 *
16231 * Returns 0 if the constraints are satisfied, a positive
16232 * error code if not and -1 if an internal error occured.
16233 */
16234static int
16235xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16236 xmlSchemaTypePtr type)
16237{
16238 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016239
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016240 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016241 * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016242 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016243 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016244 base = type->baseType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016245 if (! WXS_IS_COMPLEX(base)) {
16246 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16247 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16248 type->node, WXS_BASIC_CAST type,
16249 "The base type must be a complex type", NULL, NULL);
16250 return(ctxt->err);
16251 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016252 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16253 /*
16254 * SPEC (1) "The {base type definition} must be a complex type
16255 * definition whose {final} does not contain restriction."
16256 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016257 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16258 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16259 type->node, WXS_BASIC_CAST type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016260 "The 'final' of the base type definition "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016261 "contains 'restriction'", NULL, NULL);
16262 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016263 }
16264 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016265 * SPEC (2), (3) and (4)
16266 * Those are handled in a separate function, since the
16267 * same constraints are needed for redefinition of
16268 * attribute groups as well.
16269 */
16270 if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16271 XML_SCHEMA_ACTION_DERIVE,
16272 WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16273 type->attrUses, base->attrUses,
16274 type->attributeWildcard,
16275 base->attributeWildcard) == -1)
16276 {
16277 return(-1);
16278 }
16279 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016280 * SPEC (5) "One of the following must be true:"
16281 */
16282 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16283 /*
16284 * SPEC (5.1) "The {base type definition} must be the
16285 * ·ur-type definition·."
16286 * PASS
16287 */
16288 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16289 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16290 /*
16291 * SPEC (5.2.1) "The {content type} of the complex type definition
16292 * must be a simple type definition"
16293 *
16294 * SPEC (5.2.2) "One of the following must be true:"
16295 */
16296 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016297 (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16298 {
16299 int err;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016300 /*
16301 * SPEC (5.2.2.1) "The {content type} of the {base type
16302 * definition} must be a simple type definition from which
16303 * the {content type} is validly derived given the empty
16304 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016305 *
16306 * ATTENTION TODO: This seems not needed if the type implicitely
16307 * derived from the base type.
16308 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016309 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016310 err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16311 type->contentTypeDef, base->contentTypeDef, 0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016312 if (err != 0) {
16313 xmlChar *strA = NULL, *strB = NULL;
16314
16315 if (err == -1)
16316 return(-1);
16317 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16318 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16319 NULL, WXS_BASIC_CAST type,
16320 "The {content type} %s is not validly derived from the "
16321 "base type's {content type} %s",
16322 xmlSchemaGetComponentDesignation(&strA,
16323 type->contentTypeDef),
16324 xmlSchemaGetComponentDesignation(&strB,
16325 base->contentTypeDef));
16326 FREE_AND_NULL(strA);
16327 FREE_AND_NULL(strB);
16328 return(ctxt->err);
16329 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016330 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16331 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016332 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016333 /*
16334 * SPEC (5.2.2.2) "The {base type definition} must be mixed
16335 * and have a particle which is ·emptiable· as defined in
16336 * Particle Emptiable (§3.9.6)."
16337 * PASS
16338 */
16339 } else {
16340 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016341 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16342 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016343 "The content type of the base type must be either "
16344 "a simple type or 'mixed' and an emptiable particle", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016345 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016346 }
16347 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16348 /*
16349 * SPEC (5.3.1) "The {content type} of the complex type itself must
16350 * be empty"
16351 */
16352 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16353 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016354 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016355 * definition} must also be empty."
16356 * PASS
16357 */
16358 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16359 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16360 xmlSchemaIsParticleEmptiable(
16361 (xmlSchemaParticlePtr) base->subtypes)) {
16362 /*
16363 * SPEC (5.3.2.2) "The {content type} of the {base type
16364 * definition} must be elementOnly or mixed and have a particle
16365 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
16366 * PASS
16367 */
16368 } else {
16369 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016370 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16371 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016372 "The content type of the base type must be either "
16373 "empty or 'mixed' (or 'elements-only') and an emptiable "
16374 "particle", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016375 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016376 }
16377 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016378 WXS_HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016379 /*
16380 * SPEC (5.4.1.1) "The {content type} of the complex type definition
16381 * itself must be element-only"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016382 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016383 if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016384 /*
16385 * SPEC (5.4.1.2) "The {content type} of the complex type
16386 * definition itself and of the {base type definition} must be
16387 * mixed"
16388 */
16389 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016390 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16391 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016392 "If the content type is 'mixed', then the content type of the "
16393 "base type must also be 'mixed'", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016394 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016395 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016396 /*
16397 * SPEC (5.4.2) "The particle of the complex type definition itself
16398 * must be a ·valid restriction· of the particle of the {content
16399 * type} of the {base type definition} as defined in Particle Valid
16400 * (Restriction) (§3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016401 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016402 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016403 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016404 } else {
16405 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016406 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16407 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016408 "The type is not a valid restriction of its base type", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016409 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016410 }
16411 return (0);
16412}
16413
16414/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016415 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016416 * @ctxt: the schema parser context
16417 * @type: the complex type definition
16418 *
16419 * (3.4.6) Constraints on Complex Type Definition Schema Components
16420 *
16421 * Returns 0 if the constraints are satisfied, a positive
16422 * error code if not and -1 if an internal error occured.
16423 */
16424static int
16425xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16426 xmlSchemaTypePtr type)
16427{
16428 int ret;
16429 /*
16430 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016431 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016432 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16433 if (ret != 0)
16434 return (ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016435 if (WXS_IS_EXTENSION(type))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016436 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16437 else
16438 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16439 return (ret);
16440}
16441
16442/**
16443 * xmlSchemaCheckSRCCT:
16444 * @ctxt: the schema parser context
16445 * @type: the complex type definition
16446 *
16447 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016448 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016449 * Complex Type Definition Representation OK (src-ct)
16450 *
16451 * Returns 0 if the constraints are satisfied, a positive
16452 * error code if not and -1 if an internal error occured.
16453 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016454static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016455xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016456 xmlSchemaTypePtr type)
16457{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016458 xmlSchemaTypePtr base;
16459 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016460
16461 /*
16462 * TODO: Adjust the error codes here, as I used
16463 * XML_SCHEMAP_SRC_CT_1 only yet.
16464 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016465 base = type->baseType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016466 if (! WXS_HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016467 /*
16468 * 1 If the <complexContent> alternative is chosen, the type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016469 * ·resolved· to by the ·actual value· of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016470 * must be a complex type definition;
16471 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016472 if (! WXS_IS_COMPLEX(base)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016473 xmlChar *str = NULL;
16474 xmlSchemaPCustomErr(ctxt,
16475 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016476 WXS_BASIC_CAST type, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016477 "If using <complexContent>, the base type is expected to be "
16478 "a complex type. The base type '%s' is a simple type",
16479 xmlSchemaFormatQName(&str, base->targetNamespace,
16480 base->name));
16481 FREE_AND_NULL(str)
16482 return (XML_SCHEMAP_SRC_CT_1);
16483 }
16484 } else {
16485 /*
16486 * SPEC
16487 * 2 If the <simpleContent> alternative is chosen, all of the
16488 * following must be true:
16489 * 2.1 The type definition ·resolved· to by the ·actual value· of the
16490 * base [attribute] must be one of the following:
16491 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016492 if (WXS_IS_SIMPLE(base)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016493 if (WXS_IS_EXTENSION(type) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016494 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016495 /*
16496 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016497 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016498 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016499 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016500 xmlSchemaPCustomErr(ctxt,
16501 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016502 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016503 "If using <simpleContent> and <restriction>, the base "
16504 "type must be a complex type. The base type '%s' is "
16505 "a simple type",
16506 xmlSchemaFormatQName(&str, base->targetNamespace,
16507 base->name));
16508 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016509 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016510 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016511 } else {
16512 /* Base type is a complex type. */
16513 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16514 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16515 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016516 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016517 * simple type definition;
16518 * PASS
16519 */
16520 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016521 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016522 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016523 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016524 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016525 type->name);
16526 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016527 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016528 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016529 (WXS_IS_RESTRICTION(type))) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016530
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016531 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016532 * 2.1.2 only if the <restriction> alternative is also
16533 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016534 * is mixed and a particle emptiable.
16535 */
16536 if (! xmlSchemaIsParticleEmptiable(
16537 (xmlSchemaParticlePtr) base->subtypes)) {
16538 ret = XML_SCHEMAP_SRC_CT_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016539 } else
16540 /*
16541 * Attention: at this point the <simpleType> child is in
16542 * ->contentTypeDef (put there during parsing).
16543 */
16544 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016545 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016546 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016547 * 2.2 If clause 2.1.2 above is satisfied, then there
16548 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016549 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016550 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016551 /* TODO: Change error code to ..._SRC_CT_2_2. */
16552 xmlSchemaPCustomErr(ctxt,
16553 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016554 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016555 "A <simpleType> is expected among the children "
16556 "of <restriction>, if <simpleContent> is used and "
16557 "the base type '%s' is a complex type",
16558 xmlSchemaFormatQName(&str, base->targetNamespace,
16559 base->name));
16560 FREE_AND_NULL(str)
16561 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016562 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016563 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016564 ret = XML_SCHEMAP_SRC_CT_1;
16565 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016566 }
16567 if (ret > 0) {
16568 xmlChar *str = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016569 if (WXS_IS_RESTRICTION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016570 xmlSchemaPCustomErr(ctxt,
16571 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016572 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016573 "If <simpleContent> and <restriction> is used, the "
16574 "base type must be a simple type or a complex type with "
16575 "mixed content and particle emptiable. The base type "
16576 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016577 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016578 base->name));
16579 } else {
16580 xmlSchemaPCustomErr(ctxt,
16581 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016582 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016583 "If <simpleContent> and <extension> is used, the "
16584 "base type must be a simple type. The base type '%s' "
16585 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016586 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016587 base->name));
16588 }
16589 FREE_AND_NULL(str)
16590 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016591 }
16592 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016593 * SPEC (3) "The corresponding complex type definition component must
16594 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016595 * Definition Schema Components (§3.4.6);"
16596 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016597 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016598 /*
16599 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016600 * above for {attribute wildcard} is satisfied, the intensional
16601 * intersection must be expressible, as defined in Attribute Wildcard
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016602 * Intersection (§3.10.6).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016603 * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016604 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016605 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016606}
William M. Brack2f2a6632004-08-20 23:09:47 +000016607
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016608#ifdef ENABLE_PARTICLE_RESTRICTION
16609/**
16610 * xmlSchemaCheckParticleRangeOK:
16611 * @ctxt: the schema parser context
16612 * @type: the complex type definition
16613 *
16614 * (3.9.6) Constraints on Particle Schema Components
16615 * Schema Component Constraint:
16616 * Occurrence Range OK (range-ok)
16617 *
16618 * STATUS: complete
16619 *
16620 * Returns 0 if the constraints are satisfied, a positive
16621 * error code if not and -1 if an internal error occured.
16622 */
16623static int
16624xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16625 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016626{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016627 if (rmin < bmin)
16628 return (1);
16629 if ((bmax != UNBOUNDED) &&
16630 (rmax > bmax))
16631 return (1);
16632 return (0);
16633}
16634
16635/**
16636 * xmlSchemaCheckRCaseNameAndTypeOK:
16637 * @ctxt: the schema parser context
16638 * @r: the restricting element declaration particle
16639 * @b: the base element declaration particle
16640 *
16641 * (3.9.6) Constraints on Particle Schema Components
16642 * Schema Component Constraint:
16643 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16644 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016645 *
16646 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016647 * MISSING (3.2.3)
16648 * CLARIFY: (3.2.2)
16649 *
16650 * Returns 0 if the constraints are satisfied, a positive
16651 * error code if not and -1 if an internal error occured.
16652 */
16653static int
16654xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16655 xmlSchemaParticlePtr r,
16656 xmlSchemaParticlePtr b)
16657{
16658 xmlSchemaElementPtr elemR, elemB;
16659
16660 /* TODO: Error codes (rcase-NameAndTypeOK). */
16661 elemR = (xmlSchemaElementPtr) r->children;
16662 elemB = (xmlSchemaElementPtr) b->children;
16663 /*
16664 * SPEC (1) "The declarations' {name}s and {target namespace}s are
16665 * the same."
16666 */
16667 if ((elemR != elemB) &&
16668 ((! xmlStrEqual(elemR->name, elemB->name)) ||
16669 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16670 return (1);
16671 /*
16672 * SPEC (2) "R's occurrence range is a valid restriction of B's
16673 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16674 */
16675 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16676 b->minOccurs, b->maxOccurs) != 0)
16677 return (1);
16678 /*
16679 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16680 * {scope} are global."
16681 */
16682 if (elemR == elemB)
16683 return (0);
16684 /*
16685 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16686 */
16687 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16688 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16689 return (1);
16690 /*
16691 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16692 * or is not fixed, or R's declaration's {value constraint} is fixed
16693 * with the same value."
16694 */
16695 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16696 ((elemR->value == NULL) ||
16697 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16698 /* TODO: Equality of the initial value or normalized or canonical? */
16699 (! xmlStrEqual(elemR->value, elemB->value))))
16700 return (1);
16701 /*
16702 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16703 * definitions} is a subset of B's declaration's {identity-constraint
16704 * definitions}, if any."
16705 */
16706 if (elemB->idcs != NULL) {
16707 /* TODO */
16708 }
16709 /*
16710 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16711 * superset of B's declaration's {disallowed substitutions}."
16712 */
16713 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16714 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16715 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16716 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16717 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16718 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16719 return (1);
16720 /*
16721 * SPEC (3.2.5) "R's {type definition} is validly derived given
16722 * {extension, list, union} from B's {type definition}"
16723 *
16724 * BADSPEC TODO: What's the point of adding "list" and "union" to the
16725 * set, if the corresponding constraints handle "restriction" and
16726 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016727 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016728 */
16729 {
16730 int set = 0;
16731
16732 set |= SUBSET_EXTENSION;
16733 set |= SUBSET_LIST;
16734 set |= SUBSET_UNION;
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016735 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016736 elemB->subtypes, set) != 0)
16737 return (1);
16738 }
16739 return (0);
16740}
16741
16742/**
16743 * xmlSchemaCheckRCaseNSCompat:
16744 * @ctxt: the schema parser context
16745 * @r: the restricting element declaration particle
16746 * @b: the base wildcard particle
16747 *
16748 * (3.9.6) Constraints on Particle Schema Components
16749 * Schema Component Constraint:
16750 * Particle Derivation OK (Elt:Any -- NSCompat)
16751 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016752 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016753 * STATUS: complete
16754 *
16755 * Returns 0 if the constraints are satisfied, a positive
16756 * error code if not and -1 if an internal error occured.
16757 */
16758static int
16759xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16760 xmlSchemaParticlePtr r,
16761 xmlSchemaParticlePtr b)
16762{
16763 /* TODO:Error codes (rcase-NSCompat). */
16764 /*
16765 * SPEC "For an element declaration particle to be a ·valid restriction·
16766 * of a wildcard particle all of the following must be true:"
16767 *
16768 * SPEC (1) "The element declaration's {target namespace} is ·valid·
16769 * with respect to the wildcard's {namespace constraint} as defined by
16770 * Wildcard allows Namespace Name (§3.10.4)."
16771 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016772 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016773 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16774 return (1);
16775 /*
16776 * SPEC (2) "R's occurrence range is a valid restriction of B's
16777 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16778 */
16779 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16780 b->minOccurs, b->maxOccurs) != 0)
16781 return (1);
16782
16783 return (0);
16784}
16785
16786/**
16787 * xmlSchemaCheckRCaseRecurseAsIfGroup:
16788 * @ctxt: the schema parser context
16789 * @r: the restricting element declaration particle
16790 * @b: the base model group particle
16791 *
16792 * (3.9.6) Constraints on Particle Schema Components
16793 * Schema Component Constraint:
16794 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16795 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016796 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016797 * STATUS: TODO
16798 *
16799 * Returns 0 if the constraints are satisfied, a positive
16800 * error code if not and -1 if an internal error occured.
16801 */
16802static int
16803xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16804 xmlSchemaParticlePtr r,
16805 xmlSchemaParticlePtr b)
16806{
16807 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16808 TODO
16809 return (0);
16810}
16811
16812/**
16813 * xmlSchemaCheckRCaseNSSubset:
16814 * @ctxt: the schema parser context
16815 * @r: the restricting wildcard particle
16816 * @b: the base wildcard particle
16817 *
16818 * (3.9.6) Constraints on Particle Schema Components
16819 * Schema Component Constraint:
16820 * Particle Derivation OK (Any:Any -- NSSubset)
16821 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016822 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016823 * STATUS: complete
16824 *
16825 * Returns 0 if the constraints are satisfied, a positive
16826 * error code if not and -1 if an internal error occured.
16827 */
16828static int
16829xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16830 xmlSchemaParticlePtr r,
16831 xmlSchemaParticlePtr b,
16832 int isAnyTypeBase)
16833{
16834 /* TODO: Error codes (rcase-NSSubset). */
16835 /*
16836 * SPEC (1) "R's occurrence range is a valid restriction of B's
16837 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16838 */
16839 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16840 b->minOccurs, b->maxOccurs))
16841 return (1);
16842 /*
16843 * SPEC (2) "R's {namespace constraint} must be an intensional subset
16844 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
16845 */
16846 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
16847 (xmlSchemaWildcardPtr) b->children))
16848 return (1);
16849 /*
16850 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
16851 * definition·, R's {process contents} must be identical to or stronger
16852 * than B's {process contents}, where strict is stronger than lax is
16853 * stronger than skip."
16854 */
16855 if (! isAnyTypeBase) {
16856 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
16857 ((xmlSchemaWildcardPtr) b->children)->processContents)
16858 return (1);
16859 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016860
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016861 return (0);
16862}
16863
16864/**
16865 * xmlSchemaCheckCOSParticleRestrict:
16866 * @ctxt: the schema parser context
16867 * @type: the complex type definition
16868 *
16869 * (3.9.6) Constraints on Particle Schema Components
16870 * Schema Component Constraint:
16871 * Particle Valid (Restriction) (cos-particle-restrict)
16872 *
16873 * STATUS: TODO
16874 *
16875 * Returns 0 if the constraints are satisfied, a positive
16876 * error code if not and -1 if an internal error occured.
16877 */
16878static int
16879xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
16880 xmlSchemaParticlePtr r,
16881 xmlSchemaParticlePtr b)
16882{
16883 int ret = 0;
16884
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016885 /*part = WXS_TYPE_PARTICLE(type);
16886 basePart = WXS_TYPE_PARTICLE(base);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016887 */
16888
16889 TODO
16890
16891 /*
16892 * SPEC (1) "They are the same particle."
16893 */
16894 if (r == b)
16895 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016896
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016897
16898 return (0);
16899}
16900
16901/**
16902 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
16903 * @ctxt: the schema parser context
16904 * @r: the model group particle
16905 * @b: the base wildcard particle
16906 *
16907 * (3.9.6) Constraints on Particle Schema Components
16908 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016909 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016910 * NSRecurseCheckCardinality)
16911 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016912 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016913 * STATUS: TODO: subst-groups
16914 *
16915 * Returns 0 if the constraints are satisfied, a positive
16916 * error code if not and -1 if an internal error occured.
16917 */
16918static int
16919xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
16920 xmlSchemaParticlePtr r,
16921 xmlSchemaParticlePtr b)
16922{
16923 xmlSchemaParticlePtr part;
16924 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
16925 if ((r->children == NULL) || (r->children->children == NULL))
16926 return (-1);
16927 /*
16928 * SPEC "For a group particle to be a ·valid restriction· of a
16929 * wildcard particle..."
16930 *
16931 * SPEC (1) "Every member of the {particles} of the group is a ·valid
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016932 * restriction· of the wildcard as defined by
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016933 * Particle Valid (Restriction) (§3.9.6)."
16934 */
16935 part = (xmlSchemaParticlePtr) r->children->children;
16936 do {
16937 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
16938 return (1);
16939 part = (xmlSchemaParticlePtr) part->next;
16940 } while (part != NULL);
16941 /*
16942 * SPEC (2) "The effective total range of the group [...] is a
16943 * valid restriction of B's occurrence range as defined by
16944 * Occurrence Range OK (§3.9.6)."
16945 */
16946 if (xmlSchemaCheckParticleRangeOK(
16947 xmlSchemaGetParticleTotalRangeMin(r),
16948 xmlSchemaGetParticleTotalRangeMax(r),
16949 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016950 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016951 return (0);
16952}
16953
16954/**
16955 * xmlSchemaCheckRCaseRecurse:
16956 * @ctxt: the schema parser context
16957 * @r: the <all> or <sequence> model group particle
16958 * @b: the base <all> or <sequence> model group particle
16959 *
16960 * (3.9.6) Constraints on Particle Schema Components
16961 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016962 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016963 Recurse)
16964 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016965 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016966 * STATUS: ?
16967 * TODO: subst-groups
16968 *
16969 * Returns 0 if the constraints are satisfied, a positive
16970 * error code if not and -1 if an internal error occured.
16971 */
16972static int
16973xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
16974 xmlSchemaParticlePtr r,
16975 xmlSchemaParticlePtr b)
16976{
16977 /* xmlSchemaParticlePtr part; */
16978 /* TODO: Error codes (rcase-Recurse). */
16979 if ((r->children == NULL) || (b->children == NULL) ||
16980 (r->children->type != b->children->type))
16981 return (-1);
16982 /*
16983 * SPEC "For an all or sequence group particle to be a ·valid
16984 * restriction· of another group particle with the same {compositor}..."
16985 *
16986 * SPEC (1) "R's occurrence range is a valid restriction of B's
16987 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16988 */
16989 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16990 b->minOccurs, b->maxOccurs))
16991 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016992
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016993
16994 return (0);
16995}
16996
16997#endif
16998
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016999#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17000 xmlSchemaPCustomErrExt(pctxt, \
17001 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017002 WXS_BASIC_CAST fac1, fac1->node, \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017003 "It is an error for both '%s' and '%s' to be specified on the "\
17004 "same type definition", \
17005 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17006 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17007
17008#define FACET_RESTR_ERR(fac1, msg) \
17009 xmlSchemaPCustomErr(pctxt, \
17010 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017011 WXS_BASIC_CAST fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017012 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017013
17014#define FACET_RESTR_FIXED_ERR(fac) \
17015 xmlSchemaPCustomErr(pctxt, \
17016 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017017 WXS_BASIC_CAST fac, fac->node, \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017018 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017019 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017020
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017021static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017022xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17023 xmlSchemaFacetPtr facet1,
17024 xmlSchemaFacetPtr facet2,
17025 int lessGreater,
17026 int orEqual,
17027 int ofBase)
17028{
17029 xmlChar *msg = NULL;
17030
17031 msg = xmlStrdup(BAD_CAST "'");
17032 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17033 msg = xmlStrcat(msg, BAD_CAST "' has to be");
17034 if (lessGreater == 0)
17035 msg = xmlStrcat(msg, BAD_CAST " equal to");
17036 if (lessGreater == 1)
17037 msg = xmlStrcat(msg, BAD_CAST " greater than");
17038 else
17039 msg = xmlStrcat(msg, BAD_CAST " less than");
17040
17041 if (orEqual)
17042 msg = xmlStrcat(msg, BAD_CAST " or equal to");
17043 msg = xmlStrcat(msg, BAD_CAST " '");
17044 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17045 if (ofBase)
17046 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17047 else
17048 msg = xmlStrcat(msg, BAD_CAST "'");
17049
17050 xmlSchemaPCustomErr(pctxt,
17051 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017052 WXS_BASIC_CAST facet1, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017053 (const char *) msg, NULL);
17054
17055 if (msg != NULL)
17056 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017057}
17058
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017059/*
17060* xmlSchemaDeriveAndValidateFacets:
17061*
17062* Schema Component Constraint: Simple Type Restriction (Facets)
17063* (st-restrict-facets)
17064*/
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017065static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017066xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17067 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017068{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017069 xmlSchemaTypePtr base = type->baseType;
17070 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017071 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017072 flength = NULL, ftotdig = NULL, ffracdig = NULL,
17073 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17074 fmininc = NULL, fmaxinc = NULL,
17075 fminexc = NULL, fmaxexc = NULL,
17076 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17077 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17078 bfmininc = NULL, bfmaxinc = NULL,
17079 bfminexc = NULL, bfmaxexc = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000017080 int res; /* err = 0, fixedErr; */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017081
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017082 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017083 * SPEC st-restrict-facets 1:
17084 * "The {variety} of R is the same as that of B."
17085 */
17086 /*
17087 * SPEC st-restrict-facets 2:
17088 * "If {variety} is atomic, the {primitive type definition}
17089 * of R is the same as that of B."
17090 *
17091 * NOTE: we leave 1 & 2 out for now, since this will be
17092 * satisfied by the derivation process.
17093 * CONSTRUCTION TODO: Maybe needed if using a construction API.
17094 */
17095 /*
17096 * SPEC st-restrict-facets 3:
17097 * "The {facets} of R are the union of S and the {facets}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017098 * of B, eliminating duplicates. To eliminate duplicates,
17099 * when a facet of the same kind occurs in both S and the
17100 * {facets} of B, the one in the {facets} of B is not
17101 * included, with the exception of enumeration and pattern
17102 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017103 * are allowed."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017104 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017105
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017106 if ((type->facetSet == NULL) && (base->facetSet == NULL))
17107 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017108
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017109 last = type->facetSet;
17110 if (last != NULL)
17111 while (last->next != NULL)
17112 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017113
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017114 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17115 facet = cur->facet;
17116 switch (facet->type) {
17117 case XML_SCHEMA_FACET_LENGTH:
17118 flength = facet; break;
17119 case XML_SCHEMA_FACET_MINLENGTH:
17120 fminlen = facet; break;
17121 case XML_SCHEMA_FACET_MININCLUSIVE:
17122 fmininc = facet; break;
17123 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17124 fminexc = facet; break;
17125 case XML_SCHEMA_FACET_MAXLENGTH:
17126 fmaxlen = facet; break;
17127 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17128 fmaxinc = facet; break;
17129 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17130 fmaxexc = facet; break;
17131 case XML_SCHEMA_FACET_TOTALDIGITS:
17132 ftotdig = facet; break;
17133 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17134 ffracdig = facet; break;
17135 default:
17136 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017137 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017138 }
17139 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17140 facet = cur->facet;
17141 switch (facet->type) {
17142 case XML_SCHEMA_FACET_LENGTH:
17143 bflength = facet; break;
17144 case XML_SCHEMA_FACET_MINLENGTH:
17145 bfminlen = facet; break;
17146 case XML_SCHEMA_FACET_MININCLUSIVE:
17147 bfmininc = facet; break;
17148 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17149 bfminexc = facet; break;
17150 case XML_SCHEMA_FACET_MAXLENGTH:
17151 bfmaxlen = facet; break;
17152 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17153 bfmaxinc = facet; break;
17154 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17155 bfmaxexc = facet; break;
17156 case XML_SCHEMA_FACET_TOTALDIGITS:
17157 bftotdig = facet; break;
17158 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17159 bffracdig = facet; break;
17160 default:
17161 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017162 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017163 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017164 /*
17165 * length and minLength or maxLength (2.2) + (3.2)
17166 */
17167 if (flength && (fminlen || fmaxlen)) {
17168 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17169 "either of 'minLength' or 'maxLength' to be specified on "
17170 "the same type definition")
17171 }
17172 /*
17173 * Mutual exclusions in the same derivation step.
17174 */
17175 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017176 /*
17177 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017178 */
17179 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17180 }
17181 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017182 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017183 * SCC "minInclusive and minExclusive"
17184 */
17185 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017186 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017187
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017188 if (flength && bflength) {
17189 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017190 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017191 * The values have to be equal.
17192 */
17193 res = xmlSchemaCompareValues(flength->val, bflength->val);
17194 if (res == -2)
17195 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017196 if (res != 0)
17197 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17198 if ((res != 0) && (bflength->fixed)) {
17199 FACET_RESTR_FIXED_ERR(flength)
17200 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017201
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017202 }
17203 if (fminlen && bfminlen) {
17204 /*
17205 * SCC "minLength valid restriction"
17206 * minLength >= BASE minLength
17207 */
17208 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17209 if (res == -2)
17210 goto internal_error;
17211 if (res == -1)
17212 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17213 if ((res != 0) && (bfminlen->fixed)) {
17214 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017215 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017216 }
17217 if (fmaxlen && bfmaxlen) {
17218 /*
17219 * SCC "maxLength valid restriction"
17220 * maxLength <= BASE minLength
17221 */
17222 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17223 if (res == -2)
17224 goto internal_error;
17225 if (res == 1)
17226 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17227 if ((res != 0) && (bfmaxlen->fixed)) {
17228 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017229 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017230 }
17231 /*
17232 * SCC "length and minLength or maxLength"
17233 */
17234 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017235 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017236 if (flength) {
17237 if (! fminlen)
17238 flength = bflength;
17239 if (fminlen) {
17240 /* (1.1) length >= minLength */
17241 res = xmlSchemaCompareValues(flength->val, fminlen->val);
17242 if (res == -2)
17243 goto internal_error;
17244 if (res == -1)
17245 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17246 }
17247 if (! fmaxlen)
17248 fmaxlen = bfmaxlen;
17249 if (fmaxlen) {
17250 /* (2.1) length <= maxLength */
17251 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17252 if (res == -2)
17253 goto internal_error;
17254 if (res == 1)
17255 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17256 }
17257 }
17258 if (fmaxinc) {
17259 /*
17260 * "maxInclusive"
17261 */
17262 if (fmininc) {
17263 /* SCC "maxInclusive >= minInclusive" */
17264 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17265 if (res == -2)
17266 goto internal_error;
17267 if (res == -1) {
17268 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17269 }
17270 }
17271 /*
17272 * SCC "maxInclusive valid restriction"
17273 */
17274 if (bfmaxinc) {
17275 /* maxInclusive <= BASE maxInclusive */
17276 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17277 if (res == -2)
17278 goto internal_error;
17279 if (res == 1)
17280 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17281 if ((res != 0) && (bfmaxinc->fixed)) {
17282 FACET_RESTR_FIXED_ERR(fmaxinc)
17283 }
17284 }
17285 if (bfmaxexc) {
17286 /* maxInclusive < BASE maxExclusive */
17287 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17288 if (res == -2)
17289 goto internal_error;
17290 if (res != -1) {
17291 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17292 }
17293 }
17294 if (bfmininc) {
17295 /* maxInclusive >= BASE minInclusive */
17296 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17297 if (res == -2)
17298 goto internal_error;
17299 if (res == -1) {
17300 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17301 }
17302 }
17303 if (bfminexc) {
17304 /* maxInclusive > BASE minExclusive */
17305 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17306 if (res == -2)
17307 goto internal_error;
17308 if (res != 1) {
17309 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17310 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017311 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017312 }
17313 if (fmaxexc) {
17314 /*
17315 * "maxExclusive >= minExclusive"
17316 */
17317 if (fminexc) {
17318 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17319 if (res == -2)
17320 goto internal_error;
17321 if (res == -1) {
17322 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17323 }
17324 }
17325 /*
17326 * "maxExclusive valid restriction"
17327 */
17328 if (bfmaxexc) {
17329 /* maxExclusive <= BASE maxExclusive */
17330 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17331 if (res == -2)
17332 goto internal_error;
17333 if (res == 1) {
17334 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17335 }
17336 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017337 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017338 }
17339 }
17340 if (bfmaxinc) {
17341 /* maxExclusive <= BASE maxInclusive */
17342 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17343 if (res == -2)
17344 goto internal_error;
17345 if (res == 1) {
17346 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17347 }
17348 }
17349 if (bfmininc) {
17350 /* maxExclusive > BASE minInclusive */
17351 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17352 if (res == -2)
17353 goto internal_error;
17354 if (res != 1) {
17355 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17356 }
17357 }
17358 if (bfminexc) {
17359 /* maxExclusive > BASE minExclusive */
17360 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17361 if (res == -2)
17362 goto internal_error;
17363 if (res != 1) {
17364 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17365 }
17366 }
17367 }
17368 if (fminexc) {
17369 /*
17370 * "minExclusive < maxInclusive"
17371 */
17372 if (fmaxinc) {
17373 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17374 if (res == -2)
17375 goto internal_error;
17376 if (res != -1) {
17377 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17378 }
17379 }
17380 /*
17381 * "minExclusive valid restriction"
17382 */
17383 if (bfminexc) {
17384 /* minExclusive >= BASE minExclusive */
17385 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17386 if (res == -2)
17387 goto internal_error;
17388 if (res == -1) {
17389 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17390 }
17391 if ((res != 0) && (bfminexc->fixed)) {
17392 FACET_RESTR_FIXED_ERR(fminexc)
17393 }
17394 }
17395 if (bfmaxinc) {
17396 /* minExclusive <= BASE maxInclusive */
17397 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17398 if (res == -2)
17399 goto internal_error;
17400 if (res == 1) {
17401 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17402 }
17403 }
17404 if (bfmininc) {
17405 /* minExclusive >= BASE minInclusive */
17406 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17407 if (res == -2)
17408 goto internal_error;
17409 if (res == -1) {
17410 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17411 }
17412 }
17413 if (bfmaxexc) {
17414 /* minExclusive < BASE maxExclusive */
17415 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17416 if (res == -2)
17417 goto internal_error;
17418 if (res != -1) {
17419 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17420 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017421 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017422 }
17423 if (fmininc) {
17424 /*
17425 * "minInclusive < maxExclusive"
17426 */
17427 if (fmaxexc) {
17428 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17429 if (res == -2)
17430 goto internal_error;
17431 if (res != -1) {
17432 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17433 }
17434 }
17435 /*
17436 * "minExclusive valid restriction"
17437 */
17438 if (bfmininc) {
17439 /* minInclusive >= BASE minInclusive */
17440 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17441 if (res == -2)
17442 goto internal_error;
17443 if (res == -1) {
17444 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17445 }
17446 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017447 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017448 }
17449 }
17450 if (bfmaxinc) {
17451 /* minInclusive <= BASE maxInclusive */
17452 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17453 if (res == -2)
17454 goto internal_error;
Daniel Veillard0a119eb2005-07-20 13:46:00 +000017455 if (res == 1) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017456 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17457 }
17458 }
17459 if (bfminexc) {
17460 /* minInclusive > BASE minExclusive */
17461 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17462 if (res == -2)
17463 goto internal_error;
17464 if (res != 1)
17465 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17466 }
17467 if (bfmaxexc) {
17468 /* minInclusive < BASE maxExclusive */
17469 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17470 if (res == -2)
17471 goto internal_error;
17472 if (res != -1)
17473 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17474 }
17475 }
17476 if (ftotdig && bftotdig) {
17477 /*
17478 * SCC " totalDigits valid restriction"
17479 * totalDigits <= BASE totalDigits
17480 */
17481 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17482 if (res == -2)
17483 goto internal_error;
17484 if (res == 1)
17485 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17486 -1, 1, 1);
17487 if ((res != 0) && (bftotdig->fixed)) {
17488 FACET_RESTR_FIXED_ERR(ftotdig)
17489 }
17490 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017491 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017492 /*
17493 * SCC "fractionDigits valid restriction"
17494 * fractionDigits <= BASE fractionDigits
17495 */
17496 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17497 if (res == -2)
17498 goto internal_error;
17499 if (res == 1)
17500 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17501 -1, 1, 1);
17502 if ((res != 0) && (bffracdig->fixed)) {
17503 FACET_RESTR_FIXED_ERR(ffracdig)
17504 }
17505 }
17506 /*
17507 * SCC "fractionDigits less than or equal to totalDigits"
17508 */
17509 if (! ftotdig)
17510 ftotdig = bftotdig;
17511 if (! ffracdig)
17512 ffracdig = bffracdig;
17513 if (ftotdig && ffracdig) {
17514 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17515 if (res == -2)
17516 goto internal_error;
17517 if (res == 1)
17518 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17519 -1, 1, 0);
17520 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017521 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017522 * *Enumerations* won' be added here, since only the first set
17523 * of enumerations in the ancestor-or-self axis is used
17524 * for validation, plus we need to use the base type of those
17525 * enumerations for whitespace.
17526 *
17527 * *Patterns*: won't be add here, since they are ORed at
17528 * type level and ANDed at ancestor level. This will
17529 * happed during validation by walking the base axis
17530 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017531 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017532 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17533 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017534 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017535 * Special handling of enumerations and patterns.
17536 * TODO: hmm, they should not appear in the set, so remove this.
17537 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017538 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017539 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017540 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017541 /*
17542 * Search for a duplicate facet in the current type.
17543 */
17544 link = type->facetSet;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000017545 /* err = 0; */
17546 /* fixedErr = 0; */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017547 while (link != NULL) {
17548 facet = link->facet;
17549 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017550 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017551 case XML_SCHEMA_FACET_WHITESPACE:
17552 /*
17553 * The whitespace must be stronger.
17554 */
17555 if (facet->whitespace < bfacet->whitespace) {
17556 FACET_RESTR_ERR(flength,
17557 "The 'whitespace' value has to be equal to "
17558 "or stronger than the 'whitespace' value of "
17559 "the base type")
17560 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017561 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017562 (facet->whitespace != bfacet->whitespace)) {
17563 FACET_RESTR_FIXED_ERR(facet)
17564 }
17565 break;
17566 default:
17567 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017568 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017569 /* Duplicate found. */
17570 break;
17571 }
17572 link = link->next;
17573 }
17574 /*
17575 * If no duplicate was found: add the base types's facet
17576 * to the set.
17577 */
17578 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017579 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017580 xmlMalloc(sizeof(xmlSchemaFacetLink));
17581 if (link == NULL) {
17582 xmlSchemaPErrMemory(pctxt,
17583 "deriving facets, creating a facet link", NULL);
17584 return (-1);
17585 }
17586 link->facet = cur->facet;
17587 link->next = NULL;
17588 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017589 type->facetSet = link;
17590 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017591 last->next = link;
17592 last = link;
17593 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017594
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017595 }
17596
17597 return (0);
17598internal_error:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017599 PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17600 "an error occured");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017601 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017602}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017603
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017604static int
17605xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17606 xmlSchemaTypePtr type)
17607{
17608 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17609 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017610 * The actual value is then formed by replacing any union type
17611 * definition in the ·explicit members· with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017612 * {member type definitions}, in order.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017613 *
17614 * TODO: There's a bug entry at
17615 * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17616 * which indicates that we'll keep the union types the future.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017617 */
17618 link = type->memberTypes;
17619 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017620
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017621 if (WXS_IS_TYPE_NOT_FIXED(link->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000017622 xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017623
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017624 if (WXS_IS_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017625 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017626 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017627 link->type = subLink->type;
17628 if (subLink->next != NULL) {
17629 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017630 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017631 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017632 while (subLink != NULL) {
17633 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017634 xmlMalloc(sizeof(xmlSchemaTypeLink));
17635 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017636 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017637 NULL);
17638 return (-1);
17639 }
17640 newLink->type = subLink->type;
17641 prevLink->next = newLink;
17642 prevLink = newLink;
17643 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017644
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017645 subLink = subLink->next;
17646 }
17647 }
17648 }
17649 }
17650 link = link->next;
17651 }
17652 return (0);
17653}
17654
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017655static void
17656xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17657{
17658 int has = 0, needVal = 0, normVal = 0;
17659
17660 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17661 if (has) {
17662 needVal = (type->baseType->flags &
17663 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17664 normVal = (type->baseType->flags &
17665 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17666 }
17667 if (type->facets != NULL) {
17668 xmlSchemaFacetPtr fac;
17669
17670 for (fac = type->facets; fac != NULL; fac = fac->next) {
17671 switch (fac->type) {
17672 case XML_SCHEMA_FACET_WHITESPACE:
17673 break;
17674 case XML_SCHEMA_FACET_PATTERN:
17675 normVal = 1;
17676 has = 1;
17677 break;
17678 case XML_SCHEMA_FACET_ENUMERATION:
17679 needVal = 1;
17680 normVal = 1;
17681 has = 1;
17682 break;
17683 default:
17684 has = 1;
17685 break;
17686 }
17687 }
17688 }
17689 if (normVal)
17690 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17691 if (needVal)
17692 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17693 if (has)
17694 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17695
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017696 if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017697 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17698 /*
17699 * OPTIMIZE VAL TODO: Some facets need a computed value.
17700 */
17701 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17702 (prim->builtInType != XML_SCHEMAS_STRING)) {
17703 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17704 }
17705 }
17706}
17707
17708static int
17709xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17710{
17711
17712
17713 /*
17714 * Evaluate the whitespace-facet value.
17715 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017716 if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017717 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17718 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017719 } else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017720 return (0);
17721
17722 if (type->facetSet != NULL) {
17723 xmlSchemaFacetLinkPtr lin;
17724
17725 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17726 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17727 switch (lin->facet->whitespace) {
17728 case XML_SCHEMAS_FACET_PRESERVE:
17729 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17730 break;
17731 case XML_SCHEMAS_FACET_REPLACE:
17732 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17733 break;
17734 case XML_SCHEMAS_FACET_COLLAPSE:
17735 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17736 break;
17737 default:
17738 return (-1);
17739 }
17740 return (0);
17741 }
17742 }
17743 }
17744 /*
17745 * For all ·atomic· datatypes other than string (and types ·derived·
17746 * by ·restriction· from it) the value of whiteSpace is fixed to
17747 * collapse
17748 */
17749 {
17750 xmlSchemaTypePtr anc;
17751
17752 for (anc = type->baseType; anc != NULL &&
17753 anc->builtInType != XML_SCHEMAS_ANYTYPE;
17754 anc = anc->baseType) {
17755
17756 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17757 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17758 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17759
17760 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17761 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17762 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17763
17764 } else
17765 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17766 break;
17767 }
17768 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017769 }
17770 return (0);
17771}
17772
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017773static int
17774xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17775 xmlSchemaTypePtr type)
Daniel Veillard4255d502002-04-16 15:50:10 +000017776{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017777 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17778 return(0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017779 if (! WXS_IS_TYPE_NOT_FIXED_1(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017780 return(0);
17781 type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017782
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017783 if (WXS_IS_LIST(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017784 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017785 * Corresponds to <simpleType><list>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017786 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017787 if (type->subtypes == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017788 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017789 * This one is really needed, so get out.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017790 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017791 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017792 "list type has no item-type assigned");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017793 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017794 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017795 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017796 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017797 * Corresponds to <simpleType><union>...
17798 */
17799 if (type->memberTypes == NULL) {
17800 /*
17801 * This one is really needed, so get out.
17802 */
17803 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17804 "union type has no member-types assigned");
17805 return(-1);
17806 }
17807 } else {
17808 /*
17809 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017810 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017811 if (type->baseType == NULL) {
17812 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17813 "type has no base-type assigned");
17814 return(-1);
17815 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017816 if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017817 if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17818 return(-1);
17819 /*
17820 * Variety
17821 * If the <restriction> alternative is chosen, then the
17822 * {variety} of the {base type definition}.
17823 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017824 if (WXS_IS_ATOMIC(type->baseType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017825 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017826 else if (WXS_IS_LIST(type->baseType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017827 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017828 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017829 * Inherit the itemType.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017830 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017831 type->subtypes = type->baseType->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017832 } else if (WXS_IS_UNION(type->baseType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017833 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017834 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017835 * NOTE that we won't assign the memberTypes of the base,
17836 * since this will make trouble when freeing them; we will
17837 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017838 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017839 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017840 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017841 return(0);
17842}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017843
Daniel Veillard8651f532002-04-17 09:06:27 +000017844#ifdef DEBUG_TYPE
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017845xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
17846 xmlSchemaTypePtr type)
17847{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017848 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017849 xmlGenericError(xmlGenericErrorContext,
17850 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017851 type->node->doc->URL,
17852 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000017853 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017854 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000017855 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017856 if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017857 switch (type->contentType) {
17858 case XML_SCHEMA_CONTENT_SIMPLE:
17859 xmlGenericError(xmlGenericErrorContext, "simple\n");
17860 break;
17861 case XML_SCHEMA_CONTENT_ELEMENTS:
17862 xmlGenericError(xmlGenericErrorContext, "elements\n");
17863 break;
17864 case XML_SCHEMA_CONTENT_UNKNOWN:
17865 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
17866 break;
17867 case XML_SCHEMA_CONTENT_EMPTY:
17868 xmlGenericError(xmlGenericErrorContext, "empty\n");
17869 break;
17870 case XML_SCHEMA_CONTENT_MIXED:
17871 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017872 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017873 xmlGenericError(xmlGenericErrorContext,
17874 "mixed as emptiable particle\n");
17875 else
17876 xmlGenericError(xmlGenericErrorContext, "mixed\n");
17877 break;
17878 /* Removed, since not used. */
17879 /*
17880 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
17881 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
17882 break;
17883 */
17884 case XML_SCHEMA_CONTENT_BASIC:
17885 xmlGenericError(xmlGenericErrorContext, "basic\n");
17886 break;
17887 default:
17888 xmlGenericError(xmlGenericErrorContext,
17889 "not registered !!!\n");
17890 break;
17891 }
Daniel Veillard8651f532002-04-17 09:06:27 +000017892 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017893}
Daniel Veillard8651f532002-04-17 09:06:27 +000017894#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017895
17896/*
17897* 3.14.6 Constraints on Simple Type Definition Schema Components
17898*/
17899static int
17900xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
17901 xmlSchemaTypePtr type)
17902{
17903 int res, olderrs = pctxt->nberrors;
17904
17905 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17906 return(-1);
17907
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017908 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017909 return(0);
17910
17911 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
17912 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
17913
17914 if (type->baseType == NULL) {
17915 PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
17916 "missing baseType");
17917 goto exit_failure;
17918 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017919 if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000017920 xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017921 /*
17922 * If a member type of a union is a union itself, we need to substitute
17923 * that member type for its member types.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017924 * NOTE that this might change in WXS 1.1; i.e. we will keep the union
17925 * types in WXS 1.1.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017926 */
17927 if ((type->memberTypes != NULL) &&
17928 (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
17929 return(-1);
17930 /*
17931 * SPEC src-simple-type 1
17932 * "The corresponding simple type definition, if any, must satisfy
17933 * the conditions set out in Constraints on Simple Type Definition
17934 * Schema Components (§3.14.6)."
17935 */
17936 /*
17937 * Schema Component Constraint: Simple Type Definition Properties Correct
17938 * (st-props-correct)
17939 */
17940 res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
17941 HFAILURE HERROR
17942 /*
17943 * Schema Component Constraint: Derivation Valid (Restriction, Simple)
17944 * (cos-st-restricts)
17945 */
17946 res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
17947 HFAILURE HERROR
17948 /*
17949 * TODO: Removed the error report, since it got annoying to get an
17950 * extra error report, if anything failed until now.
17951 * Enable this if needed.
17952 *
17953 * xmlSchemaPErr(ctxt, type->node,
17954 * XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
17955 * "Simple type '%s' does not satisfy the constraints "
17956 * "on simple type definitions.\n",
17957 * type->name, NULL);
17958 */
17959 /*
17960 * Schema Component Constraint: Simple Type Restriction (Facets)
17961 * (st-restrict-facets)
17962 */
17963 res = xmlSchemaCheckFacetValues(type, pctxt);
17964 HFAILURE HERROR
17965 if ((type->facetSet != NULL) ||
17966 (type->baseType->facetSet != NULL)) {
17967 res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
17968 HFAILURE HERROR
17969 }
17970 /*
17971 * Whitespace value.
17972 */
17973 res = xmlSchemaTypeFixupWhitespace(type);
17974 HFAILURE HERROR
17975 xmlSchemaTypeFixupOptimFacets(type);
17976
17977exit_error:
17978#ifdef DEBUG_TYPE
17979 xmlSchemaDebugFixedType(pctxt, type);
17980#endif
17981 if (olderrs != pctxt->nberrors)
17982 return(pctxt->err);
17983 return(0);
17984
17985exit_failure:
17986#ifdef DEBUG_TYPE
17987 xmlSchemaDebugFixedType(pctxt, type);
17988#endif
17989 return(-1);
17990}
17991
17992static int
17993xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
17994 xmlSchemaTypePtr type)
17995{
17996 int res = 0, olderrs = pctxt->nberrors;
17997 xmlSchemaTypePtr baseType = type->baseType;
17998
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017999 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018000 return(0);
18001 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18002 if (baseType == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018003 PERROR_INT("xmlSchemaFixupComplexType",
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018004 "missing baseType");
18005 goto exit_failure;
18006 }
18007 /*
18008 * Fixup the base type.
18009 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018010 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018011 xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018012 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18013 /*
18014 * Skip fixup if the base type is invalid.
18015 * TODO: Generate a warning!
18016 */
18017 return(0);
18018 }
18019 /*
18020 * This basically checks if the base type can be derived.
18021 */
18022 res = xmlSchemaCheckSRCCT(pctxt, type);
18023 HFAILURE HERROR
18024 /*
18025 * Fixup the content type.
18026 */
18027 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18028 /*
18029 * Corresponds to <complexType><simpleContent>...
18030 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018031 if ((WXS_IS_COMPLEX(baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018032 (baseType->contentTypeDef != NULL) &&
18033 (WXS_IS_RESTRICTION(type))) {
18034 xmlSchemaTypePtr contentBase, content;
18035#ifdef ENABLE_NAMED_LOCALS
18036 char buf[30];
18037 const xmlChar *tmpname;
18038#endif
18039 /*
18040 * SPEC (1) If <restriction> + base type is <complexType>,
18041 * "whose own {content type} is a simple type..."
18042 */
18043 if (type->contentTypeDef != NULL) {
18044 /*
18045 * SPEC (1.1) "the simple type definition corresponding to the
18046 * <simpleType> among the [children] of <restriction> if there
18047 * is one;"
18048 * Note that this "<simpleType> among the [children]" was put
18049 * into ->contentTypeDef during parsing.
18050 */
18051 contentBase = type->contentTypeDef;
18052 type->contentTypeDef = NULL;
18053 } else {
18054 /*
18055 * (1.2) "...otherwise (<restriction> has no <simpleType>
18056 * among its [children]), the simple type definition which
18057 * is the {content type} of the ... base type."
18058 */
18059 contentBase = baseType->contentTypeDef;
18060 }
18061 /*
18062 * SPEC
18063 * "... a simple type definition which restricts the simple
18064 * type definition identified in clause 1.1 or clause 1.2
18065 * with a set of facet components"
18066 *
18067 * Create the anonymous simple type, which will be the content
18068 * type of the complex type.
18069 */
18070#ifdef ENABLE_NAMED_LOCALS
18071 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18072 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018073 content = xmlSchemaAddType(pctxt, pctxt->schema,
18074 XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018075 type->node, 0);
18076#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018077 content = xmlSchemaAddType(pctxt, pctxt->schema,
18078 XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018079 type->node, 0);
18080#endif
18081 if (content == NULL)
18082 goto exit_failure;
18083 /*
18084 * We will use the same node as for the <complexType>
18085 * to have it somehow anchored in the schema doc.
18086 */
18087 content->type = XML_SCHEMA_TYPE_SIMPLE;
18088 content->baseType = contentBase;
18089 /*
18090 * Move the facets, previously anchored on the
18091 * complexType during parsing.
18092 */
18093 content->facets = type->facets;
18094 type->facets = NULL;
18095 content->facetSet = type->facetSet;
18096 type->facetSet = NULL;
18097
18098 type->contentTypeDef = content;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018099 if (WXS_IS_TYPE_NOT_FIXED(contentBase))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018100 xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018101 /*
18102 * Fixup the newly created type. We don't need to check
18103 * for circularity here.
18104 */
18105 res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18106 HFAILURE HERROR
18107 res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18108 HFAILURE HERROR
18109
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018110 } else if ((WXS_IS_COMPLEX(baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018111 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18112 (WXS_IS_RESTRICTION(type))) {
18113 /*
18114 * SPEC (2) If <restriction> + base is a mixed <complexType> with
18115 * an emptiable particle, then a simple type definition which
18116 * restricts the <restriction>'s <simpleType> child.
18117 */
18118 if ((type->contentTypeDef == NULL) ||
18119 (type->contentTypeDef->baseType == NULL)) {
18120 /*
18121 * TODO: Check if this ever happens.
18122 */
18123 xmlSchemaPCustomErr(pctxt,
18124 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018125 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018126 "Internal error: xmlSchemaTypeFixup, "
18127 "complex type '%s': the <simpleContent><restriction> "
18128 "is missing a <simpleType> child, but was not catched "
18129 "by xmlSchemaCheckSRCCT()", type->name);
18130 goto exit_failure;
18131 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018132 } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018133 /*
18134 * SPEC (3) If <extension> + base is <complexType> with
18135 * <simpleType> content, "...then the {content type} of that
18136 * complex type definition"
18137 */
18138 if (baseType->contentTypeDef == NULL) {
18139 /*
18140 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18141 * should have catched this already.
18142 */
18143 xmlSchemaPCustomErr(pctxt,
18144 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018145 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018146 "Internal error: xmlSchemaTypeFixup, "
18147 "complex type '%s': the <extension>ed base type is "
18148 "a complex type with no simple content type",
18149 type->name);
18150 goto exit_failure;
18151 }
18152 type->contentTypeDef = baseType->contentTypeDef;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018153 } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018154 /*
18155 * SPEC (4) <extension> + base is <simpleType>
18156 * "... then that simple type definition"
18157 */
18158 type->contentTypeDef = baseType;
18159 } else {
18160 /*
18161 * TODO: Check if this ever happens.
18162 */
18163 xmlSchemaPCustomErr(pctxt,
18164 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018165 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018166 "Internal error: xmlSchemaTypeFixup, "
18167 "complex type '%s' with <simpleContent>: unhandled "
18168 "derivation case", type->name);
18169 goto exit_failure;
18170 }
18171 } else {
18172 int dummySequence = 0;
18173 xmlSchemaParticlePtr particle =
18174 (xmlSchemaParticlePtr) type->subtypes;
18175 /*
18176 * Corresponds to <complexType><complexContent>...
18177 *
18178 * NOTE that the effective mixed was already set during parsing of
18179 * <complexType> and <complexContent>; its flag value is
18180 * XML_SCHEMAS_TYPE_MIXED.
18181 *
18182 * Compute the "effective content":
18183 * (2.1.1) + (2.1.2) + (2.1.3)
18184 */
18185 if ((particle == NULL) ||
18186 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18187 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18188 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18189 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18190 (particle->minOccurs == 0))) &&
18191 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18192 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18193 /*
18194 * SPEC (2.1.4) "If the ·effective mixed· is true, then
18195 * a particle whose properties are as follows:..."
18196 *
18197 * Empty sequence model group with
18198 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18199 * NOTE that we sill assign it the <complexType> node to
18200 * somehow anchor it in the doc.
18201 */
18202 if ((particle == NULL) ||
18203 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18204 /*
18205 * Create the particle.
18206 */
18207 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
18208 type->node, 1, 1);
18209 if (particle == NULL)
18210 goto exit_failure;
18211 /*
18212 * Create the model group.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018213 */ /* URGENT TODO: avoid adding to pending items. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018214 particle->children = (xmlSchemaTreeItemPtr)
18215 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18216 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18217 if (particle->children == NULL)
18218 goto exit_failure;
18219
18220 type->subtypes = (xmlSchemaTypePtr) particle;
18221 }
18222 dummySequence = 1;
18223 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18224 } else {
18225 /*
18226 * SPEC (2.1.5) "otherwise empty"
18227 */
18228 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18229 }
18230 } else {
18231 /*
18232 * SPEC (2.2) "otherwise the particle corresponding to the
18233 * <all>, <choice>, <group> or <sequence> among the
18234 * [children]."
18235 */
18236 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18237 }
18238 /*
18239 * Compute the "content type".
18240 */
18241 if (WXS_IS_RESTRICTION(type)) {
18242 /*
18243 * SPEC (3.1) "If <restriction>..."
18244 * (3.1.1) + (3.1.2) */
18245 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18246 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18247 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18248 }
18249 } else {
18250 /*
18251 * SPEC (3.2) "If <extension>..."
18252 */
18253 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18254 /*
18255 * SPEC (3.2.1)
18256 */
18257 type->contentType = baseType->contentType;
18258 type->subtypes = baseType->subtypes;
18259 /*
18260 * NOTE that the effective mixed is ignored here.
18261 */
18262 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18263 /*
18264 * SPEC (3.2.2)
18265 */
18266 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18267 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18268 } else {
18269 /*
18270 * SPEC (3.2.3)
18271 */
18272 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18273 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18274 /*
18275 * "A model group whose {compositor} is sequence and whose
18276 * {particles} are..."
18277 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018278 if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18279 (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18280 ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18281 XML_SCHEMA_TYPE_ALL))
18282 {
18283 /*
18284 * SPEC cos-all-limited (1)
18285 */
18286 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18287 /* TODO: error code */
18288 XML_SCHEMAP_COS_ALL_LIMITED,
18289 WXS_ITEM_NODE(type), NULL,
18290 "The type has an 'all' model group in its "
18291 "{content type} and thus cannot be derived from "
18292 "a non-empty type, since this would produce a "
18293 "'sequence' model group containing the 'all' "
18294 "model group; 'all' model groups are not "
18295 "allowed to appear inside other model groups",
18296 NULL, NULL);
18297
18298 } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18299 (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18300 ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18301 XML_SCHEMA_TYPE_ALL))
18302 {
18303 /*
18304 * SPEC cos-all-limited (1)
18305 */
18306 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18307 /* TODO: error code */
18308 XML_SCHEMAP_COS_ALL_LIMITED,
18309 WXS_ITEM_NODE(type), NULL,
18310 "A type cannot be derived by extension from a type "
18311 "which has an 'all' model group in its "
18312 "{content type}, since this would produce a "
18313 "'sequence' model group containing the 'all' "
18314 "model group; 'all' model groups are not "
18315 "allowed to appear inside other model groups",
18316 NULL, NULL);
18317
18318 } else if (! dummySequence) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018319 xmlSchemaTreeItemPtr effectiveContent =
18320 (xmlSchemaTreeItemPtr) type->subtypes;
18321 /*
18322 * Create the particle.
18323 */
18324 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
18325 type->node, 1, 1);
18326 if (particle == NULL)
18327 goto exit_failure;
18328 /*
18329 * Create the "sequence" model group.
18330 */
18331 particle->children = (xmlSchemaTreeItemPtr)
18332 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18333 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18334 if (particle->children == NULL)
18335 goto exit_failure;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018336 WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018337 /*
18338 * SPEC "the particle of the {content type} of
18339 * the ... base ..."
18340 * Create a duplicate of the base type's particle
18341 * and assign its "term" to it.
18342 */
18343 particle->children->children =
18344 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18345 pctxt->schema, type->node,
18346 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
18347 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
18348 if (particle->children->children == NULL)
18349 goto exit_failure;
18350 particle = (xmlSchemaParticlePtr)
18351 particle->children->children;
18352 particle->children =
18353 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
18354 /*
18355 * SPEC "followed by the ·effective content·."
18356 */
18357 particle->next = effectiveContent;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018358 /*
18359 * This all will result in:
18360 * new-particle
18361 * --> new-sequence(
18362 * new-particle
18363 * --> base-model,
18364 * this-particle
18365 * --> this-model
18366 * )
18367 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018368 } else {
18369 /*
18370 * This is the case when there is already an empty
18371 * <sequence> with minOccurs==maxOccurs==1.
18372 * Just add the base types's content type.
18373 * NOTE that, although we miss to add an intermediate
18374 * <sequence>, this should produce no difference to
18375 * neither the regex compilation of the content model,
18376 * nor to the complex type contraints.
18377 */
18378 particle->children->children =
18379 (xmlSchemaTreeItemPtr) baseType->subtypes;
18380 }
18381 }
18382 }
18383 }
18384 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018385 * Now fixup attribute uses:
18386 * - expand attr. group references
18387 * - intersect attribute wildcards
18388 * - inherit attribute uses of the base type
18389 * - inherit or union attr. wildcards if extending
18390 * - apply attr. use prohibitions if restricting
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018391 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018392 res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018393 HFAILURE HERROR
18394 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018395 * Apply the complex type component constraints; this will not
18396 * check attributes, since this is done in
18397 * xmlSchemaFixupTypeAttributeUses().
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018398 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018399 res = xmlSchemaCheckCTComponent(pctxt, type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018400 HFAILURE HERROR
18401
18402#ifdef DEBUG_TYPE
18403 xmlSchemaDebugFixedType(pctxt, type);
18404#endif
18405 if (olderrs != pctxt->nberrors)
18406 return(pctxt->err);
18407 else
18408 return(0);
18409
18410exit_error:
18411 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18412#ifdef DEBUG_TYPE
18413 xmlSchemaDebugFixedType(pctxt, type);
18414#endif
18415 return(pctxt->err);
18416
18417exit_failure:
18418 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18419#ifdef DEBUG_TYPE
18420 xmlSchemaDebugFixedType(pctxt, type);
18421#endif
18422 return(-1);
18423}
18424
18425
18426/**
18427 * xmlSchemaTypeFixup:
18428 * @typeDecl: the schema type definition
18429 * @ctxt: the schema parser context
18430 *
18431 * Fixes the content model of the type.
18432 * URGENT TODO: We need an int result!
18433 */
18434static int
18435xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018436 xmlSchemaAbstractCtxtPtr actxt)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018437{
18438 if (type == NULL)
18439 return(0);
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018440 if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18441 AERROR_INT("xmlSchemaTypeFixup",
18442 "this function needs a parser context");
18443 return(-1);
18444 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018445 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018446 return(0);
18447 if (type->type == XML_SCHEMA_TYPE_COMPLEX)
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018448 return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018449 else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018450 return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018451 return(0);
Daniel Veillard4255d502002-04-16 15:50:10 +000018452}
18453
18454/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018455 * xmlSchemaCheckFacet:
18456 * @facet: the facet
18457 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000018458 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018459 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018460 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018461 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018462 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018463 * Returns 0 if valid, a positive error code if not valid and
18464 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018465 */
18466int
18467xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018468 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018469 xmlSchemaParserCtxtPtr pctxt,
18470 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018471{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018472 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018473
Daniel Veillardce682bc2004-11-05 17:22:25 +000018474 if ((facet == NULL) || (typeDecl == NULL))
18475 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018476 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018477 * TODO: will the parser context be given if used from
18478 * the relaxNG module?
18479 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018480 if (pctxt == NULL)
18481 ctxtGiven = 0;
18482 else
18483 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018484
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018485 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018486 case XML_SCHEMA_FACET_MININCLUSIVE:
18487 case XML_SCHEMA_FACET_MINEXCLUSIVE:
18488 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018489 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18490 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018491 /*
18492 * Okay we need to validate the value
18493 * at that point.
18494 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018495 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018496
18497 /* 4.3.5.5 Constraints on enumeration Schema Components
18498 * Schema Component Constraint: enumeration valid restriction
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018499 * It is an ·error· if any member of {value} is not in the
18500 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018501 *
18502 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018503 * The value ·must· be in the
18504 * ·value space· of the ·base type·.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018505 */
18506 /*
18507 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018508 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018509 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018510 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018511 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018512 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018513 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018514 */
18515 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18516 base = typeDecl->baseType;
18517 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018518 PERROR_INT("xmlSchemaCheckFacet",
18519 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018520 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018521 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018522 } else
18523 base = typeDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018524
18525 if (! ctxtGiven) {
18526 /*
18527 * A context is needed if called from RelaxNG.
18528 */
18529 pctxt = xmlSchemaNewParserCtxt("*");
18530 if (pctxt == NULL)
18531 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018532 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018533 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018534 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018535 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018536 * facet->node is just the node holding the facet
18537 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018538 * of the facet.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018539 */
18540 ret = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018541 ACTXT_CAST pctxt, facet->node, base,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018542 facet->value, &(facet->val), 1, 1, 0);
18543 if (ret != 0) {
18544 if (ret < 0) {
18545 /* No error message for RelaxNG. */
18546 if (ctxtGiven) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018547 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018548 XML_SCHEMAP_INTERNAL, facet->node, NULL,
18549 "Internal error: xmlSchemaCheckFacet, "
18550 "failed to validate the value '%s' of the "
18551 "facet '%s' against the base type",
18552 facet->value, xmlSchemaFacetTypeToString(facet->type));
18553 }
18554 goto internal_error;
18555 }
18556 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18557 /* No error message for RelaxNG. */
18558 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018559 xmlChar *str = NULL;
18560
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018561 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018562 ret, facet->node, WXS_BASIC_CAST facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018563 "The value '%s' of the facet does not validate "
18564 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018565 facet->value,
18566 xmlSchemaFormatQName(&str,
18567 base->targetNamespace, base->name));
18568 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018569 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018570 goto exit;
18571 } else if (facet->val == NULL) {
18572 if (ctxtGiven) {
18573 PERROR_INT("xmlSchemaCheckFacet",
18574 "value was not computed");
18575 }
18576 TODO
18577 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018578 break;
18579 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018580 case XML_SCHEMA_FACET_PATTERN:
18581 facet->regexp = xmlRegexpCompile(facet->value);
18582 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018583 ret = XML_SCHEMAP_REGEXP_INVALID;
18584 /* No error message for RelaxNG. */
18585 if (ctxtGiven) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018586 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018587 ret, facet->node, WXS_BASIC_CAST typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018588 "The value '%s' of the facet 'pattern' is not a "
18589 "valid regular expression",
18590 facet->value, NULL);
18591 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018592 }
18593 break;
18594 case XML_SCHEMA_FACET_TOTALDIGITS:
18595 case XML_SCHEMA_FACET_FRACTIONDIGITS:
18596 case XML_SCHEMA_FACET_LENGTH:
18597 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018598 case XML_SCHEMA_FACET_MINLENGTH:
18599
18600 if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18601 ret = xmlSchemaValidatePredefinedType(
18602 xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18603 facet->value, &(facet->val));
18604 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018605 ret = xmlSchemaValidatePredefinedType(
18606 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18607 facet->value, &(facet->val));
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018608 }
18609 if (ret != 0) {
18610 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018611 /* No error message for RelaxNG. */
18612 if (ctxtGiven) {
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018613 PERROR_INT("xmlSchemaCheckFacet",
18614 "validating facet value");
18615 }
18616 goto internal_error;
18617 }
18618 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18619 /* No error message for RelaxNG. */
18620 if (ctxtGiven) {
18621 /* error code */
18622 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18623 ret, facet->node, WXS_BASIC_CAST typeDecl,
18624 "The value '%s' of the facet '%s' is not a valid '%s'",
18625 facet->value,
18626 xmlSchemaFacetTypeToString(facet->type),
18627 (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18628 BAD_CAST "nonNegativeInteger" :
18629 BAD_CAST "positiveInteger",
18630 NULL);
18631 }
18632 }
18633 break;
18634
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018635 case XML_SCHEMA_FACET_WHITESPACE:{
18636 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18637 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18638 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18639 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18640 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18641 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18642 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018643 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18644 /* No error message for RelaxNG. */
18645 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018646 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018647 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018648 ret, facet->node, WXS_BASIC_CAST typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018649 "The value '%s' of the facet 'whitespace' is not "
18650 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018651 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018652 }
18653 }
18654 default:
18655 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018656 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018657exit:
18658 if ((! ctxtGiven) && (pctxt != NULL))
18659 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018660 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018661internal_error:
18662 if ((! ctxtGiven) && (pctxt != NULL))
18663 xmlSchemaFreeParserCtxt(pctxt);
18664 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018665}
18666
18667/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018668 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000018669 * @typeDecl: the schema type definition
18670 * @ctxt: the schema parser context
18671 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018672 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000018673 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018674static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018675xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018676 xmlSchemaParserCtxtPtr pctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000018677{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018678 int res, olderrs = pctxt->nberrors;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018679 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018680 /*
18681 * NOTE: It is intended to use the facets list, instead
18682 * of facetSet.
18683 */
18684 if (typeDecl->facets != NULL) {
18685 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018686
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018687 /*
18688 * Temporarily assign the "schema" to the validation context
18689 * of the parser context. This is needed for NOTATION validation.
18690 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018691 if (pctxt->vctxt == NULL) {
18692 if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18693 return(-1);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018694 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018695 pctxt->vctxt->schema = pctxt->schema;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018696 while (facet != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018697 res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18698 HFAILURE
Daniel Veillard01fa6152004-06-29 17:04:39 +000018699 facet = facet->next;
18700 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018701 pctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018702 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018703 if (olderrs != pctxt->nberrors)
18704 return(pctxt->err);
18705 return(0);
18706exit_failure:
18707 return(-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018708}
18709
18710/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018711 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018712 * @ctxtMGroup: the searched model group
18713 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018714 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018715 *
18716 * This one is intended to be used by
18717 * xmlSchemaCheckGroupDefCircular only.
18718 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018719 * Returns the particle with the circular model group definition reference,
18720 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018721 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018722static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018723xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018724 xmlSchemaTreeItemPtr particle)
18725{
18726 xmlSchemaTreeItemPtr circ = NULL;
18727 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018728 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018729
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018730 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018731 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018732 if (term == NULL)
18733 continue;
18734 switch (term->type) {
18735 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018736 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018737 if (gdef == groupDef)
18738 return (particle);
18739 /*
18740 * Mark this model group definition to avoid infinite
18741 * recursion on circular references not yet examined.
18742 */
18743 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18744 continue;
18745 if (gdef->children != NULL) {
18746 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18747 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18748 gdef->children->children);
18749 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18750 if (circ != NULL)
18751 return (circ);
18752 }
18753 break;
18754 case XML_SCHEMA_TYPE_SEQUENCE:
18755 case XML_SCHEMA_TYPE_CHOICE:
18756 case XML_SCHEMA_TYPE_ALL:
18757 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18758 if (circ != NULL)
18759 return (circ);
18760 break;
18761 default:
18762 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018763 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018764 }
18765 return (NULL);
18766}
18767
18768/**
18769 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018770 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018771 * @ctxt: the parser context
18772 * @name: the name
18773 *
18774 * Checks for circular references to model group definitions.
18775 */
18776static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018777xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018778 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018779{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018780 /*
18781 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018782 * 2 Circular groups are disallowed. That is, within the {particles}
18783 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018784 * is the group itself.
18785 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018786 if ((item == NULL) ||
18787 (item->type != XML_SCHEMA_TYPE_GROUP) ||
18788 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018789 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018790 {
18791 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018792
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018793 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018794 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018795 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018796 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018797 * TODO: The error report is not adequate: this constraint
18798 * is defined for model groups but not definitions, but since
18799 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018800 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018801 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018802 */
18803 xmlSchemaPCustomErr(ctxt,
18804 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018805 NULL, WXS_ITEM_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018806 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018807 "defined", xmlSchemaFormatQName(&str,
18808 item->targetNamespace, item->name));
18809 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018810 /*
18811 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018812 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018813 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018814 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018815 }
18816 }
18817}
18818
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018819/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018820 * xmlSchemaModelGroupToModelGroupDefFixup:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018821 * @ctxt: the parser context
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018822 * @mg: the model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018823 *
18824 * Assigns the model group of model group definitions to the "term"
18825 * of the referencing particle.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018826 * In xmlSchemaResolveModelGroupParticleReferences the model group
18827 * definitions were assigned to the "term", since needed for the
18828 * circularity check.
18829 *
18830 * Schema Component Constraint:
18831 * All Group Limited (cos-all-limited) (1.2)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018832 */
18833static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018834xmlSchemaModelGroupToModelGroupDefFixup(
18835 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18836 xmlSchemaModelGroupPtr mg)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018837{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018838 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
18839
18840 while (particle != NULL) {
18841 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
18842 ((WXS_PARTICLE_TERM(particle))->type !=
18843 XML_SCHEMA_TYPE_GROUP))
18844 {
18845 particle = WXS_PTC_CAST particle->next;
18846 continue;
18847 }
18848 if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
18849 /*
18850 * TODO: Remove the particle.
18851 */
18852 WXS_PARTICLE_TERM(particle) = NULL;
18853 particle = WXS_PTC_CAST particle->next;
18854 continue;
18855 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018856 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018857 * Assign the model group to the {term} of the particle.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018858 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018859 WXS_PARTICLE_TERM(particle) =
18860 WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
18861
18862 particle = WXS_PTC_CAST particle->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018863 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018864}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018865
18866/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018867 * xmlSchemaCheckAttrGroupCircularRecur:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018868 * @ctxtGr: the searched attribute group
18869 * @attr: the current attribute list to be processed
18870 *
18871 * This one is intended to be used by
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018872 * xmlSchemaCheckAttrGroupCircular only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018873 *
18874 * Returns the circular attribute grou reference, otherwise NULL.
18875 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018876static xmlSchemaQNameRefPtr
18877xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
18878 xmlSchemaItemListPtr list)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018879{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018880 xmlSchemaAttributeGroupPtr gr;
18881 xmlSchemaQNameRefPtr ref, circ;
18882 int i;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018883 /*
18884 * We will search for an attribute group reference which
18885 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018886 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018887 for (i = 0; i < list->nbItems; i++) {
18888 ref = list->items[i];
18889 if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
18890 (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
18891 (ref->item != NULL))
18892 {
18893 gr = WXS_ATTR_GROUP_CAST ref->item;
18894 if (gr == ctxtGr)
18895 return(ref);
18896 if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
18897 continue;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018898 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018899 * Mark as visited to avoid infinite recursion on
18900 * circular references not yet examined.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018901 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018902 if ((gr->attrUses) &&
18903 (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
18904 {
18905 gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
18906 circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
18907 (xmlSchemaItemListPtr) gr->attrUses);
18908 gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
18909 if (circ != NULL)
18910 return (circ);
18911 }
18912
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018913 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018914 }
18915 return (NULL);
18916}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018917
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018918/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018919 * xmlSchemaCheckAttrGroupCircular:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018920 * attrGr: the attribute group definition
18921 * @ctxt: the parser context
18922 * @name: the name
18923 *
18924 * Checks for circular references of attribute groups.
18925 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018926static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018927xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018928 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018929{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018930 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018931 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018932 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018933 * 3 Circular group reference is disallowed outside <redefine>.
18934 * That is, unless this element information item's parent is
18935 * <redefine>, then among the [children], if any, there must
18936 * not be an <attributeGroup> with ref [attribute] which resolves
18937 * to the component corresponding to this <attributeGroup>. Indirect
18938 * circularity is also ruled out. That is, when QName resolution
18939 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
18940 * any <attributeGroup>s with a ref [attribute] among the [children],
18941 * it must not be the case that a ·QName· is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018942 * which resolves to the component corresponding to this <attributeGroup>.
18943 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018944 if (attrGr->attrUses == NULL)
18945 return(0);
18946 else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
18947 return(0);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018948 else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018949 xmlSchemaQNameRefPtr circ;
18950
18951 circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
18952 (xmlSchemaItemListPtr) attrGr->attrUses);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018953 if (circ != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018954 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018955 /*
18956 * TODO: Report the referenced attr group as QName.
18957 */
18958 xmlSchemaPCustomErr(ctxt,
18959 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018960 NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018961 "Circular reference to the attribute group '%s' "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018962 "defined", xmlSchemaGetComponentQName(&str, attrGr));
18963 FREE_AND_NULL(str);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018964 /*
18965 * NOTE: We will cut the reference to avoid further
18966 * confusion of the processor.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018967 * BADSPEC TODO: The spec should define how to process in this case.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018968 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018969 circ->item = NULL;
18970 return(ctxt->err);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018971 }
18972 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018973 return(0);
18974}
18975
18976static int
18977xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
18978 xmlSchemaAttributeGroupPtr attrGr);
18979
18980/**
18981 * xmlSchemaExpandAttributeGroupRefs:
18982 * @pctxt: the parser context
18983 * @node: the node of the component holding the attribute uses
18984 * @completeWild: the intersected wildcard to be returned
18985 * @list: the attribute uses
18986 *
18987 * Substitutes contained attribute group references
18988 * for their attribute uses. Wilcards are intersected.
18989 * Attribute use prohibitions are removed from the list
18990 * and returned via the @prohibs list.
18991 * Pointlessness of attr. prohibs, if a matching attr. decl
18992 * is existent a well, are checked.
18993 */
18994static int
18995xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
18996 xmlSchemaBasicItemPtr item,
18997 xmlSchemaWildcardPtr *completeWild,
18998 xmlSchemaItemListPtr list,
18999 xmlSchemaItemListPtr prohibs)
19000{
19001 xmlSchemaAttributeGroupPtr gr;
19002 xmlSchemaAttributeUsePtr use;
19003 xmlSchemaItemListPtr sublist;
19004 int i, j;
19005 int created = (*completeWild == NULL) ? 0 : 1;
19006
19007 if (prohibs)
19008 prohibs->nbItems = 0;
19009
19010 for (i = 0; i < list->nbItems; i++) {
19011 use = list->items[i];
19012
19013 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19014 if (prohibs == NULL) {
19015 PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19016 "unexpected attr prohibition found");
19017 return(-1);
19018 }
19019 /*
19020 * Remove from attribute uses.
19021 */
19022 if (xmlSchemaItemListRemove(list, i) == -1)
19023 return(-1);
19024 i--;
19025 /*
19026 * Note that duplicate prohibitions were already
19027 * handled at parsing time.
19028 */
19029 /*
19030 * Add to list of prohibitions.
19031 */
19032 xmlSchemaItemListAddSize(prohibs, 2, use);
19033 continue;
19034 }
19035 if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19036 ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19037 {
19038 if ((WXS_QNAME_CAST use)->item == NULL)
19039 return(-1);
19040 gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19041 /*
19042 * Expand the referenced attr. group.
19043 * TODO: remove this, this is done in a previous step, so
19044 * already done here.
19045 */
19046 if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19047 if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19048 return(-1);
19049 }
19050 /*
19051 * Build the 'complete' wildcard; i.e. intersect multiple
19052 * wildcards.
19053 */
19054 if (gr->attributeWildcard != NULL) {
19055 if (*completeWild == NULL) {
19056 *completeWild = gr->attributeWildcard;
19057 } else {
19058 if (! created) {
19059 xmlSchemaWildcardPtr tmpWild;
19060
19061 /*
19062 * Copy the first encountered wildcard as context,
19063 * except for the annotation.
19064 *
19065 * Although the complete wildcard might not correspond
19066 * to any node in the schema, we will anchor it on
19067 * the node of the owner component.
19068 */
19069 tmpWild = xmlSchemaAddWildcard(pctxt, pctxt->schema,
19070 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19071 WXS_ITEM_NODE(item));
19072 if (tmpWild == NULL)
19073 return(-1);
19074 if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19075 tmpWild, *completeWild) == -1)
19076 return (-1);
19077 tmpWild->processContents = (*completeWild)->processContents;
19078 *completeWild = tmpWild;
19079 created = 1;
19080 }
19081
19082 if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19083 gr->attributeWildcard) == -1)
19084 return(-1);
19085 }
19086 }
19087 /*
19088 * Just remove the reference if the referenced group does not
19089 * contain any attribute uses.
19090 */
19091 if (gr->attrUses == NULL) {
19092 if (xmlSchemaItemListRemove(list, i) == -1)
19093 return(-1);
19094 i--;
19095 continue;
19096 }
19097 /*
19098 * Add the attribute uses.
19099 */
19100 sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19101 if (sublist->nbItems != 0) {
19102 list->items[i] = sublist->items[0];
19103 if (sublist->nbItems != 1) {
19104 for (j = 1; j < sublist->nbItems; j++) {
19105 i++;
19106 if (xmlSchemaItemListInsert(list,
19107 sublist->items[j], i) == -1)
19108 return(-1);
19109 }
19110 }
19111 }
19112 }
19113
19114 }
19115 /*
19116 * Handle pointless prohibitions of declared attributes.
19117 */
19118 if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19119 xmlSchemaAttributeUseProhibPtr prohib;
19120
19121 for (i = prohibs->nbItems -1; i >= 0; i--) {
19122 prohib = prohibs->items[i];
19123 for (j = 0; j < list->nbItems; j++) {
19124 use = list->items[j];
19125
19126 if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19127 (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19128 {
19129 xmlChar *str = NULL;
19130
19131 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19132 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19133 prohib->node, NULL,
19134 "Skipping pointless attribute use prohibition "
19135 "'%s', since a corresponding attribute use "
19136 "exists already in the type definition",
19137 xmlSchemaFormatQName(&str,
19138 prohib->targetNamespace, prohib->name),
19139 NULL, NULL);
19140 FREE_AND_NULL(str);
19141 /*
19142 * Remove the prohibition.
19143 */
19144 if (xmlSchemaItemListRemove(prohibs, i) == -1)
19145 return(-1);
19146 break;
19147 }
19148 }
19149 }
19150 }
19151 return(0);
19152}
19153
19154/**
19155 * xmlSchemaAttributeGroupExpandRefs:
19156 * @pctxt: the parser context
19157 * @attrGr: the attribute group definition
19158 *
19159 * Computation of:
19160 * {attribute uses} property
19161 * {attribute wildcard} property
19162 *
19163 * Substitutes contained attribute group references
19164 * for their attribute uses. Wilcards are intersected.
19165 */
19166static int
19167xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19168 xmlSchemaAttributeGroupPtr attrGr)
19169{
19170 if ((attrGr->attrUses == NULL) ||
19171 (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19172 return(0);
19173
19174 attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19175 if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19176 &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19177 return(-1);
19178 return(0);
19179}
19180
19181/**
19182 * xmlSchemaAttributeGroupExpandRefs:
19183 * @pctxt: the parser context
19184 * @attrGr: the attribute group definition
19185 *
19186 * Substitutes contained attribute group references
19187 * for their attribute uses. Wilcards are intersected.
19188 *
19189 * Schema Component Constraint:
19190 * Attribute Group Definition Properties Correct (ag-props-correct)
19191 */
19192static int
19193xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19194 xmlSchemaAttributeGroupPtr attrGr)
19195{
19196 /*
19197 * SPEC ag-props-correct
19198 * (1) "The values of the properties of an attribute group definition
19199 * must be as described in the property tableau in The Attribute
19200 * Group Definition Schema Component (§3.6.1), modulo the impact of
19201 * Missing Sub-components (§5.3);"
19202 */
19203
19204 if ((attrGr->attrUses != NULL) &&
19205 (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19206 {
19207 xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19208 xmlSchemaAttributeUsePtr use, tmp;
19209 int i, j, hasId = 0;
19210
19211 for (i = uses->nbItems -1; i >= 0; i--) {
19212 use = uses->items[i];
19213 /*
19214 * SPEC ag-props-correct
19215 * (2) "Two distinct members of the {attribute uses} must not have
19216 * {attribute declaration}s both of whose {name}s match and whose
19217 * {target namespace}s are identical."
19218 */
19219 if (i > 0) {
19220 for (j = i -1; j >= 0; j--) {
19221 tmp = uses->items[j];
19222 if ((WXS_ATTRUSE_DECL_NAME(use) ==
19223 WXS_ATTRUSE_DECL_NAME(tmp)) &&
19224 (WXS_ATTRUSE_DECL_TNS(use) ==
19225 WXS_ATTRUSE_DECL_TNS(tmp)))
19226 {
19227 xmlChar *str = NULL;
19228
19229 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19230 XML_SCHEMAP_AG_PROPS_CORRECT,
19231 attrGr->node, WXS_BASIC_CAST attrGr,
19232 "Duplicate %s",
19233 xmlSchemaGetComponentDesignation(&str, use),
19234 NULL);
19235 FREE_AND_NULL(str);
19236 /*
19237 * Remove the duplicate.
19238 */
19239 if (xmlSchemaItemListRemove(uses, i) == -1)
19240 return(-1);
19241 goto next_use;
19242 }
19243 }
19244 }
19245 /*
19246 * SPEC ag-props-correct
19247 * (3) "Two distinct members of the {attribute uses} must not have
19248 * {attribute declaration}s both of whose {type definition}s are or
19249 * are derived from ID."
19250 * TODO: Does 'derived' include member-types of unions?
19251 */
19252 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19253 if (xmlSchemaIsDerivedFromBuiltInType(
19254 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19255 {
19256 if (hasId) {
19257 xmlChar *str = NULL;
19258
19259 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19260 XML_SCHEMAP_AG_PROPS_CORRECT,
19261 attrGr->node, WXS_BASIC_CAST attrGr,
19262 "There must not exist more than one attribute "
19263 "declaration of type 'xs:ID' "
19264 "(or derived from 'xs:ID'). The %s violates this "
19265 "constraint",
19266 xmlSchemaGetComponentDesignation(&str, use),
19267 NULL);
19268 FREE_AND_NULL(str);
19269 if (xmlSchemaItemListRemove(uses, i) == -1)
19270 return(-1);
19271 }
19272 hasId = 1;
19273 }
19274 }
19275next_use: {}
19276 }
19277 }
19278 return(0);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019279}
19280
19281/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019282 * xmlSchemaResolveAttrGroupReferences:
Daniel Veillard13e04c62002-04-23 17:51:29 +000019283 * @attrgrpDecl: the schema attribute definition
19284 * @ctxt: the schema parser context
19285 * @name: the attribute name
19286 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019287 * Resolves references to attribute group definitions.
Daniel Veillard13e04c62002-04-23 17:51:29 +000019288 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019289static int
19290xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19291 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard13e04c62002-04-23 17:51:29 +000019292{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019293 xmlSchemaAttributeGroupPtr group;
Daniel Veillard13e04c62002-04-23 17:51:29 +000019294
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019295 if (ref->item != NULL)
19296 return(0);
19297 group = xmlSchemaGetAttributeGroup(ctxt->schema,
19298 ref->name,
19299 ref->targetNamespace);
19300 if (group == NULL) {
19301 xmlSchemaPResCompAttrErr(ctxt,
19302 XML_SCHEMAP_SRC_RESOLVE,
19303 NULL, ref->node,
19304 "ref", ref->name, ref->targetNamespace,
19305 ref->itemType, NULL);
19306 return(ctxt->err);
Daniel Veillard3646d642004-06-02 19:19:14 +000019307 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019308 ref->item = WXS_BASIC_CAST group;
19309 return(0);
Daniel Veillard13e04c62002-04-23 17:51:29 +000019310}
19311
19312/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019313 * xmlSchemaCheckAttrPropsCorrect:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019314 * @item: an schema attribute declaration/use
19315 * @ctxt: a schema parser context
19316 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019317 *
19318 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019319 * Schema Component Constraint:
19320 * Attribute Declaration Properties Correct (a-props-correct)
Daniel Veillard4255d502002-04-16 15:50:10 +000019321 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019322 * Validates the value constraints of an attribute declaration/use.
19323 * NOTE that this needs the simle type definitions to be already
19324 * builded and checked.
Daniel Veillard4255d502002-04-16 15:50:10 +000019325 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019326static int
19327xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19328 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019329{
19330
19331 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019332 * SPEC a-props-correct (1)
19333 * "The values of the properties of an attribute declaration must
19334 * be as described in the property tableau in The Attribute
19335 * Declaration Schema Component (§3.2.1), modulo the impact of
19336 * Missing Sub-components (§5.3)."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019337 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019338
19339 if (WXS_ATTR_TYPEDEF(attr) == NULL)
19340 return(0);
19341
19342 if (attr->defValue != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019343 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019344
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019345 /*
19346 * SPEC a-props-correct (3)
19347 * "If the {type definition} is or is derived from ID then there
19348 * must not be a {value constraint}."
19349 */
19350 if (xmlSchemaIsDerivedFromBuiltInType(
19351 WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19352 {
19353 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19354 XML_SCHEMAP_A_PROPS_CORRECT_3,
19355 NULL, WXS_BASIC_CAST attr,
19356 "Value constraints are not allowed if the type definition "
19357 "is or is derived from xs:ID",
19358 NULL, NULL);
19359 return(pctxt->err);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019360 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019361 /*
19362 * SPEC a-props-correct (2)
19363 * "if there is a {value constraint}, the canonical lexical
19364 * representation of its value must be ·valid· with respect
19365 * to the {type definition} as defined in String Valid (§3.14.4)."
19366 * TODO: Don't care about the *cononical* stuff here, this requirement
19367 * will be removed in WXS 1.1 anyway.
19368 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019369 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019370 attr->node, WXS_ATTR_TYPEDEF(attr),
19371 attr->defValue, &(attr->defVal),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019372 1, 1, 0);
19373 if (ret != 0) {
19374 if (ret < 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019375 PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019376 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019377 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019378 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019379 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019380 XML_SCHEMAP_A_PROPS_CORRECT_2,
19381 NULL, WXS_BASIC_CAST attr,
19382 "The value of the value constraint is not valid",
19383 NULL, NULL);
19384 return(pctxt->err);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019385 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019386 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019387
19388 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019389}
19390
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019391static xmlSchemaElementPtr
19392xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19393 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019394{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019395 xmlSchemaElementPtr ret;
19396
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019397 if (WXS_SUBST_HEAD(ancestor) == NULL)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019398 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019399 if (WXS_SUBST_HEAD(ancestor) == elemDecl)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019400 return (ancestor);
19401
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019402 if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019403 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019404 WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019405 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019406 WXS_SUBST_HEAD(ancestor));
19407 WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019408
19409 return (ret);
19410}
19411
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019412/**
19413 * xmlSchemaCheckElemPropsCorrect:
19414 * @ctxt: a schema parser context
19415 * @decl: the element declaration
19416 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019417 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019418 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019419 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019420 *
19421 * STATUS:
19422 * missing: (6)
19423 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019424static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019425xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19426 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019427{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019428 int ret = 0;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019429 xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019430 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019431 * SPEC (1) "The values of the properties of an element declaration
19432 * must be as described in the property tableau in The Element
19433 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
19434 * Sub-components (§5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019435 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019436 if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19437 xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019438
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019439 xmlSchemaCheckElementDeclComponent(head, pctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019440 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019441 * SPEC (3) "If there is a non-·absent· {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019442 * affiliation}, then {scope} must be global."
19443 */
19444 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19445 xmlSchemaPCustomErr(pctxt,
19446 XML_SCHEMAP_E_PROPS_CORRECT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019447 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019448 "Only global element declarations can have a "
19449 "substitution group affiliation", NULL);
19450 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019451 }
19452 /*
19453 * TODO: SPEC (6) "Circular substitution groups are disallowed.
19454 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019455 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019456 * property."
19457 */
19458 if (head == elemDecl)
19459 circ = head;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019460 else if (WXS_SUBST_HEAD(head) != NULL)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019461 circ = xmlSchemaCheckSubstGroupCircular(head, head);
19462 else
19463 circ = NULL;
19464 if (circ != NULL) {
19465 xmlChar *strA = NULL, *strB = NULL;
19466
19467 xmlSchemaPCustomErrExt(pctxt,
19468 XML_SCHEMAP_E_PROPS_CORRECT_6,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019469 WXS_BASIC_CAST circ, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019470 "The element declaration '%s' defines a circular "
19471 "substitution group to element declaration '%s'",
19472 xmlSchemaGetComponentQName(&strA, circ),
19473 xmlSchemaGetComponentQName(&strB, head),
19474 NULL);
19475 FREE_AND_NULL(strA)
19476 FREE_AND_NULL(strB)
19477 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19478 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019479 /*
19480 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019481 * the {type definition}
19482 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019483 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019484 * of the {substitution group exclusions} of the {substitution group
19485 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
19486 * (if the {type definition} is complex) or as defined in
19487 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019488 * simple)."
19489 *
19490 * NOTE: {substitution group exclusions} means the values of the
19491 * attribute "final".
19492 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019493
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019494 if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019495 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019496
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019497 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19498 set |= SUBSET_EXTENSION;
19499 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19500 set |= SUBSET_RESTRICTION;
19501
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000019502 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019503 WXS_ELEM_TYPEDEF(head), set) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019504 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19505
19506 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019507 xmlSchemaPCustomErrExt(pctxt,
19508 XML_SCHEMAP_E_PROPS_CORRECT_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019509 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019510 "The type definition '%s' was "
19511 "either rejected by the substitution group "
19512 "affiliation '%s', or not validly derived from its type "
19513 "definition '%s'",
19514 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019515 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019516 xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019517 FREE_AND_NULL(strA)
19518 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019519 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019520 }
19521 }
19522 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019523 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019524 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019525 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019526 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019527 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019528 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019529 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019530 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019531 ((WXS_IS_SIMPLE(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019532 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019533 (WXS_IS_COMPLEX(typeDef) &&
19534 WXS_HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019535 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19536 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019537
19538 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19539 xmlSchemaPCustomErr(pctxt,
19540 XML_SCHEMAP_E_PROPS_CORRECT_5,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019541 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019542 "The type definition (or type definition's content type) is or "
19543 "is derived from ID; value constraints are not allowed in "
19544 "conjunction with such a type definition", NULL);
19545 } else if (elemDecl->value != NULL) {
19546 int vcret;
19547 xmlNodePtr node = NULL;
19548
19549 /*
19550 * SPEC (2) "If there is a {value constraint}, the canonical lexical
19551 * representation of its value must be ·valid· with respect to the
19552 * {type definition} as defined in Element Default Valid (Immediate)
19553 * (§3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019554 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019555 if (typeDef == NULL) {
19556 xmlSchemaPErr(pctxt, elemDecl->node,
19557 XML_SCHEMAP_INTERNAL,
19558 "Internal error: xmlSchemaCheckElemPropsCorrect, "
19559 "type is missing... skipping validation of "
19560 "the value constraint", NULL, NULL);
19561 return (-1);
19562 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019563 if (elemDecl->node != NULL) {
19564 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19565 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19566 BAD_CAST "fixed");
19567 else
19568 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19569 BAD_CAST "default");
19570 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019571 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19572 typeDef, elemDecl->value, &(elemDecl->defVal));
19573 if (vcret != 0) {
19574 if (vcret < 0) {
19575 PERROR_INT("xmlSchemaElemCheckValConstr",
19576 "failed to validate the value constraint of an "
19577 "element declaration");
19578 return (-1);
19579 }
19580 return (vcret);
19581 }
19582 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019583
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019584 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019585}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019586
19587/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019588 * xmlSchemaCheckElemSubstGroup:
19589 * @ctxt: a schema parser context
19590 * @decl: the element declaration
19591 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019592 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019593 * Schema Component Constraint:
19594 * Substitution Group (cos-equiv-class)
19595 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019596 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019597 * a list will be built for each subst. group head, holding all direct
19598 * referents to this head.
19599 * NOTE that this function needs:
19600 * 1. circular subst. groups to be checked beforehand
19601 * 2. the declaration's type to be derived from the head's type
19602 *
19603 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019604 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019605 */
19606static void
19607xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19608 xmlSchemaElementPtr elemDecl)
19609{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019610 if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019611 /* SPEC (1) "Its {abstract} is false." */
19612 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19613 return;
19614 {
19615 xmlSchemaElementPtr head;
19616 xmlSchemaTypePtr headType, type;
19617 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019618 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019619 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19620 * {disallowed substitutions} as the blocking constraint, as defined in
19621 * Substitution Group OK (Transitive) (§3.3.6)."
19622 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019623 for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19624 head = WXS_SUBST_HEAD(head)) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019625 set = 0;
19626 methSet = 0;
19627 /*
19628 * The blocking constraints.
19629 */
19630 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19631 continue;
19632 headType = head->subtypes;
19633 type = elemDecl->subtypes;
19634 if (headType == type)
19635 goto add_member;
19636 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19637 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19638 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19639 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19640 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019641 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019642 * "The set of all {derivation method}s involved in the
19643 * derivation of D's {type definition} from C's {type definition}
19644 * does not intersect with the union of the blocking constraint,
19645 * C's {prohibited substitutions} (if C is complex, otherwise the
19646 * empty set) and the {prohibited substitutions} (respectively the
19647 * empty set) of any intermediate {type definition}s in the
19648 * derivation of D's {type definition} from C's {type definition}."
19649 */
19650 /*
19651 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19652 * subst.head axis, the methSet does not need to be computed for
19653 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019654 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019655 /*
19656 * The set of all {derivation method}s involved in the derivation
19657 */
19658 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019659 if ((WXS_IS_EXTENSION(type)) &&
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019660 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19661 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019662
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019663 if (WXS_IS_RESTRICTION(type) &&
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019664 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19665 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19666
19667 type = type->baseType;
19668 }
19669 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019670 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019671 * the head's type.
19672 */
19673 type = elemDecl->subtypes->baseType;
19674 while (type != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019675 if (WXS_IS_COMPLEX(type)) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019676 if ((type->flags &
19677 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19678 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19679 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19680 if ((type->flags &
19681 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19682 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19683 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19684 } else
19685 break;
19686 if (type == headType)
19687 break;
19688 type = type->baseType;
19689 }
19690 if ((set != 0) &&
19691 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19692 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19693 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19694 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19695 continue;
19696 }
19697add_member:
19698 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19699 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19700 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19701 }
19702 }
19703}
19704
19705/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019706 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019707 * @item: an schema element declaration/particle
19708 * @ctxt: a schema parser context
19709 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019710 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019711 * Validates the value constraints of an element declaration.
19712 *
19713 * Fixes finish doing the computations on the element declarations.
19714 */
19715static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019716xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019717 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019718{
19719 if (elemDecl == NULL)
19720 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019721 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19722 return;
19723 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019724 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
19725 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019726}
19727
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019728/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019729 * xmlSchemaResolveModelGroupParticleReferences:
19730 * @particle: a particle component
19731 * @ctxt: a parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019732 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019733 * Resolves references of a model group's {particles} to
19734 * model group definitions and to element declarations.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019735 */
19736static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019737xmlSchemaResolveModelGroupParticleReferences(
19738 xmlSchemaParserCtxtPtr ctxt,
19739 xmlSchemaModelGroupPtr mg)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019740{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019741 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19742 xmlSchemaQNameRefPtr ref;
19743 xmlSchemaBasicItemPtr refItem;
19744
19745 /*
19746 * URGENT TODO: Test this.
19747 */
19748 while (particle != NULL) {
19749 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19750 ((WXS_PARTICLE_TERM(particle))->type !=
19751 XML_SCHEMA_EXTRA_QNAMEREF))
19752 {
19753 goto next_particle;
19754 }
19755 ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019756 /*
19757 * Resolve the reference.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019758 * NULL the {term} by default.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019759 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019760 particle->children = NULL;
19761
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019762 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
19763 ref->itemType, ref->name, ref->targetNamespace);
19764 if (refItem == NULL) {
19765 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019766 NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019767 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019768 /* TODO: remove the particle. */
19769 goto next_particle;
19770 }
19771 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
19772 if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
19773 /* TODO: remove the particle. */
19774 goto next_particle;
19775 /*
19776 * NOTE that we will assign the model group definition
19777 * itself to the "term" of the particle. This will ease
19778 * the check for circular model group definitions. After
19779 * that the "term" will be assigned the model group of the
19780 * model group definition.
19781 */
19782 if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
19783 XML_SCHEMA_TYPE_ALL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019784 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019785 * SPEC cos-all-limited (1)
19786 * SPEC cos-all-limited (1.2)
19787 * "It appears only as the value of one or both of the
19788 * following properties:"
19789 * (1.1) "the {model group} property of a model group
19790 * definition."
19791 * (1.2) "the {term} property of a particle [... of] the "
19792 * {content type} of a complex type definition."
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019793 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019794 xmlSchemaCustomErr(ACTXT_CAST ctxt,
19795 /* TODO: error code */
19796 XML_SCHEMAP_COS_ALL_LIMITED,
19797 WXS_ITEM_NODE(particle), NULL,
19798 "A model group definition is referenced, but "
19799 "it contains an 'all' model group, which "
19800 "cannot be contained by model groups",
19801 NULL, NULL);
19802 /* TODO: remove the particle. */
19803 goto next_particle;
19804 }
19805 particle->children = (xmlSchemaTreeItemPtr) refItem;
19806 } else {
19807 /*
19808 * TODO: Are referenced element declarations the only
19809 * other components we expect here?
19810 */
19811 particle->children = (xmlSchemaTreeItemPtr) refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019812 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019813next_particle:
19814 particle = WXS_PTC_CAST particle->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019815 }
19816}
19817
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019818static int
19819xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
19820 xmlSchemaValPtr y)
19821{
19822 xmlSchemaTypePtr tx, ty, ptx, pty;
19823 int ret;
19824
19825 while (x != NULL) {
19826 /* Same types. */
19827 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
19828 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
19829 ptx = xmlSchemaGetPrimitiveType(tx);
19830 pty = xmlSchemaGetPrimitiveType(ty);
19831 /*
19832 * (1) if a datatype T' is ·derived· by ·restriction· from an
19833 * atomic datatype T then the ·value space· of T' is a subset of
19834 * the ·value space· of T. */
19835 /*
19836 * (2) if datatypes T' and T'' are ·derived· by ·restriction·
19837 * from a common atomic ancestor T then the ·value space·s of T'
19838 * and T'' may overlap.
19839 */
19840 if (ptx != pty)
19841 return(0);
19842 /*
19843 * We assume computed values to be normalized, so do a fast
19844 * string comparison for string based types.
19845 */
19846 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019847 WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019848 if (! xmlStrEqual(
19849 xmlSchemaValueGetAsString(x),
19850 xmlSchemaValueGetAsString(y)))
19851 return (0);
19852 } else {
19853 ret = xmlSchemaCompareValuesWhtsp(
19854 x, XML_SCHEMA_WHITESPACE_PRESERVE,
19855 y, XML_SCHEMA_WHITESPACE_PRESERVE);
19856 if (ret == -2)
19857 return(-1);
19858 if (ret != 0)
19859 return(0);
19860 }
19861 /*
19862 * Lists.
19863 */
19864 x = xmlSchemaValueGetNext(x);
19865 if (x != NULL) {
19866 y = xmlSchemaValueGetNext(y);
19867 if (y == NULL)
19868 return (0);
19869 } else if (xmlSchemaValueGetNext(y) != NULL)
19870 return (0);
19871 else
19872 return (1);
19873 }
19874 return (0);
19875}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019876
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019877/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019878 * xmlSchemaResolveAttrUseReferences:
19879 * @item: an attribute use
19880 * @ctxt: a parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019881 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019882 * Resolves the referenced attribute declaration.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019883 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019884static int
19885xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
19886 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000019887{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019888 if ((ctxt == NULL) || (ause == NULL))
19889 return(-1);
19890 if ((ause->attrDecl == NULL) ||
19891 (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
19892 return(0);
19893
19894 {
19895 xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
19896
19897 /*
19898 * TODO: Evaluate, what errors could occur if the declaration is not
19899 * found.
19900 */
19901 ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
19902 ref->name, ref->targetNamespace);
19903 if (ause->attrDecl == NULL) {
19904 xmlSchemaPResCompAttrErr(ctxt,
19905 XML_SCHEMAP_SRC_RESOLVE,
19906 WXS_BASIC_CAST ause, ause->node,
19907 "ref", ref->name, ref->targetNamespace,
19908 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
19909 return(ctxt->err);;
19910 }
19911 }
19912 return(0);
19913}
19914
19915/**
19916 * xmlSchemaCheckAttrUsePropsCorrect:
19917 * @ctxt: a parser context
19918 * @use: an attribute use
19919 *
19920 * Schema Component Constraint:
19921 * Attribute Use Correct (au-props-correct)
19922 *
19923 */
19924static int
19925xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
19926 xmlSchemaAttributeUsePtr use)
19927{
19928 if ((ctxt == NULL) || (use == NULL))
19929 return(-1);
19930 if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
19931 ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
19932 return(0);
19933
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019934 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019935 * SPEC au-props-correct (1)
19936 * "The values of the properties of an attribute use must be as
19937 * described in the property tableau in The Attribute Use Schema
19938 * Component (§3.5.1), modulo the impact of Missing
19939 * Sub-components (§5.3)."
Daniel Veillardc0826a72004-08-10 14:17:33 +000019940 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019941
19942 if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
19943 ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
19944 ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
19945 {
19946 xmlSchemaPCustomErr(ctxt,
19947 XML_SCHEMAP_AU_PROPS_CORRECT_2,
19948 WXS_BASIC_CAST use, NULL,
19949 "The attribute declaration has a 'fixed' value constraint "
19950 ", thus the attribute use must also have a 'fixed' value "
19951 "constraint",
19952 NULL);
19953 return(ctxt->err);
19954 }
19955 /*
19956 * Compute and check the value constraint's value.
19957 */
19958 if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
19959 int ret;
19960 /*
19961 * TODO: The spec seems to be missing a check of the
19962 * value constraint of the attribute use. We will do it here.
19963 */
19964 /*
19965 * SPEC a-props-correct (3)
19966 */
19967 if (xmlSchemaIsDerivedFromBuiltInType(
19968 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19969 {
19970 xmlSchemaCustomErr(ACTXT_CAST ctxt,
19971 XML_SCHEMAP_AU_PROPS_CORRECT,
19972 NULL, WXS_BASIC_CAST use,
19973 "Value constraints are not allowed if the type definition "
19974 "is or is derived from xs:ID",
19975 NULL, NULL);
19976 return(ctxt->err);
19977 }
19978
19979 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
19980 use->node, WXS_ATTRUSE_TYPEDEF(use),
19981 use->defValue, &(use->defVal),
19982 1, 1, 0);
19983 if (ret != 0) {
19984 if (ret < 0) {
19985 PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
19986 "calling xmlSchemaVCheckCVCSimpleType()");
19987 return(-1);
19988 }
19989 xmlSchemaCustomErr(ACTXT_CAST ctxt,
19990 XML_SCHEMAP_AU_PROPS_CORRECT,
19991 NULL, WXS_BASIC_CAST use,
19992 "The value of the value constraint is not valid",
19993 NULL, NULL);
19994 return(ctxt->err);
19995 }
19996 }
19997 /*
19998 * SPEC au-props-correct (2)
19999 * "If the {attribute declaration} has a fixed
20000 * {value constraint}, then if the attribute use itself has a
20001 * {value constraint}, it must also be fixed and its value must match
20002 * that of the {attribute declaration}'s {value constraint}."
20003 */
20004 if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20005 (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20006 {
20007 if (! xmlSchemaAreValuesEqual(use->defVal,
20008 (WXS_ATTRUSE_DECL(use))->defVal))
20009 {
20010 xmlSchemaPCustomErr(ctxt,
20011 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20012 WXS_BASIC_CAST use, NULL,
20013 "The 'fixed' value constraint of the attribute use "
20014 "must match the attribute declaration's value "
20015 "constraint '%s'",
20016 (WXS_ATTRUSE_DECL(use))->defValue);
20017 }
20018 return(ctxt->err);
20019 }
20020 return(0);
20021}
20022
20023
20024
20025
20026/**
20027 * xmlSchemaResolveAttrTypeReferences:
20028 * @item: an attribute declaration
20029 * @ctxt: a parser context
20030 *
20031 * Resolves the referenced type definition component.
20032 */
20033static int
20034xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20035 xmlSchemaParserCtxtPtr ctxt)
20036{
Daniel Veillard01fa6152004-06-29 17:04:39 +000020037 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020038 * The simple type definition corresponding to the <simpleType> element
20039 * information item in the [children], if present, otherwise the simple
20040 * type definition ·resolved· to by the ·actual value· of the type
Daniel Veillard01fa6152004-06-29 17:04:39 +000020041 * [attribute], if present, otherwise the ·simple ur-type definition·.
20042 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020043 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020044 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020045 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20046 if (item->subtypes != NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020047 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020048 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020049 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000020050
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020051 type = xmlSchemaGetType(ctxt->schema, item->typeName,
20052 item->typeNs);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020053 if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000020054 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000020055 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020056 WXS_BASIC_CAST item, item->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020057 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020058 XML_SCHEMA_TYPE_SIMPLE, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020059 return(ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020060 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020061 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020062
Daniel Veillard3646d642004-06-02 19:19:14 +000020063 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020064 /*
20065 * The type defaults to the xs:anySimpleType.
20066 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020067 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20068 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020069 return(0);
Daniel Veillard4255d502002-04-16 15:50:10 +000020070}
20071
20072/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020073 * xmlSchemaResolveIDCKeyReferences:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020074 * @idc: the identity-constraint definition
20075 * @ctxt: the schema parser context
20076 * @name: the attribute name
20077 *
20078 * Resolve keyRef references to key/unique IDCs.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020079 * Schema Component Constraint:
20080 * Identity-constraint Definition Properties Correct (c-props-correct)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020081 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020082static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020083xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020084 xmlSchemaParserCtxtPtr pctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020085{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020086 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020087 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020088 if (idc->ref->name != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020089 idc->ref->item = (xmlSchemaBasicItemPtr)
20090 xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20091 idc->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020092 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020093 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020094 * TODO: It is actually not an error to fail to resolve
20095 * at this stage. BUT we need to be that strict!
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020096 */
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020097 xmlSchemaPResCompAttrErr(pctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020098 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020099 WXS_BASIC_CAST idc, idc->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020100 "refer", idc->ref->name,
20101 idc->ref->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020102 XML_SCHEMA_TYPE_IDC_KEY, NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020103 return(pctxt->err);
20104 } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20105 /*
20106 * SPEC c-props-correct (1)
20107 */
20108 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20109 XML_SCHEMAP_C_PROPS_CORRECT,
20110 NULL, WXS_BASIC_CAST idc,
20111 "The keyref references a keyref",
20112 NULL, NULL);
20113 idc->ref->item = NULL;
20114 return(pctxt->err);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020115 } else {
20116 if (idc->nbFields !=
20117 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20118 xmlChar *str = NULL;
20119 xmlSchemaIDCPtr refer;
20120
20121 refer = (xmlSchemaIDCPtr) idc->ref->item;
20122 /*
20123 * SPEC c-props-correct(2)
20124 * "If the {identity-constraint category} is keyref,
20125 * the cardinality of the {fields} must equal that of
20126 * the {fields} of the {referenced key}.
20127 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020128 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020129 XML_SCHEMAP_C_PROPS_CORRECT,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020130 NULL, WXS_BASIC_CAST idc,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020131 "The cardinality of the keyref differs from the "
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020132 "cardinality of the referenced key/unique '%s'",
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020133 xmlSchemaFormatQName(&str, refer->targetNamespace,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020134 refer->name),
20135 NULL);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020136 FREE_AND_NULL(str)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020137 return(pctxt->err);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020138 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020139 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020140 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020141 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020142}
20143
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020144static int
20145xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20146 xmlSchemaParserCtxtPtr pctxt)
20147{
20148 if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20149 prohib->targetNamespace) == NULL) {
20150
20151 xmlSchemaPResCompAttrErr(pctxt,
20152 XML_SCHEMAP_SRC_RESOLVE,
20153 NULL, prohib->node,
20154 "ref", prohib->name, prohib->targetNamespace,
20155 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20156 return(XML_SCHEMAP_SRC_RESOLVE);
20157 }
20158 return(0);
20159}
20160
20161#define WXS_REDEFINED_TYPE(c) \
20162(((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20163
20164#define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20165(((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20166
20167#define WXS_REDEFINED_ATTR_GROUP(c) \
20168(((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20169
20170static int
20171xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20172{
20173 int err = 0;
20174 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20175 xmlSchemaBasicItemPtr prev, item;
20176 int wasRedefined;
20177
20178 if (redef == NULL)
20179 return(0);
20180
20181 do {
20182 item = redef->item;
20183 /*
20184 * First try to locate the redefined component in the
20185 * schema graph starting with the redefined schema.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020186 * NOTE: According to this schema bug entry:
20187 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20188 * it's not clear if the referenced component needs to originate
20189 * from the <redefine>d schema _document_ or the schema; the latter
20190 * would include all imported and included sub-schemas of the
20191 * <redefine>d schema. Currenlty we latter approach is used.
20192 * SUPPLEMENT: It seems that the WG moves towards the latter
20193 * approach, so we are doing it right.
20194 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020195 */
20196 prev = xmlSchemaFindRedefCompInGraph(
20197 redef->targetBucket, item->type,
20198 redef->refName, redef->refTargetNs);
20199 if (prev == NULL) {
20200 xmlChar *str = NULL;
20201 xmlNodePtr node;
20202
20203 /*
20204 * SPEC src-redefine:
20205 * (6.2.1) "The ·actual value· of its own name attribute plus
20206 * target namespace must successfully ·resolve· to a model
20207 * group definition in I."
20208 * (7.2.1) "The ·actual value· of its own name attribute plus
20209 * target namespace must successfully ·resolve· to an attribute
20210 * group definition in I."
20211
20212 *
20213 * Note that, if we are redefining with the use of references
20214 * to components, the spec assumes the src-resolve to be used;
20215 * but this won't assure that we search only *inside* the
20216 * redefined schema.
20217 */
20218 if (redef->reference)
20219 node = WXS_ITEM_NODE(redef->reference);
20220 else
20221 node = WXS_ITEM_NODE(item);
20222 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20223 /*
20224 * TODO: error code.
20225 * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20226 * reference kind.
20227 */
20228 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
Kasimier T. Buchcik5d2998b2005-11-22 17:36:01 +000020229 "The %s '%s' to be redefined could not be found in "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020230 "the redefined schema",
20231 WXS_ITEM_TYPE_NAME(item),
20232 xmlSchemaFormatQName(&str, redef->refTargetNs,
20233 redef->refName));
20234 FREE_AND_NULL(str);
20235 err = pctxt->err;
20236 redef = redef->next;
20237 continue;
20238 }
20239 /*
20240 * TODO: Obtaining and setting the redefinition state is really
20241 * clumsy.
20242 */
20243 wasRedefined = 0;
20244 switch (item->type) {
20245 case XML_SCHEMA_TYPE_COMPLEX:
20246 case XML_SCHEMA_TYPE_SIMPLE:
20247 if ((WXS_TYPE_CAST prev)->flags &
20248 XML_SCHEMAS_TYPE_REDEFINED)
20249 {
20250 wasRedefined = 1;
20251 break;
20252 }
20253 /* Mark it as redefined. */
20254 (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20255 /*
20256 * Assign the redefined type to the
20257 * base type of the redefining type.
20258 * TODO: How
20259 */
20260 ((xmlSchemaTypePtr) item)->baseType =
20261 (xmlSchemaTypePtr) prev;
20262 break;
20263 case XML_SCHEMA_TYPE_GROUP:
20264 if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20265 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20266 {
20267 wasRedefined = 1;
20268 break;
20269 }
20270 /* Mark it as redefined. */
20271 (WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20272 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20273 if (redef->reference != NULL) {
20274 /*
20275 * Overwrite the QName-reference with the
20276 * referenced model group def.
20277 */
20278 (WXS_PTC_CAST redef->reference)->children =
20279 WXS_TREE_CAST prev;
20280 }
20281 redef->target = prev;
20282 break;
20283 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20284 if ((WXS_ATTR_GROUP_CAST prev)->flags &
20285 XML_SCHEMAS_ATTRGROUP_REDEFINED)
20286 {
20287 wasRedefined = 1;
20288 break;
20289 }
20290 (WXS_ATTR_GROUP_CAST prev)->flags |=
20291 XML_SCHEMAS_ATTRGROUP_REDEFINED;
20292 if (redef->reference != NULL) {
20293 /*
20294 * Assign the redefined attribute group to the
20295 * QName-reference component.
20296 * This is the easy case, since we will just
20297 * expand the redefined group.
20298 */
20299 (WXS_QNAME_CAST redef->reference)->item = prev;
20300 redef->target = NULL;
20301 } else {
20302 /*
20303 * This is the complicated case: we need
20304 * to apply src-redefine (7.2.2) at a later
20305 * stage, i.e. when attribute group references
20306 * have beed expanded and simple types have
20307 * beed fixed.
20308 */
20309 redef->target = prev;
20310 }
20311 break;
20312 default:
20313 PERROR_INT("xmlSchemaResolveRedefReferences",
20314 "Unexpected redefined component type");
20315 return(-1);
20316 }
20317 if (wasRedefined) {
20318 xmlChar *str = NULL;
20319 xmlNodePtr node;
20320
20321 if (redef->reference)
20322 node = WXS_ITEM_NODE(redef->reference);
20323 else
20324 node = WXS_ITEM_NODE(redef->item);
20325
20326 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20327 /* TODO: error code. */
20328 XML_SCHEMAP_SRC_REDEFINE,
20329 node, NULL,
20330 "The referenced %s was already redefined. Multiple "
20331 "redefinition of the same component is not supported",
20332 xmlSchemaGetComponentDesignation(&str, prev),
20333 NULL);
20334 FREE_AND_NULL(str)
20335 err = pctxt->err;
20336 redef = redef->next;
20337 continue;
20338 }
20339 redef = redef->next;
20340 } while (redef != NULL);
20341
20342 return(err);
20343}
20344
20345static int
20346xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20347{
20348 int err = 0;
20349 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20350 xmlSchemaBasicItemPtr item;
20351
20352 if (redef == NULL)
20353 return(0);
20354
20355 do {
20356 if (redef->target == NULL) {
20357 redef = redef->next;
20358 continue;
20359 }
20360 item = redef->item;
20361
20362 switch (item->type) {
20363 case XML_SCHEMA_TYPE_SIMPLE:
20364 case XML_SCHEMA_TYPE_COMPLEX:
20365 /*
20366 * Since the spec wants the {name} of the redefined
20367 * type to be 'absent', we'll NULL it.
20368 */
20369 (WXS_TYPE_CAST redef->target)->name = NULL;
20370
20371 /*
20372 * TODO: Seems like there's nothing more to do. The normal
20373 * inheritance mechanism is used. But not 100% sure.
20374 */
20375 break;
20376 case XML_SCHEMA_TYPE_GROUP:
20377 /*
20378 * URGENT TODO:
20379 * SPEC src-redefine:
20380 * (6.2.2) "The {model group} of the model group definition
20381 * which corresponds to it per XML Representation of Model
20382 * Group Definition Schema Components (§3.7.2) must be a
20383 * ·valid restriction· of the {model group} of that model
20384 * group definition in I, as defined in Particle Valid
20385 * (Restriction) (§3.9.6)."
20386 */
20387 break;
20388 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20389 /*
20390 * SPEC src-redefine:
20391 * (7.2.2) "The {attribute uses} and {attribute wildcard} of
20392 * the attribute group definition which corresponds to it
20393 * per XML Representation of Attribute Group Definition Schema
20394 * Components (§3.6.2) must be ·valid restrictions· of the
20395 * {attribute uses} and {attribute wildcard} of that attribute
20396 * group definition in I, as defined in clause 2, clause 3 and
20397 * clause 4 of Derivation Valid (Restriction, Complex)
20398 * (§3.4.6) (where references to the base type definition are
20399 * understood as references to the attribute group definition
20400 * in I)."
20401 */
20402 err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20403 XML_SCHEMA_ACTION_REDEFINE,
20404 item, redef->target,
20405 (WXS_ATTR_GROUP_CAST item)->attrUses,
20406 (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20407 (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20408 (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20409 if (err == -1)
20410 return(-1);
20411 break;
20412 default:
20413 break;
20414 }
20415 redef = redef->next;
20416 } while (redef != NULL);
20417 return(0);
20418}
20419
20420
20421static int
20422xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20423 xmlSchemaBucketPtr bucket)
20424{
20425 xmlSchemaBasicItemPtr item;
20426 int err;
20427 xmlHashTablePtr *table;
20428 const xmlChar *name;
20429 int i;
20430
20431#define WXS_GET_GLOBAL_HASH(c, s, slot) { \
20432 if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20433 table = &(WXS_IMPBUCKET((c))->schema->slot); \
20434 else \
20435 table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20436
20437 /*
20438 * Add global components to the schema's hash tables.
20439 * This is the place where duplicate components will be
20440 * detected.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020441 * TODO: I think normally we should support imports of the
20442 * same namespace from multiple locations. We don't do currently,
20443 * but if we do then according to:
20444 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20445 * we would need, if imported directly, to import redefined
20446 * components as well to be able to catch clashing components.
20447 * (I hope I'll still know what this means after some months :-()
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020448 */
20449 if (bucket == NULL)
20450 return(-1);
20451 if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20452 return(0);
20453 bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20454
20455 for (i = 0; i < bucket->globals->nbItems; i++) {
20456 item = bucket->globals->items[i];
20457 table = NULL;
20458 switch (item->type) {
20459 case XML_SCHEMA_TYPE_COMPLEX:
20460 case XML_SCHEMA_TYPE_SIMPLE:
20461 if (WXS_REDEFINED_TYPE(item))
20462 continue;
20463 name = (WXS_TYPE_CAST item)->name;
20464 WXS_GET_GLOBAL_HASH(bucket, schema, typeDecl)
20465 break;
20466 case XML_SCHEMA_TYPE_ELEMENT:
20467 name = (WXS_ELEM_CAST item)->name;
20468 WXS_GET_GLOBAL_HASH(bucket, schema, elemDecl)
20469 break;
20470 case XML_SCHEMA_TYPE_ATTRIBUTE:
20471 name = (WXS_ATTR_CAST item)->name;
20472 WXS_GET_GLOBAL_HASH(bucket, schema, attrDecl)
20473 break;
20474 case XML_SCHEMA_TYPE_GROUP:
20475 if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20476 continue;
20477 name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20478 WXS_GET_GLOBAL_HASH(bucket, schema, groupDecl)
20479 break;
20480 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20481 if (WXS_REDEFINED_ATTR_GROUP(item))
20482 continue;
20483 name = (WXS_ATTR_GROUP_CAST item)->name;
20484 WXS_GET_GLOBAL_HASH(bucket, schema, attrgrpDecl)
20485 break;
20486 case XML_SCHEMA_TYPE_IDC_KEY:
20487 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20488 case XML_SCHEMA_TYPE_IDC_KEYREF:
20489 name = (WXS_IDC_CAST item)->name;
20490 WXS_GET_GLOBAL_HASH(bucket, schema, idcDef)
20491 break;
20492 case XML_SCHEMA_TYPE_NOTATION:
20493 name = ((xmlSchemaNotationPtr) item)->name;
20494 WXS_GET_GLOBAL_HASH(bucket, schema, notaDecl)
20495 break;
20496 default:
20497 PERROR_INT("xmlSchemaAddComponents",
20498 "Unexpected global component type");
20499 continue;
20500 }
20501 if (*table == NULL) {
20502 *table = xmlHashCreateDict(10, pctxt->dict);
20503 if (*table == NULL) {
20504 PERROR_INT("xmlSchemaAddComponents",
20505 "failed to create a component hash table");
20506 return(-1);
20507 }
20508 }
20509 err = xmlHashAddEntry(*table, name, item);
20510 if (err != 0) {
20511 xmlChar *str = NULL;
20512
20513 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20514 XML_SCHEMAP_REDEFINED_TYPE,
20515 WXS_ITEM_NODE(item),
20516 WXS_BASIC_CAST item,
20517 "A global %s '%s' does already exist",
20518 WXS_ITEM_TYPE_NAME(item),
20519 xmlSchemaGetComponentQName(&str, item));
20520 FREE_AND_NULL(str);
20521 }
20522 }
20523 /*
20524 * Process imported/included schemas.
20525 */
20526 if (bucket->relations != NULL) {
20527 xmlSchemaSchemaRelationPtr rel = bucket->relations;
20528 do {
20529 if ((rel->bucket != NULL) &&
20530 ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20531 if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20532 return(-1);
20533 }
20534 rel = rel->next;
20535 } while (rel != NULL);
20536 }
20537 return(0);
20538}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020539
20540static int
20541xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt)
20542{
20543 xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20544 xmlSchemaTreeItemPtr item, *items;
20545 int nbItems, i;
20546
20547#define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20548
20549 if ((con->pending == NULL) ||
20550 (con->pending->nbItems == 0))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020551 return(0);
20552
20553 /* TODO:
20554 * SPEC (src-redefine):
20555 * (6.2) "If it has no such self-reference, then all of the
20556 * following must be true:"
20557
20558 * (6.2.2) The {model group} of the model group definition which
20559 * corresponds to it per XML Representation of Model Group
20560 * Definition Schema Components (§3.7.2) must be a ·valid
20561 * restriction· of the {model group} of that model group definition
20562 * in I, as defined in Particle Valid (Restriction) (§3.9.6)."
20563 */
20564 xmlSchemaCheckSRCRedefineFirst(pctxt);
20565
20566 /*
20567 * Add global components to the schemata's hash tables.
20568 */
20569 xmlSchemaAddComponents(pctxt, WXS_CONSTRUCTOR(pctxt)->mainBucket);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020570
20571 pctxt->ctxtType = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020572 items = (xmlSchemaTreeItemPtr *) con->pending->items;
20573 nbItems = con->pending->nbItems;
20574 /*
20575 * Now that we have parsed *all* the schema document(s) and converted
20576 * them to schema components, we can resolve references, apply component
20577 * constraints, create the FSA from the content model, etc.
20578 */
20579 /*
20580 * Resolve references of..
20581 *
20582 * 1. element declarations:
20583 * - the type definition
20584 * - the substitution group affiliation
20585 * 2. simple/complex types:
20586 * - the base type definition
20587 * - the memberTypes of union types
20588 * - the itemType of list types
20589 * 3. attributes declarations and attribute uses:
20590 * - the type definition
20591 * - if an attribute use, then the attribute declaration
20592 * 4. attribute group references:
20593 * - the attribute group definition
20594 * 5. particles:
20595 * - the term of the particle (e.g. a model group)
20596 * 6. IDC key-references:
20597 * - the referenced IDC 'key' or 'unique' definition
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020598 * 7. Attribute prohibitions which had a "ref" attribute.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020599 */
20600 for (i = 0; i < nbItems; i++) {
20601 item = items[i];
20602 switch (item->type) {
20603 case XML_SCHEMA_TYPE_ELEMENT:
20604 xmlSchemaResolveElementReferences(
20605 (xmlSchemaElementPtr) item, pctxt);
20606 FIXHFAILURE;
20607 break;
20608 case XML_SCHEMA_TYPE_COMPLEX:
20609 case XML_SCHEMA_TYPE_SIMPLE:
20610 xmlSchemaResolveTypeReferences(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020611 (xmlSchemaTypePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020612 FIXHFAILURE;
20613 break;
20614 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020615 xmlSchemaResolveAttrTypeReferences(
20616 (xmlSchemaAttributePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020617 FIXHFAILURE;
20618 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020619 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20620 xmlSchemaResolveAttrUseReferences(
20621 (xmlSchemaAttributeUsePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020622 FIXHFAILURE;
20623 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020624 case XML_SCHEMA_EXTRA_QNAMEREF:
20625 if ((WXS_QNAME_CAST item)->itemType ==
20626 XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20627 {
20628 xmlSchemaResolveAttrGroupReferences(
20629 WXS_QNAME_CAST item, pctxt);
20630 }
20631 FIXHFAILURE;
20632 break;
20633 case XML_SCHEMA_TYPE_SEQUENCE:
20634 case XML_SCHEMA_TYPE_CHOICE:
20635 case XML_SCHEMA_TYPE_ALL:
20636 xmlSchemaResolveModelGroupParticleReferences(pctxt,
20637 WXS_MODEL_GROUP_CAST item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020638 FIXHFAILURE;
20639 break;
20640 case XML_SCHEMA_TYPE_IDC_KEY:
20641 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20642 case XML_SCHEMA_TYPE_IDC_KEYREF:
20643 xmlSchemaResolveIDCKeyReferences(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020644 (xmlSchemaIDCPtr) item, pctxt);
20645 FIXHFAILURE;
20646 break;
20647 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20648 /*
20649 * Handle attribue prohibition which had a
20650 * "ref" attribute.
20651 */
20652 xmlSchemaResolveAttrUseProhibReferences(
20653 WXS_ATTR_PROHIB_CAST item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020654 FIXHFAILURE;
20655 break;
20656 default:
20657 break;
20658 }
20659 }
20660 if (pctxt->nberrors != 0)
20661 goto exit_error;
20662
20663 /*
20664 * Now that all references are resolved we
20665 * can check for circularity of...
20666 * 1. the base axis of type definitions
20667 * 2. nested model group definitions
20668 * 3. nested attribute group definitions
20669 * TODO: check for circual substitution groups.
20670 */
20671 for (i = 0; i < nbItems; i++) {
20672 item = items[i];
20673 /*
20674 * Let's better stop on the first error here.
20675 */
20676 switch (item->type) {
20677 case XML_SCHEMA_TYPE_COMPLEX:
20678 case XML_SCHEMA_TYPE_SIMPLE:
20679 xmlSchemaCheckTypeDefCircular(
20680 (xmlSchemaTypePtr) item, pctxt);
20681 FIXHFAILURE;
20682 if (pctxt->nberrors != 0)
20683 goto exit_error;
20684 break;
20685 case XML_SCHEMA_TYPE_GROUP:
20686 xmlSchemaCheckGroupDefCircular(
20687 (xmlSchemaModelGroupDefPtr) item, pctxt);
20688 FIXHFAILURE;
20689 if (pctxt->nberrors != 0)
20690 goto exit_error;
20691 break;
20692 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20693 xmlSchemaCheckAttrGroupCircular(
20694 (xmlSchemaAttributeGroupPtr) item, pctxt);
20695 FIXHFAILURE;
20696 if (pctxt->nberrors != 0)
20697 goto exit_error;
20698 break;
20699 default:
20700 break;
20701 }
20702 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020703 if (pctxt->nberrors != 0)
20704 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020705 /*
20706 * Model group definition references:
20707 * Such a reference is reflected by a particle at the component
20708 * level. Until now the 'term' of such particles pointed
20709 * to the model group definition; this was done, in order to
20710 * ease circularity checks. Now we need to set the 'term' of
20711 * such particles to the model group of the model group definition.
20712 */
20713 for (i = 0; i < nbItems; i++) {
20714 item = items[i];
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020715 switch (item->type) {
20716 case XML_SCHEMA_TYPE_SEQUENCE:
20717 case XML_SCHEMA_TYPE_CHOICE:
20718 xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
20719 WXS_MODEL_GROUP_CAST item);
20720 break;
20721 default:
20722 break;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020723 }
20724 }
20725 if (pctxt->nberrors != 0)
20726 goto exit_error;
20727 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020728 * Expand attribute group references of attribute group definitions.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020729 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020730 for (i = 0; i < nbItems; i++) {
20731 item = items[i];
20732 switch (item->type) {
20733 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20734 if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
20735 WXS_ATTR_GROUP_HAS_REFS(item))
20736 {
20737 xmlSchemaAttributeGroupExpandRefs(pctxt,
20738 WXS_ATTR_GROUP_CAST item);
20739 FIXHFAILURE;
20740 }
20741 break;
20742 default:
20743 break;
20744 }
20745 }
20746 if (pctxt->nberrors != 0)
20747 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020748 /*
20749 * First compute the variety of simple types. This is needed as
20750 * a seperate step, since otherwise we won't be able to detect
20751 * circular union types in all cases.
20752 */
20753 for (i = 0; i < nbItems; i++) {
20754 item = items[i];
20755 switch (item->type) {
20756 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020757 if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020758 xmlSchemaFixupSimpleTypeStageOne(pctxt,
20759 (xmlSchemaTypePtr) item);
20760 FIXHFAILURE;
20761 }
20762 break;
20763 default:
20764 break;
20765 }
20766 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020767 if (pctxt->nberrors != 0)
20768 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020769 /*
20770 * Detect circular union types. Note that this needs the variety to
20771 * be already computed.
20772 */
20773 for (i = 0; i < nbItems; i++) {
20774 item = items[i];
20775 switch (item->type) {
20776 case XML_SCHEMA_TYPE_SIMPLE:
20777 if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
20778 xmlSchemaCheckUnionTypeDefCircular(pctxt,
20779 (xmlSchemaTypePtr) item);
20780 FIXHFAILURE;
20781 }
20782 break;
20783 default:
20784 break;
20785 }
20786 }
20787 if (pctxt->nberrors != 0)
20788 goto exit_error;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020789
20790 /*
20791 * Do the complete type fixup for simple types.
20792 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020793 for (i = 0; i < nbItems; i++) {
20794 item = items[i];
20795 switch (item->type) {
20796 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020797 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
20798 xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
20799 FIXHFAILURE;
20800 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020801 break;
20802 default:
20803 break;
20804 }
20805 }
20806 if (pctxt->nberrors != 0)
20807 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020808 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020809 * At this point we need all simple types to be builded and checked.
20810 */
20811 /*
20812 * Apply contraints for attribute declarations.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020813 */
20814 for (i = 0; i < nbItems; i++) {
20815 item = items[i];
20816 switch (item->type) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020817 case XML_SCHEMA_TYPE_ATTRIBUTE:
20818 xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
20819 FIXHFAILURE;
20820 break;
20821 default:
20822 break;
20823 }
20824 }
20825 if (pctxt->nberrors != 0)
20826 goto exit_error;
20827 /*
20828 * Apply constraints for attribute uses.
20829 */
20830 for (i = 0; i < nbItems; i++) {
20831 item = items[i];
20832 switch (item->type) {
20833 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20834 if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
20835 xmlSchemaCheckAttrUsePropsCorrect(pctxt,
20836 WXS_ATTR_USE_CAST item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020837 FIXHFAILURE;
20838 }
20839 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020840 default:
20841 break;
20842 }
20843 }
20844 if (pctxt->nberrors != 0)
20845 goto exit_error;
20846
20847 /*
20848 * Apply constraints for attribute group definitions.
20849 */
20850 for (i = 0; i < nbItems; i++) {
20851 item = items[i];
20852 switch (item->type) {
20853 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20854 if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
20855 ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
20856 {
20857 xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
20858 FIXHFAILURE;
20859 }
20860 break;
20861 default:
20862 break;
20863 }
20864 }
20865 if (pctxt->nberrors != 0)
20866 goto exit_error;
20867
20868 /*
20869 * Apply constraints for redefinitions.
20870 */
20871 if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
20872 xmlSchemaCheckSRCRedefineSecond(pctxt);
20873 if (pctxt->nberrors != 0)
20874 goto exit_error;
20875
20876 /*
20877 * Fixup complex types.
20878 */
20879 for (i = 0; i < nbItems; i++) {
20880 item = con->pending->items[i];
20881 switch (item->type) {
20882 case XML_SCHEMA_TYPE_COMPLEX:
20883 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
20884 xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
20885 FIXHFAILURE;
20886 }
20887 break;
20888 default:
20889 break;
20890 }
20891 }
20892 if (pctxt->nberrors != 0)
20893 goto exit_error;
20894
20895 /*
20896 * The list could have changed, since xmlSchemaFixupComplexType()
20897 * will create particles and model groups in some cases.
20898 */
20899 items = (xmlSchemaTreeItemPtr *) con->pending->items;
20900 nbItems = con->pending->nbItems;
20901
20902 /*
20903 * At this point all complex types need to be builded and checked.
20904 */
20905 /*
20906 * Apply some constraints for element declarations.
20907 */
20908 for (i = 0; i < nbItems; i++) {
20909 item = items[i];
20910 switch (item->type) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020911 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020912
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020913 if ((((xmlSchemaElementPtr) item)->flags &
20914 XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0) {
20915 xmlSchemaCheckElementDeclComponent(
20916 (xmlSchemaElementPtr) item, pctxt);
20917 FIXHFAILURE;
20918 }
20919 break;
20920 default:
20921 break;
20922 }
20923 }
20924 if (pctxt->nberrors != 0)
20925 goto exit_error;
20926 /*
20927 * Finally we can build the automaton from the content model of
20928 * complex types.
20929 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020930
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020931 for (i = 0; i < nbItems; i++) {
20932 item = items[i];
20933 switch (item->type) {
20934 case XML_SCHEMA_TYPE_COMPLEX:
20935 xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020936 /* FIXHFAILURE; */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020937 break;
20938 default:
20939 break;
20940 }
20941 }
20942 if (pctxt->nberrors != 0)
20943 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020944 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020945 * URGENT TODO: cos-element-consistent
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020946 */
20947 con->pending->nbItems = 0;
20948 return(0);
20949exit_error:
20950 con->pending->nbItems = 0;
20951 return(pctxt->err);
20952exit_failure:
20953 con->pending->nbItems = 0;
20954 return(-1);
20955}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020956/**
Daniel Veillard4255d502002-04-16 15:50:10 +000020957 * xmlSchemaParse:
20958 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000020959 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000020960 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000020961 * XML Shema struture which can be used to validate instances.
Daniel Veillard4255d502002-04-16 15:50:10 +000020962 *
20963 * Returns the internal XML Schema structure built from the resource or
20964 * NULL in case of error
20965 */
20966xmlSchemaPtr
20967xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
20968{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020969 xmlSchemaPtr schema = NULL;
20970 xmlSchemaBucketPtr bucket = NULL;
20971 int res;
Daniel Veillard4255d502002-04-16 15:50:10 +000020972
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020973 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020974 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020975 * the API; i.e. not automatically by the validated instance document.
20976 */
20977
Daniel Veillard4255d502002-04-16 15:50:10 +000020978 xmlSchemaInitTypes();
20979
Daniel Veillard6045c902002-10-09 21:13:59 +000020980 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000020981 return (NULL);
20982
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020983 /* TODO: Init the context. Is this all we need?*/
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000020984 ctxt->nberrors = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020985 ctxt->err = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000020986 ctxt->counter = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000020987
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020988 /* Create the *main* schema. */
20989 schema = xmlSchemaNewSchema(ctxt);
20990 if (schema == NULL)
20991 goto exit_failure;
Daniel Veillard4255d502002-04-16 15:50:10 +000020992 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020993 * Create the schema constructor.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000020994 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020995 if (ctxt->constructor == NULL) {
20996 ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
20997 if (ctxt->constructor == NULL)
20998 return(NULL);
20999 /* Take ownership of the constructor to be able to free it. */
21000 ctxt->ownsConstructor = 1;
21001 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021002 ctxt->constructor->mainSchema = schema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021003 /*
21004 * Locate and add the schema document.
21005 */
21006 res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21007 ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21008 NULL, NULL, &bucket);
21009 if (res == -1)
21010 goto exit_failure;
21011 if (res != 0)
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000021012 goto exit;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021013
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021014 if (bucket == NULL) {
21015 /* TODO: Error code, actually we failed to *locate* the schema. */
21016 if (ctxt->URL)
21017 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21018 NULL, NULL,
21019 "Failed to locate the main schema resource at '%s'",
21020 ctxt->URL, NULL);
21021 else
21022 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21023 NULL, NULL,
21024 "Failed to locate the main schema resource",
21025 NULL, NULL);
21026 goto exit;
21027 }
21028 /* Set the main schema bucket. */
21029 ctxt->constructor->bucket = bucket;
21030 ctxt->targetNamespace = bucket->targetNamespace;
21031 schema->targetNamespace = bucket->targetNamespace;
21032
21033 /* Then do the parsing for good. */
21034 if (xmlSchemaParseNewDocWithContext(ctxt, schema, bucket) == -1)
21035 goto exit_failure;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021036 if (ctxt->nberrors != 0)
21037 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021038
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021039 schema->doc = bucket->doc;
21040 schema->preserve = ctxt->preserve;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021041
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021042 ctxt->schema = schema;
21043
21044 if (xmlSchemaFixupComponents(ctxt) == -1)
21045 goto exit_failure;
21046
21047 /*
21048 * TODO: This is not nice, since we cannot distinguish from the
21049 * result if there was an internal error or not.
21050 */
21051exit:
21052 if (ctxt->nberrors != 0) {
21053 if (schema) {
21054 xmlSchemaFree(schema);
21055 schema = NULL;
21056 }
21057 if (ctxt->constructor) {
21058 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21059 ctxt->constructor = NULL;
21060 ctxt->ownsConstructor = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021061 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021062 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021063 ctxt->schema = NULL;
21064 return(schema);
21065exit_failure:
21066 /*
21067 * Quite verbose, but should catch internal errors, which were
21068 * not communitated.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021069 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021070 if (schema) {
21071 xmlSchemaFree(schema);
21072 schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021073 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021074 if (ctxt->constructor) {
21075 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21076 ctxt->constructor = NULL;
21077 ctxt->ownsConstructor = 0;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000021078 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021079 PERROR_INT2("xmlSchemaParse",
21080 "An internal error occured");
21081 ctxt->schema = NULL;
21082 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000021083}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021084
Daniel Veillard4255d502002-04-16 15:50:10 +000021085/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000021086 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000021087 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000021088 * @err: the error callback
21089 * @warn: the warning callback
21090 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000021091 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000021092 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000021093 */
21094void
21095xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021096 xmlSchemaValidityErrorFunc err,
21097 xmlSchemaValidityWarningFunc warn, void *ctx)
21098{
Daniel Veillard4255d502002-04-16 15:50:10 +000021099 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021100 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000021101 ctxt->error = err;
21102 ctxt->warning = warn;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021103 ctxt->errCtxt = ctx;
21104 if (ctxt->vctxt != NULL)
21105 xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21106}
21107
21108/**
21109 * xmlSchemaSetParserStructuredErrors:
21110 * @ctxt: a schema parser context
21111 * @serror: the structured error function
21112 * @ctx: the functions context
21113 *
21114 * Set the structured error callback
21115 */
21116void
21117xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21118 xmlStructuredErrorFunc serror,
21119 void *ctx)
21120{
21121 if (ctxt == NULL)
21122 return;
21123 ctxt->serror = serror;
21124 ctxt->errCtxt = ctx;
21125 if (ctxt->vctxt != NULL)
21126 xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000021127}
21128
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021129/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000021130 * xmlSchemaGetParserErrors:
21131 * @ctxt: a XMl-Schema parser context
21132 * @err: the error callback result
21133 * @warn: the warning callback result
21134 * @ctx: contextual data for the callbacks result
21135 *
21136 * Get the callback information used to handle errors for a parser context
21137 *
21138 * Returns -1 in case of failure, 0 otherwise
21139 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021140int
Daniel Veillard259f0df2004-08-18 09:13:18 +000021141xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021142 xmlSchemaValidityErrorFunc * err,
21143 xmlSchemaValidityWarningFunc * warn, void **ctx)
Daniel Veillard259f0df2004-08-18 09:13:18 +000021144{
21145 if (ctxt == NULL)
21146 return(-1);
21147 if (err != NULL)
21148 *err = ctxt->error;
21149 if (warn != NULL)
21150 *warn = ctxt->warning;
21151 if (ctx != NULL)
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021152 *ctx = ctxt->errCtxt;
Daniel Veillard259f0df2004-08-18 09:13:18 +000021153 return(0);
21154}
21155
21156/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021157 * xmlSchemaFacetTypeToString:
21158 * @type: the facet type
21159 *
21160 * Convert the xmlSchemaTypeType to a char string.
21161 *
21162 * Returns the char string representation of the facet type if the
21163 * type is a facet and an "Internal Error" string otherwise.
21164 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021165static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021166xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21167{
21168 switch (type) {
21169 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021170 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021171 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021172 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021173 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021174 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021175 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021176 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021177 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021178 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021179 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021180 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021181 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021182 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021183 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021184 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021185 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021186 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021187 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021188 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021189 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021190 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021191 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021192 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021193 default:
21194 break;
21195 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021196 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021197}
21198
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021199static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000021200xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21201{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021202 /*
21203 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000021204 * from xsd:string.
21205 */
21206 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021207 /*
21208 * Note that we assume a whitespace of preserve for anySimpleType.
21209 */
21210 if ((type->builtInType == XML_SCHEMAS_STRING) ||
21211 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21212 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000021213 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021214 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021215 else {
21216 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021217 * For all ·atomic· datatypes other than string (and types ·derived·
21218 * by ·restriction· from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000021219 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021220 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000021221 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021222 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021223 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021224 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021225 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021226 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021227 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021228 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021229 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021230 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021231 } else if (WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021232 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21233 return (XML_SCHEMA_WHITESPACE_PRESERVE);
21234 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21235 return (XML_SCHEMA_WHITESPACE_REPLACE);
21236 else
21237 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021238 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021239 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021240}
21241
Daniel Veillard4255d502002-04-16 15:50:10 +000021242/************************************************************************
21243 * *
21244 * Simple type validation *
21245 * *
21246 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000021247
Daniel Veillard4255d502002-04-16 15:50:10 +000021248
21249/************************************************************************
21250 * *
21251 * DOM Validation code *
21252 * *
21253 ************************************************************************/
21254
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021255/**
21256 * xmlSchemaAssembleByLocation:
21257 * @pctxt: a schema parser context
21258 * @vctxt: a schema validation context
21259 * @schema: the existing schema
21260 * @node: the node that fired the assembling
21261 * @nsName: the namespace name of the new schema
21262 * @location: the location of the schema
21263 *
21264 * Expands an existing schema by an additional schema.
21265 *
21266 * Returns 0 if the new schema is correct, a positive error code
21267 * number otherwise and -1 in case of an internal or API error.
21268 */
21269static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021270xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021271 xmlSchemaPtr schema,
21272 xmlNodePtr node,
21273 const xmlChar *nsName,
21274 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021275{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021276 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021277 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021278 xmlSchemaBucketPtr bucket = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021279
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021280 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021281 return (-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021282
21283 if (vctxt->pctxt == NULL) {
21284 VERROR_INT("xmlSchemaAssembleByLocation",
21285 "no parser context available");
21286 return(-1);
21287 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021288 pctxt = vctxt->pctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021289 if (pctxt->constructor == NULL) {
21290 PERROR_INT("xmlSchemaAssembleByLocation",
21291 "no constructor");
21292 return(-1);
21293 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021294 /*
21295 * Acquire the schema document.
21296 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021297 location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21298 location, node);
21299 /*
21300 * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21301 * the process will automatically change this to
21302 * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21303 */
21304 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21305 location, NULL, NULL, 0, node, NULL, nsName,
21306 &bucket);
21307 if (ret != 0)
21308 return(ret);
21309 if (bucket == NULL) {
21310 PERROR_INT("xmlSchemaAssembleByLocation",
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021311 "no schema bucket acquired");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021312 return(-1);
21313 }
21314 /*
21315 * The first located schema will be handled as if all other
21316 * schemas imported by XSI were imported by this first schema.
21317 */
21318 if ((bucket != NULL) &&
21319 (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21320 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21321 /*
21322 * TODO: Is this handled like an import? I.e. is it not an error
21323 * if the schema cannot be located?
21324 */
21325 if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21326 return(0);
21327 /*
21328 * We will reuse the parser context for every schema imported
21329 * directly via XSI. So reset the context.
21330 */
21331 pctxt->nberrors = 0;
21332 pctxt->err = 0;
21333 pctxt->doc = bucket->doc;
21334
21335 ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21336 if (ret == -1) {
21337 pctxt->doc = NULL;
21338 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021339 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021340 /* Paranoid error channelling. */
21341 if ((ret == 0) && (pctxt->nberrors != 0))
21342 ret = pctxt->err;
21343 if (pctxt->nberrors == 0) {
21344 /*
21345 * Only bother to fixup pending components, if there was
21346 * no error yet.
21347 */
21348 xmlSchemaFixupComponents(pctxt);
Kasimier T. Buchcik215406f2005-12-07 12:14:09 +000021349 ret = pctxt->err;
21350 /*
21351 * Not nice, but we need somehow to channel the schema parser
21352 * error to the validation context.
21353 */
21354 if ((ret != 0) && (vctxt->err == 0))
21355 vctxt->err = ret;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021356 vctxt->nberrors += pctxt->nberrors;
21357 } else {
21358 /* Add to validation error sum. */
21359 vctxt->nberrors += pctxt->nberrors;
21360 }
21361 pctxt->doc = NULL;
21362 return(ret);
21363exit_failure:
21364 pctxt->doc = NULL;
21365 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021366}
21367
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021368static xmlSchemaAttrInfoPtr
21369xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21370 int metaType)
21371{
21372 if (vctxt->nbAttrInfos == 0)
21373 return (NULL);
21374 {
21375 int i;
21376 xmlSchemaAttrInfoPtr iattr;
21377
21378 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21379 iattr = vctxt->attrInfos[i];
21380 if (iattr->metaType == metaType)
21381 return (iattr);
21382 }
21383
21384 }
21385 return (NULL);
21386}
21387
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021388/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021389 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021390 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021391 *
21392 * Expands an existing schema by an additional schema using
21393 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21394 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21395 * must be set to 1.
21396 *
21397 * Returns 0 if the new schema is correct, a positive error code
21398 * number otherwise and -1 in case of an internal or API error.
21399 */
21400static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021401xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021402{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021403 const xmlChar *cur, *end;
21404 const xmlChar *nsname = NULL, *location;
21405 int count = 0;
21406 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021407 xmlSchemaAttrInfoPtr iattr;
21408
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021409 /*
21410 * Parse the value; we will assume an even number of values
21411 * to be given (this is how Xerces and XSV work).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021412 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021413 * URGENT TODO: !! This needs to work for both
21414 * @noNamespaceSchemaLocation AND @schemaLocation on the same
21415 * element !!
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021416 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021417 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21418 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21419 if (iattr == NULL)
Kasimier T. Buchcik81755ea2005-11-23 16:39:27 +000021420 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021421 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21422 if (iattr == NULL)
21423 return (0);
21424 cur = iattr->value;
21425 do {
21426 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021427 /*
21428 * Get the namespace name.
21429 */
21430 while (IS_BLANK_CH(*cur))
21431 cur++;
21432 end = cur;
21433 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21434 end++;
21435 if (end == cur)
21436 break;
21437 count++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021438 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021439 cur = end;
21440 }
21441 /*
21442 * Get the URI.
21443 */
21444 while (IS_BLANK_CH(*cur))
21445 cur++;
21446 end = cur;
21447 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21448 end++;
21449 if (end == cur)
21450 break;
21451 count++;
21452 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021453 cur = end;
21454 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21455 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021456 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021457 VERROR_INT("xmlSchemaAssembleByXSI",
21458 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021459 return (-1);
21460 }
21461 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021462 return (ret);
21463}
21464
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021465static const xmlChar *
21466xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21467 const xmlChar *prefix)
21468{
21469 if (vctxt->sax != NULL) {
21470 int i, j;
21471 xmlSchemaNodeInfoPtr inode;
21472
21473 for (i = vctxt->depth; i >= 0; i--) {
21474 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21475 inode = vctxt->elemInfos[i];
21476 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21477 if (((prefix == NULL) &&
21478 (inode->nsBindings[j] == NULL)) ||
21479 ((prefix != NULL) && xmlStrEqual(prefix,
21480 inode->nsBindings[j]))) {
21481
21482 /*
21483 * Note that the namespace bindings are already
21484 * in a string dict.
21485 */
21486 return (inode->nsBindings[j+1]);
21487 }
21488 }
21489 }
21490 }
21491 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000021492#ifdef LIBXML_WRITER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021493 } else if (vctxt->reader != NULL) {
21494 xmlChar *nsName;
21495
21496 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21497 if (nsName != NULL) {
21498 const xmlChar *ret;
21499
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021500 ret = xmlDictLookup(vctxt->dict, nsName, -1);
21501 xmlFree(nsName);
21502 return (ret);
21503 } else
21504 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000021505#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021506 } else {
21507 xmlNsPtr ns;
21508
21509 if ((vctxt->inode->node == NULL) ||
21510 (vctxt->inode->node->doc == NULL)) {
21511 VERROR_INT("xmlSchemaLookupNamespace",
21512 "no node or node's doc avaliable");
21513 return (NULL);
21514 }
21515 ns = xmlSearchNs(vctxt->inode->node->doc,
21516 vctxt->inode->node, prefix);
21517 if (ns != NULL)
21518 return (ns->href);
21519 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021520 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021521}
21522
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021523/*
21524* This one works on the schema of the validation context.
21525*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021526static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021527xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21528 xmlSchemaPtr schema,
21529 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021530 const xmlChar *value,
21531 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021532 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021533{
21534 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021535
21536 if (vctxt && (vctxt->schema == NULL)) {
21537 VERROR_INT("xmlSchemaValidateNotation",
21538 "a schema is needed on the validation context");
21539 return (-1);
21540 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021541 ret = xmlValidateQName(value, 1);
21542 if (ret != 0)
21543 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021544 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021545 xmlChar *localName = NULL;
21546 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021547
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021548 localName = xmlSplitQName2(value, &prefix);
21549 if (prefix != NULL) {
21550 const xmlChar *nsName = NULL;
21551
21552 if (vctxt != NULL)
21553 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21554 else if (node != NULL) {
21555 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21556 if (ns != NULL)
21557 nsName = ns->href;
21558 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021559 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021560 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021561 return (1);
21562 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021563 if (nsName == NULL) {
21564 xmlFree(prefix);
21565 xmlFree(localName);
21566 return (1);
21567 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021568 if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021569 if (valNeeded && (val != NULL)) {
21570 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
21571 BAD_CAST xmlStrdup(nsName));
21572 if (*val == NULL)
21573 ret = -1;
21574 }
21575 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021576 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021577 xmlFree(prefix);
21578 xmlFree(localName);
21579 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021580 if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021581 if (valNeeded && (val != NULL)) {
21582 (*val) = xmlSchemaNewNOTATIONValue(
21583 BAD_CAST xmlStrdup(value), NULL);
21584 if (*val == NULL)
21585 ret = -1;
21586 }
21587 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021588 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021589 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021590 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021591 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021592}
21593
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000021594static int
21595xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21596 const xmlChar* lname,
21597 const xmlChar* nsname)
21598{
21599 int i;
21600
21601 lname = xmlDictLookup(vctxt->dict, lname, -1);
21602 if (lname == NULL)
21603 return(-1);
21604 if (nsname != NULL) {
21605 nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21606 if (nsname == NULL)
21607 return(-1);
21608 }
21609 for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21610 if ((vctxt->nodeQNames->items [i] == lname) &&
21611 (vctxt->nodeQNames->items[i +1] == nsname))
21612 /* Already there */
21613 return(i);
21614 }
21615 /* Add new entry. */
21616 i = vctxt->nodeQNames->nbItems;
21617 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21618 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21619 return(i);
21620}
21621
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021622/************************************************************************
21623 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021624 * Validation of identity-constraints (IDC) *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021625 * *
21626 ************************************************************************/
21627
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021628/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021629 * xmlSchemaAugmentIDC:
21630 * @idcDef: the IDC definition
21631 *
21632 * Creates an augmented IDC definition item.
21633 *
21634 * Returns the item, or NULL on internal errors.
21635 */
21636static void
21637xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
21638 xmlSchemaValidCtxtPtr vctxt)
21639{
21640 xmlSchemaIDCAugPtr aidc;
21641
21642 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21643 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021644 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021645 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21646 NULL);
21647 return;
21648 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021649 aidc->keyrefDepth = -1;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021650 aidc->def = idcDef;
21651 aidc->next = NULL;
21652 if (vctxt->aidcs == NULL)
21653 vctxt->aidcs = aidc;
21654 else {
21655 aidc->next = vctxt->aidcs;
21656 vctxt->aidcs = aidc;
21657 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021658 /*
21659 * Save if we have keyrefs at all.
21660 */
21661 if ((vctxt->hasKeyrefs == 0) &&
21662 (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
21663 vctxt->hasKeyrefs = 1;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021664}
21665
21666/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021667 * xmlSchemaIDCNewBinding:
21668 * @idcDef: the IDC definition of this binding
21669 *
21670 * Creates a new IDC binding.
21671 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021672 * Returns the new IDC binding, NULL on internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021673 */
21674static xmlSchemaPSVIIDCBindingPtr
21675xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
21676{
21677 xmlSchemaPSVIIDCBindingPtr ret;
21678
21679 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
21680 sizeof(xmlSchemaPSVIIDCBinding));
21681 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021682 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021683 "allocating a PSVI IDC binding item", NULL);
21684 return (NULL);
21685 }
21686 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
21687 ret->definition = idcDef;
21688 return (ret);
21689}
21690
21691/**
21692 * xmlSchemaIDCStoreNodeTableItem:
21693 * @vctxt: the WXS validation context
21694 * @item: the IDC node table item
21695 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021696 * The validation context is used to store IDC node table items.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021697 * They are stored to avoid copying them if IDC node-tables are merged
21698 * with corresponding parent IDC node-tables (bubbling).
21699 *
21700 * Returns 0 if succeeded, -1 on internal errors.
21701 */
21702static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021703xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021704 xmlSchemaPSVIIDCNodePtr item)
21705{
21706 /*
21707 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021708 */
21709 if (vctxt->idcNodes == NULL) {
21710 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021711 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
21712 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021713 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021714 "allocating the IDC node table item list", NULL);
21715 return (-1);
21716 }
21717 vctxt->sizeIdcNodes = 20;
21718 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
21719 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021720 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
21721 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021722 sizeof(xmlSchemaPSVIIDCNodePtr));
21723 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021724 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021725 "re-allocating the IDC node table item list", NULL);
21726 return (-1);
21727 }
21728 }
21729 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021730
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021731 return (0);
21732}
21733
21734/**
21735 * xmlSchemaIDCStoreKey:
21736 * @vctxt: the WXS validation context
21737 * @item: the IDC key
21738 *
21739 * The validation context is used to store an IDC key.
21740 *
21741 * Returns 0 if succeeded, -1 on internal errors.
21742 */
21743static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021744xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021745 xmlSchemaPSVIIDCKeyPtr key)
21746{
21747 /*
21748 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021749 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021750 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021751 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021752 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
21753 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021754 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021755 "allocating the IDC key storage list", NULL);
21756 return (-1);
21757 }
21758 vctxt->sizeIdcKeys = 40;
21759 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
21760 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021761 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
21762 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021763 sizeof(xmlSchemaPSVIIDCKeyPtr));
21764 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021765 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021766 "re-allocating the IDC key storage list", NULL);
21767 return (-1);
21768 }
21769 }
21770 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021771
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021772 return (0);
21773}
21774
21775/**
21776 * xmlSchemaIDCAppendNodeTableItem:
21777 * @bind: the IDC binding
21778 * @ntItem: the node-table item
21779 *
21780 * Appends the IDC node-table item to the binding.
21781 *
21782 * Returns 0 on success and -1 on internal errors.
21783 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021784static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021785xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
21786 xmlSchemaPSVIIDCNodePtr ntItem)
21787{
21788 if (bind->nodeTable == NULL) {
21789 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021790 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021791 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
21792 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021793 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021794 "allocating an array of IDC node-table items", NULL);
21795 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021796 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021797 } else if (bind->sizeNodes <= bind->nbNodes) {
21798 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021799 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
21800 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021801 sizeof(xmlSchemaPSVIIDCNodePtr));
21802 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021803 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021804 "re-allocating an array of IDC node-table items", NULL);
21805 return(-1);
21806 }
21807 }
21808 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021809 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021810}
21811
21812/**
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021813 * xmlSchemaIDCAcquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021814 * @vctxt: the WXS validation context
21815 * @matcher: the IDC matcher
21816 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021817 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021818 * of the given matcher. If none found, a new one is created
21819 * and added to the IDC table.
21820 *
21821 * Returns an IDC binding or NULL on internal errors.
21822 */
21823static xmlSchemaPSVIIDCBindingPtr
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021824xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021825 xmlSchemaIDCMatcherPtr matcher)
21826{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021827 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021828
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021829 ielem = vctxt->elemInfos[matcher->depth];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021830
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021831 if (ielem->idcTable == NULL) {
21832 ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
21833 if (ielem->idcTable == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021834 return (NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021835 return(ielem->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021836 } else {
21837 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021838
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021839 bind = ielem->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021840 do {
21841 if (bind->definition == matcher->aidc->def)
21842 return(bind);
21843 if (bind->next == NULL) {
21844 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
21845 if (bind->next == NULL)
21846 return (NULL);
21847 return(bind->next);
21848 }
21849 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021850 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021851 }
21852 return (NULL);
21853}
21854
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021855static xmlSchemaItemListPtr
21856xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
21857 xmlSchemaIDCMatcherPtr matcher)
21858{
21859 if (matcher->targets == NULL)
21860 matcher->targets = xmlSchemaItemListCreate();
21861 return(matcher->targets);
21862}
21863
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021864/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021865 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021866 * @key: the IDC key
21867 *
21868 * Frees an IDC key together with its compiled value.
21869 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021870static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021871xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
21872{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021873 if (key->val != NULL)
21874 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021875 xmlFree(key);
21876}
21877
21878/**
21879 * xmlSchemaIDCFreeBinding:
21880 *
21881 * Frees an IDC binding. Note that the node table-items
21882 * are not freed.
21883 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021884static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021885xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
21886{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021887 if (bind->nodeTable != NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021888 xmlFree(bind->nodeTable);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021889 if (bind->dupls != NULL)
21890 xmlSchemaItemListFree(bind->dupls);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021891 xmlFree(bind);
21892}
21893
21894/**
21895 * xmlSchemaIDCFreeIDCTable:
21896 * @bind: the first IDC binding in the list
21897 *
21898 * Frees an IDC table, i.e. all the IDC bindings in the list.
21899 */
21900static void
21901xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
21902{
21903 xmlSchemaPSVIIDCBindingPtr prev;
21904
21905 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021906 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021907 bind = bind->next;
21908 xmlSchemaIDCFreeBinding(prev);
21909 }
21910}
21911
21912/**
21913 * xmlSchemaIDCFreeMatcherList:
21914 * @matcher: the first IDC matcher in the list
21915 *
21916 * Frees a list of IDC matchers.
21917 */
21918static void
21919xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
21920{
21921 xmlSchemaIDCMatcherPtr next;
21922
21923 while (matcher != NULL) {
21924 next = matcher->next;
21925 if (matcher->keySeqs != NULL) {
21926 int i;
21927 for (i = 0; i < matcher->sizeKeySeqs; i++)
21928 if (matcher->keySeqs[i] != NULL)
21929 xmlFree(matcher->keySeqs[i]);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021930 xmlFree(matcher->keySeqs);
21931 }
21932 if (matcher->targets != NULL) {
21933 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
21934 int i;
21935 xmlSchemaPSVIIDCNodePtr idcNode;
21936 /*
21937 * Node-table items for keyrefs are not stored globally
21938 * to the validation context, since they are not bubbled.
21939 * We need to free them here.
21940 */
21941 for (i = 0; i < matcher->targets->nbItems; i++) {
21942 idcNode =
21943 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
21944 xmlFree(idcNode->keys);
21945 xmlFree(idcNode);
21946 }
21947 }
21948 xmlSchemaItemListFree(matcher->targets);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021949 }
21950 xmlFree(matcher);
21951 matcher = next;
21952 }
21953}
21954
21955/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021956 * xmlSchemaIDCAddStateObject:
21957 * @vctxt: the WXS validation context
21958 * @matcher: the IDC matcher
21959 * @sel: the XPath information
21960 * @parent: the parent "selector" state object if any
21961 * @type: "selector" or "field"
21962 *
21963 * Creates/reuses and activates state objects for the given
21964 * XPath information; if the XPath expression consists of unions,
21965 * multiple state objects are created for every unioned expression.
21966 *
21967 * Returns 0 on success and -1 on internal errors.
21968 */
21969static int
21970xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
21971 xmlSchemaIDCMatcherPtr matcher,
21972 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021973 int type)
21974{
21975 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021976
21977 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021978 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021979 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021980 if (vctxt->xpathStatePool != NULL) {
21981 sto = vctxt->xpathStatePool;
21982 vctxt->xpathStatePool = sto->next;
21983 sto->next = NULL;
21984 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021985 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021986 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021987 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021988 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
21989 if (sto == NULL) {
21990 xmlSchemaVErrMemory(NULL,
21991 "allocating an IDC state object", NULL);
21992 return (-1);
21993 }
21994 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
21995 }
21996 /*
21997 * Add to global list.
21998 */
21999 if (vctxt->xpathStates != NULL)
22000 sto->next = vctxt->xpathStates;
22001 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022002
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022003 /*
22004 * Free the old xpath validation context.
22005 */
22006 if (sto->xpathCtxt != NULL)
22007 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22008
22009 /*
22010 * Create a new XPath (pattern) validation context.
22011 */
22012 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22013 (xmlPatternPtr) sel->xpathComp);
22014 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022015 VERROR_INT("xmlSchemaIDCAddStateObject",
22016 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022017 return (-1);
22018 }
22019 sto->type = type;
22020 sto->depth = vctxt->depth;
22021 sto->matcher = matcher;
22022 sto->sel = sel;
22023 sto->nbHistory = 0;
22024
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022025#ifdef DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022026 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
22027 sto->sel->xpath);
22028#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022029 return (0);
22030}
22031
22032/**
22033 * xmlSchemaXPathEvaluate:
22034 * @vctxt: the WXS validation context
22035 * @nodeType: the nodeType of the current node
22036 *
22037 * Evaluates all active XPath state objects.
22038 *
22039 * Returns the number of IC "field" state objects which resolved to
22040 * this node, 0 if none resolved and -1 on internal errors.
22041 */
22042static int
22043xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022044 xmlElementType nodeType)
22045{
22046 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022047 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022048
22049 if (vctxt->xpathStates == NULL)
22050 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022051
22052 if (nodeType == XML_ATTRIBUTE_NODE)
22053 depth++;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022054#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022055 {
22056 xmlChar *str = NULL;
22057 xmlGenericError(xmlGenericErrorContext,
22058 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022059 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22060 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022061 FREE_AND_NULL(str)
22062 }
22063#endif
22064 /*
22065 * Process all active XPath state objects.
22066 */
22067 first = vctxt->xpathStates;
22068 sto = first;
22069 while (sto != head) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022070#ifdef DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022071 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022072 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
22073 sto->matcher->aidc->def->name, sto->sel->xpath);
22074 else
22075 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
22076 sto->matcher->aidc->def->name, sto->sel->xpath);
22077#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022078 if (nodeType == XML_ELEMENT_NODE)
22079 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022080 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022081 else
22082 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022083 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022084
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022085 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022086 VERROR_INT("xmlSchemaXPathEvaluate",
22087 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022088 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022089 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022090 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022091 goto next_sto;
22092 /*
22093 * Full match.
22094 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022095#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022096 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022097 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022098#endif
22099 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022100 * Register a match in the state object history.
22101 */
22102 if (sto->history == NULL) {
22103 sto->history = (int *) xmlMalloc(5 * sizeof(int));
22104 if (sto->history == NULL) {
22105 xmlSchemaVErrMemory(NULL,
22106 "allocating the state object history", NULL);
22107 return(-1);
22108 }
22109 sto->sizeHistory = 10;
22110 } else if (sto->sizeHistory <= sto->nbHistory) {
22111 sto->sizeHistory *= 2;
22112 sto->history = (int *) xmlRealloc(sto->history,
22113 sto->sizeHistory * sizeof(int));
22114 if (sto->history == NULL) {
22115 xmlSchemaVErrMemory(NULL,
22116 "re-allocating the state object history", NULL);
22117 return(-1);
22118 }
22119 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022120 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022121
22122#ifdef DEBUG_IDC
22123 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
22124 vctxt->depth);
22125#endif
22126
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022127 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22128 xmlSchemaIDCSelectPtr sel;
22129 /*
22130 * Activate state objects for the IDC fields of
22131 * the IDC selector.
22132 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022133#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022134 xmlGenericError(xmlGenericErrorContext, "IDC: "
22135 "activating field states\n");
22136#endif
22137 sel = sto->matcher->aidc->def->fields;
22138 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022139 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22140 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22141 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022142 sel = sel->next;
22143 }
22144 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22145 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022146 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022147 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022148#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022149 xmlGenericError(xmlGenericErrorContext,
22150 "IDC: key found\n");
22151#endif
22152 /*
22153 * Notify that the character value of this node is
22154 * needed.
22155 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022156 if (resolved == 0) {
22157 if ((vctxt->inode->flags &
22158 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22159 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22160 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022161 resolved++;
22162 }
22163next_sto:
22164 if (sto->next == NULL) {
22165 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022166 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022167 */
22168 head = first;
22169 sto = vctxt->xpathStates;
22170 } else
22171 sto = sto->next;
22172 }
22173 return (resolved);
22174}
22175
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022176static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022177xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022178 xmlChar **buf,
22179 xmlSchemaPSVIIDCKeyPtr *seq,
22180 int count)
22181{
22182 int i, res;
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022183 xmlChar *value = NULL;
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022184
22185 *buf = xmlStrdup(BAD_CAST "[");
22186 for (i = 0; i < count; i++) {
22187 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022188 res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22189 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22190 &value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022191 if (res == 0)
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022192 *buf = xmlStrcat(*buf, BAD_CAST value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022193 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022194 VERROR_INT("xmlSchemaFormatIDCKeySequence",
22195 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022196 *buf = xmlStrcat(*buf, BAD_CAST "???");
22197 }
22198 if (i < count -1)
22199 *buf = xmlStrcat(*buf, BAD_CAST "', ");
22200 else
22201 *buf = xmlStrcat(*buf, BAD_CAST "'");
22202 if (value != NULL) {
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022203 xmlFree(value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022204 value = NULL;
22205 }
22206 }
22207 *buf = xmlStrcat(*buf, BAD_CAST "]");
22208
22209 return (BAD_CAST *buf);
22210}
22211
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022212/**
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000022213 * xmlSchemaXPathPop:
22214 * @vctxt: the WXS validation context
22215 *
22216 * Pops all XPath states.
22217 *
22218 * Returns 0 on success and -1 on internal errors.
22219 */
22220static int
22221xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22222{
22223 xmlSchemaIDCStateObjPtr sto;
22224 int res;
22225
22226 if (vctxt->xpathStates == NULL)
22227 return(0);
22228 sto = vctxt->xpathStates;
22229 do {
22230 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22231 if (res == -1)
22232 return (-1);
22233 sto = sto->next;
22234 } while (sto != NULL);
22235 return(0);
22236}
22237
22238/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022239 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022240 * @vctxt: the WXS validation context
22241 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022242 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022243 *
22244 * Processes and pops the history items of the IDC state objects.
22245 * IDC key-sequences are validated/created on IDC bindings.
22246 *
22247 * Returns 0 on success and -1 on internal errors.
22248 */
22249static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022250xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022251 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022252{
22253 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022254 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022255 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022256 xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022257
22258 if (vctxt->xpathStates == NULL)
22259 return (0);
22260 sto = vctxt->xpathStates;
22261
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022262#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022263 {
22264 xmlChar *str = NULL;
22265 xmlGenericError(xmlGenericErrorContext,
22266 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022267 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22268 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022269 FREE_AND_NULL(str)
22270 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022271#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022272 /*
22273 * Evaluate the state objects.
22274 */
22275 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000022276 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22277 if (res == -1) {
22278 VERROR_INT("xmlSchemaXPathProcessHistory",
22279 "calling xmlStreamPop()");
22280 return (-1);
22281 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022282#ifdef DEBUG_IDC
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022283 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
22284 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022285#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022286 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022287 goto deregister_check;
22288
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022289 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022290
22291 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022292 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022293 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022294 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022295 sto = sto->next;
22296 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022297 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022298 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022299 /*
22300 * NOTE: According to
22301 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22302 * ... the simple-content of complex types is also allowed.
22303 */
22304
22305 if (WXS_IS_COMPLEX(type)) {
22306 if (WXS_HAS_SIMPLE_CONTENT(type)) {
22307 /*
22308 * Sanity check for complex types with simple content.
22309 */
22310 simpleType = type->contentTypeDef;
22311 if (simpleType == NULL) {
22312 VERROR_INT("xmlSchemaXPathProcessHistory",
22313 "field resolves to a CT with simple content "
22314 "but the CT is missing the ST definition");
22315 return (-1);
22316 }
22317 } else
22318 simpleType = NULL;
22319 } else
22320 simpleType = type;
22321 if (simpleType == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022322 xmlChar *str = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022323
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022324 /*
22325 * Not qualified if the field resolves to a node of non
22326 * simple type.
22327 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022328 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022329 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022330 WXS_BASIC_CAST sto->matcher->aidc->def,
22331 "The XPath '%s' of a field of %s does evaluate to a node of "
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022332 "non-simple type",
22333 sto->sel->xpath,
22334 xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22335 FREE_AND_NULL(str);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022336 sto->nbHistory--;
22337 goto deregister_check;
22338 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022339
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022340 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022341 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022342 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022343 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022344 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022345 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022346 WXS_BASIC_CAST sto->matcher->aidc->def,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000022347 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022348 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022349 sto->nbHistory--;
22350 goto deregister_check;
22351 } else {
22352 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22353 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022354 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022355
22356 /*
22357 * The key will be anchored on the matcher's list of
22358 * key-sequences. The position in this list is determined
22359 * by the target node's depth relative to the matcher's
22360 * depth of creation (i.e. the depth of the scope element).
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022361 *
22362 * Element Depth Pos List-entries
22363 * <scope> 0 NULL
22364 * <bar> 1 NULL
22365 * <target/> 2 2 target
22366 * <bar>
22367 * </scope>
22368 *
22369 * The size of the list is only dependant on the depth of
22370 * the tree.
22371 * An entry will be NULLed in selector_leave, i.e. when
22372 * we hit the target's
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022373 */
22374 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022375 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022376
22377 /*
22378 * Create/grow the array of key-sequences.
22379 */
22380 if (matcher->keySeqs == NULL) {
22381 if (pos > 9)
22382 matcher->sizeKeySeqs = pos * 2;
22383 else
22384 matcher->sizeKeySeqs = 10;
22385 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22386 xmlMalloc(matcher->sizeKeySeqs *
22387 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22388 if (matcher->keySeqs == NULL) {
22389 xmlSchemaVErrMemory(NULL,
22390 "allocating an array of key-sequences",
22391 NULL);
22392 return(-1);
22393 }
22394 memset(matcher->keySeqs, 0,
22395 matcher->sizeKeySeqs *
22396 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22397 } else if (pos >= matcher->sizeKeySeqs) {
22398 int i = matcher->sizeKeySeqs;
22399
22400 matcher->sizeKeySeqs *= 2;
22401 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22402 xmlRealloc(matcher->keySeqs,
22403 matcher->sizeKeySeqs *
22404 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022405 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022406 xmlSchemaVErrMemory(NULL,
22407 "reallocating an array of key-sequences",
22408 NULL);
22409 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022410 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022411 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022412 * The array needs to be NULLed.
22413 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022414 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022415 for (; i < matcher->sizeKeySeqs; i++)
22416 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022417 }
22418
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022419 /*
22420 * Get/create the key-sequence.
22421 */
22422 keySeq = matcher->keySeqs[pos];
22423 if (keySeq == NULL) {
22424 goto create_sequence;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022425 } else if (keySeq[idx] != NULL) {
22426 xmlChar *str = NULL;
22427 /*
22428 * cvc-identity-constraint:
22429 * 3 For each node in the ·target node set· all
22430 * of the {fields}, with that node as the context
22431 * node, evaluate to either an empty node-set or
22432 * a node-set with exactly one member, which must
22433 * have a simple type.
22434 *
22435 * The key was already set; report an error.
22436 */
22437 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22438 XML_SCHEMAV_CVC_IDC, NULL,
22439 WXS_BASIC_CAST matcher->aidc->def,
22440 "The XPath '%s' of a field of %s evaluates to a "
22441 "node-set with more than one member",
22442 sto->sel->xpath,
22443 xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22444 FREE_AND_NULL(str);
22445 sto->nbHistory--;
22446 goto deregister_check;
22447 } else
22448 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022449
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022450create_sequence:
22451 /*
22452 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022453 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022454 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22455 matcher->aidc->def->nbFields *
22456 sizeof(xmlSchemaPSVIIDCKeyPtr));
22457 if (keySeq == NULL) {
22458 xmlSchemaVErrMemory(NULL,
22459 "allocating an IDC key-sequence", NULL);
22460 return(-1);
22461 }
22462 memset(keySeq, 0, matcher->aidc->def->nbFields *
22463 sizeof(xmlSchemaPSVIIDCKeyPtr));
22464 matcher->keySeqs[pos] = keySeq;
22465create_key:
22466 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022467 * Create a key once per node only.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022468 */
22469 if (key == NULL) {
22470 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22471 sizeof(xmlSchemaPSVIIDCKey));
22472 if (key == NULL) {
22473 xmlSchemaVErrMemory(NULL,
22474 "allocating a IDC key", NULL);
22475 xmlFree(keySeq);
22476 matcher->keySeqs[pos] = NULL;
22477 return(-1);
22478 }
22479 /*
22480 * Consume the compiled value.
22481 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022482 key->type = simpleType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022483 key->val = vctxt->inode->val;
22484 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022485 /*
22486 * Store the key in a global list.
22487 */
22488 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22489 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022490 return (-1);
22491 }
22492 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022493 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022494 }
22495 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022496
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022497 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022498 /* xmlSchemaPSVIIDCBindingPtr bind; */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022499 xmlSchemaPSVIIDCNodePtr ntItem;
22500 xmlSchemaIDCMatcherPtr matcher;
22501 xmlSchemaIDCPtr idc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022502 xmlSchemaItemListPtr targets;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022503 int pos, i, j, nbKeys;
22504 /*
22505 * Here we have the following scenario:
22506 * An IDC 'selector' state object resolved to a target node,
22507 * during the time this target node was in the
22508 * ancestor-or-self axis, the 'field' state object(s) looked
22509 * out for matching nodes to create a key-sequence for this
22510 * target node. Now we are back to this target node and need
22511 * to put the key-sequence, together with the target node
22512 * itself, into the node-table of the corresponding IDC
22513 * binding.
22514 */
22515 matcher = sto->matcher;
22516 idc = matcher->aidc->def;
22517 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022518 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022519 /*
22520 * Check if the matcher has any key-sequences at all, plus
22521 * if it has a key-sequence for the current target node.
22522 */
22523 if ((matcher->keySeqs == NULL) ||
22524 (matcher->sizeKeySeqs <= pos)) {
22525 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22526 goto selector_key_error;
22527 else
22528 goto selector_leave;
22529 }
22530
22531 keySeq = &(matcher->keySeqs[pos]);
22532 if (*keySeq == NULL) {
22533 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22534 goto selector_key_error;
22535 else
22536 goto selector_leave;
22537 }
22538
22539 for (i = 0; i < nbKeys; i++) {
22540 if ((*keySeq)[i] == NULL) {
22541 /*
22542 * Not qualified, if not all fields did resolve.
22543 */
22544 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22545 /*
22546 * All fields of a "key" IDC must resolve.
22547 */
22548 goto selector_key_error;
22549 }
22550 goto selector_leave;
22551 }
22552 }
22553 /*
22554 * All fields did resolve.
22555 */
22556
22557 /*
22558 * 4.1 If the {identity-constraint category} is unique(/key),
22559 * then no two members of the ·qualified node set· have
22560 * ·key-sequences· whose members are pairwise equal, as
22561 * defined by Equal in [XML Schemas: Datatypes].
22562 *
22563 * Get the IDC binding from the matcher and check for
22564 * duplicate key-sequences.
22565 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022566#if 0
22567 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22568#endif
22569 targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022570 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022571 (targets->nbItems != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022572 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022573
22574 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022575 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022576 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022577 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022578 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022579 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022580 bkeySeq =
22581 ((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022582 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022583 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022584 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022585 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022586 if (res == -1) {
22587 return (-1);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022588 } else if (res == 0) {
22589 /*
22590 * One of the keys differs, so the key-sequence
22591 * won't be equal; get out.
22592 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022593 break;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022594 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022595 }
22596 if (res == 1) {
22597 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022598 * Duplicate key-sequence found.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022599 */
22600 break;
22601 }
22602 i++;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022603 } while (i < targets->nbItems);
22604 if (i != targets->nbItems) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022605 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022606 /*
22607 * TODO: Try to report the key-sequence.
22608 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022609 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022610 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022611 WXS_BASIC_CAST idc,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022612 "Duplicate key-sequence %s in %s",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022613 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022614 (*keySeq), nbKeys),
22615 xmlSchemaGetIDCDesignation(&strB, idc));
22616 FREE_AND_NULL(str);
22617 FREE_AND_NULL(strB);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022618 goto selector_leave;
22619 }
22620 }
22621 /*
22622 * Add a node-table item to the IDC binding.
22623 */
22624 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
22625 sizeof(xmlSchemaPSVIIDCNode));
22626 if (ntItem == NULL) {
22627 xmlSchemaVErrMemory(NULL,
22628 "allocating an IDC node-table item", NULL);
22629 xmlFree(*keySeq);
22630 *keySeq = NULL;
22631 return(-1);
22632 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022633 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022634
22635 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022636 * Store the node-table item in a global list.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022637 */
22638 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
22639 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
22640 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022641 xmlFree(*keySeq);
22642 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022643 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022644 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022645 ntItem->nodeQNameID = -1;
22646 } else {
22647 /*
22648 * Save a cached QName for this node on the IDC node, to be
22649 * able to report it, even if the node is not saved.
22650 */
22651 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
22652 vctxt->inode->localName, vctxt->inode->nsName);
22653 if (ntItem->nodeQNameID == -1) {
22654 xmlFree(ntItem);
22655 xmlFree(*keySeq);
22656 *keySeq = NULL;
22657 return (-1);
22658 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022659 }
22660 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022661 * Init the node-table item: Save the node, position and
22662 * consume the key-sequence.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022663 */
22664 ntItem->node = vctxt->node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022665 ntItem->nodeLine = vctxt->inode->nodeLine;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022666 ntItem->keys = *keySeq;
22667 *keySeq = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022668#if 0
22669 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
22670#endif
22671 if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022672 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
22673 /*
22674 * Free the item, since keyref items won't be
22675 * put on a global list.
22676 */
22677 xmlFree(ntItem->keys);
22678 xmlFree(ntItem);
22679 }
22680 return (-1);
22681 }
22682
22683 goto selector_leave;
22684selector_key_error:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022685 {
22686 xmlChar *str = NULL;
22687 /*
22688 * 4.2.1 (KEY) The ·target node set· and the
22689 * ·qualified node set· are equal, that is, every
22690 * member of the ·target node set· is also a member
22691 * of the ·qualified node set· and vice versa.
22692 */
22693 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22694 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022695 WXS_BASIC_CAST idc,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022696 "Not all fields of %s evaluate to a node",
22697 xmlSchemaGetIDCDesignation(&str, idc), NULL);
22698 FREE_AND_NULL(str);
22699 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022700selector_leave:
22701 /*
22702 * Free the key-sequence if not added to the IDC table.
22703 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022704 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022705 xmlFree(*keySeq);
22706 *keySeq = NULL;
22707 }
22708 } /* if selector */
22709
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022710 sto->nbHistory--;
22711
22712deregister_check:
22713 /*
22714 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022715 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022716 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022717#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022718 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
22719 sto->sel->xpath);
22720#endif
22721 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022722 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022723 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022724 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022725 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022726 nextsto = sto->next;
22727 /*
22728 * Unlink from the list of active XPath state objects.
22729 */
22730 vctxt->xpathStates = sto->next;
22731 sto->next = vctxt->xpathStatePool;
22732 /*
22733 * Link it to the pool of reusable state objects.
22734 */
22735 vctxt->xpathStatePool = sto;
22736 sto = nextsto;
22737 } else
22738 sto = sto->next;
22739 } /* while (sto != NULL) */
22740 return (0);
22741}
22742
22743/**
22744 * xmlSchemaIDCRegisterMatchers:
22745 * @vctxt: the WXS validation context
22746 * @elemDecl: the element declaration
22747 *
22748 * Creates helper objects to evaluate IDC selectors/fields
22749 * successively.
22750 *
22751 * Returns 0 if OK and -1 on internal errors.
22752 */
22753static int
22754xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
22755 xmlSchemaElementPtr elemDecl)
22756{
22757 xmlSchemaIDCMatcherPtr matcher, last = NULL;
22758 xmlSchemaIDCPtr idc, refIdc;
22759 xmlSchemaIDCAugPtr aidc;
22760
22761 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
22762 if (idc == NULL)
22763 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022764
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022765#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022766 {
22767 xmlChar *str = NULL;
22768 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022769 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022770 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22771 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022772 FREE_AND_NULL(str)
22773 }
22774#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022775 if (vctxt->inode->idcMatchers != NULL) {
22776 VERROR_INT("xmlSchemaIDCRegisterMatchers",
22777 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022778 return (-1);
22779 }
22780 do {
22781 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
22782 /*
22783 * Since IDCs bubbles are expensive we need to know the
22784 * depth at which the bubbles should stop; this will be
22785 * the depth of the top-most keyref IDC. If no keyref
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022786 * references a key/unique IDC, the keyrefDepth will
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022787 * be -1, indicating that no bubbles are needed.
22788 */
22789 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
22790 if (refIdc != NULL) {
22791 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022792 * Remember that we have keyrefs on this node.
22793 */
22794 vctxt->inode->hasKeyrefs = 1;
22795 /*
22796 * Lookup the referenced augmented IDC info.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022797 */
22798 aidc = vctxt->aidcs;
22799 while (aidc != NULL) {
22800 if (aidc->def == refIdc)
22801 break;
22802 aidc = aidc->next;
22803 }
22804 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022805 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022806 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022807 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022808 return (-1);
22809 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022810 if ((aidc->keyrefDepth == -1) ||
22811 (vctxt->depth < aidc->keyrefDepth))
22812 aidc->keyrefDepth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022813 }
22814 }
22815 /*
22816 * Lookup the augmented IDC item for the IDC definition.
22817 */
22818 aidc = vctxt->aidcs;
22819 while (aidc != NULL) {
22820 if (aidc->def == idc)
22821 break;
22822 aidc = aidc->next;
22823 }
22824 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022825 VERROR_INT("xmlSchemaIDCRegisterMatchers",
22826 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022827 return (-1);
22828 }
22829 /*
22830 * Create an IDC matcher for every IDC definition.
22831 */
22832 matcher = (xmlSchemaIDCMatcherPtr)
22833 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
22834 if (matcher == NULL) {
22835 xmlSchemaVErrMemory(vctxt,
22836 "allocating an IDC matcher", NULL);
22837 return (-1);
22838 }
22839 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
22840 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022841 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022842 else
22843 last->next = matcher;
22844 last = matcher;
22845
22846 matcher->type = IDC_MATCHER;
22847 matcher->depth = vctxt->depth;
22848 matcher->aidc = aidc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022849 matcher->idcType = aidc->def->type;
22850#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022851 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
22852#endif
22853 /*
22854 * Init the automaton state object.
22855 */
22856 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022857 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022858 return (-1);
22859
22860 idc = idc->next;
22861 } while (idc != NULL);
22862 return (0);
22863}
22864
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022865static int
22866xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
22867 xmlSchemaNodeInfoPtr ielem)
22868{
22869 xmlSchemaPSVIIDCBindingPtr bind;
22870 int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
22871 xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
22872 xmlSchemaPSVIIDCNodePtr *targets, *dupls;
22873
22874 xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
22875 /* vctxt->createIDCNodeTables */
22876 while (matcher != NULL) {
22877 /*
22878 * Skip keyref IDCs and empty IDC target-lists.
22879 */
22880 if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
22881 WXS_ILIST_IS_EMPTY(matcher->targets))
22882 {
22883 matcher = matcher->next;
22884 continue;
22885 }
22886 /*
22887 * If we _want_ the IDC node-table to be created in any case
22888 * then do so. Otherwise create them only if keyrefs need them.
22889 */
22890 if ((! vctxt->createIDCNodeTables) &&
22891 ((matcher->aidc->keyrefDepth == -1) ||
22892 (matcher->aidc->keyrefDepth > vctxt->depth)))
22893 {
22894 matcher = matcher->next;
22895 continue;
22896 }
22897 /*
22898 * Get/create the IDC binding on this element for the IDC definition.
22899 */
22900 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22901
22902 if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
22903 dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
22904 nbDupls = bind->dupls->nbItems;
22905 } else {
22906 dupls = NULL;
22907 nbDupls = 0;
22908 }
22909 if (bind->nodeTable != NULL) {
22910 nbNodeTable = bind->nbNodes;
22911 } else {
22912 nbNodeTable = 0;
22913 }
22914
22915 if ((nbNodeTable == 0) && (nbDupls == 0)) {
22916 /*
22917 * Transfer all IDC target-nodes to the IDC node-table.
22918 */
22919 bind->nodeTable =
22920 (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
22921 bind->sizeNodes = matcher->targets->sizeItems;
22922 bind->nbNodes = matcher->targets->nbItems;
22923
22924 matcher->targets->items = NULL;
22925 matcher->targets->sizeItems = 0;
22926 matcher->targets->nbItems = 0;
22927 } else {
22928 /*
22929 * Compare the key-sequences and add to the IDC node-table.
22930 */
22931 nbTargets = matcher->targets->nbItems;
22932 targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
22933 nbFields = matcher->aidc->def->nbFields;
22934 i = 0;
22935 do {
22936 keys = targets[i]->keys;
22937 if (nbDupls) {
22938 /*
22939 * Search in already found duplicates first.
22940 */
22941 j = 0;
22942 do {
22943 if (nbFields == 1) {
22944 res = xmlSchemaAreValuesEqual(keys[0]->val,
22945 dupls[j]->keys[0]->val);
22946 if (res == -1)
22947 goto internal_error;
22948 if (res == 1) {
22949 /*
22950 * Equal key-sequence.
22951 */
22952 goto next_target;
22953 }
22954 } else {
22955 res = 0;
22956 ntkeys = dupls[j]->keys;
22957 for (k = 0; k < nbFields; k++) {
22958 res = xmlSchemaAreValuesEqual(keys[k]->val,
22959 ntkeys[k]->val);
22960 if (res == -1)
22961 goto internal_error;
22962 if (res == 0) {
22963 /*
22964 * One of the keys differs.
22965 */
22966 break;
22967 }
22968 }
22969 if (res == 1) {
22970 /*
22971 * Equal key-sequence found.
22972 */
22973 goto next_target;
22974 }
22975 }
22976 j++;
22977 } while (j < nbDupls);
22978 }
22979 if (nbNodeTable) {
22980 j = 0;
22981 do {
22982 if (nbFields == 1) {
22983 res = xmlSchemaAreValuesEqual(keys[0]->val,
22984 bind->nodeTable[j]->keys[0]->val);
22985 if (res == -1)
22986 goto internal_error;
22987 if (res == 0) {
22988 /*
22989 * The key-sequence differs.
22990 */
22991 goto next_node_table_entry;
22992 }
22993 } else {
22994 res = 0;
22995 ntkeys = bind->nodeTable[j]->keys;
22996 for (k = 0; k < nbFields; k++) {
22997 res = xmlSchemaAreValuesEqual(keys[k]->val,
22998 ntkeys[k]->val);
22999 if (res == -1)
23000 goto internal_error;
23001 if (res == 0) {
23002 /*
23003 * One of the keys differs.
23004 */
23005 goto next_node_table_entry;
23006 }
23007 }
23008 }
23009 /*
23010 * Add the duplicate to the list of duplicates.
23011 */
23012 if (bind->dupls == NULL) {
23013 bind->dupls = xmlSchemaItemListCreate();
23014 if (bind->dupls == NULL)
23015 goto internal_error;
23016 }
23017 if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23018 goto internal_error;
23019 /*
23020 * Remove the duplicate entry from the IDC node-table.
23021 */
23022 bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23023 bind->nbNodes--;
23024
23025 goto next_target;
23026
23027next_node_table_entry:
23028 j++;
23029 } while (j < nbNodeTable);
23030 }
23031 /*
23032 * If everything is fine, then add the IDC target-node to
23033 * the IDC node-table.
23034 */
23035 if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23036 goto internal_error;
23037
23038next_target:
23039 i++;
23040 } while (i < nbTargets);
23041 }
23042 matcher = matcher->next;
23043 }
23044 return(0);
23045
23046internal_error:
23047 return(-1);
23048}
23049
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023050/**
23051 * xmlSchemaBubbleIDCNodeTables:
23052 * @depth: the current tree depth
23053 *
23054 * Merges IDC bindings of an element at @depth into the corresponding IDC
23055 * bindings of its parent element. If a duplicate note-table entry is found,
23056 * both, the parent node-table entry and child entry are discarded from the
23057 * node-table of the parent.
23058 *
23059 * Returns 0 if OK and -1 on internal errors.
23060 */
23061static int
23062xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23063{
23064 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023065 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23066 xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023067 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023068 int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023069
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023070 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023071 if (bind == NULL) {
23072 /* Fine, no table, no bubbles. */
23073 return (0);
23074 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000023075
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023076 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23077 /*
23078 * Walk all bindings; create new or add to existing bindings.
23079 * Remove duplicate key-sequences.
23080 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023081 while (bind != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023082
23083 if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23084 goto next_binding;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023085 /*
23086 * Check if the key/unique IDC table needs to be bubbled.
23087 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023088 if (! vctxt->createIDCNodeTables) {
23089 aidc = vctxt->aidcs;
23090 do {
23091 if (aidc->def == bind->definition) {
23092 if ((aidc->keyrefDepth == -1) ||
23093 (aidc->keyrefDepth >= vctxt->depth)) {
23094 goto next_binding;
23095 }
23096 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023097 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023098 aidc = aidc->next;
23099 } while (aidc != NULL);
23100 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023101
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023102 if (parTable != NULL)
23103 parBind = *parTable;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023104 /*
23105 * Search a matching parent binding for the
23106 * IDC definition.
23107 */
23108 while (parBind != NULL) {
23109 if (parBind->definition == bind->definition)
23110 break;
23111 parBind = parBind->next;
23112 }
23113
23114 if (parBind != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023115 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023116 * Compare every node-table entry of the child node,
23117 * i.e. the key-sequence within, ...
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023118 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023119 oldNum = parBind->nbNodes; /* Skip newly added items. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023120
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023121 if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23122 oldDupls = parBind->dupls->nbItems;
23123 dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23124 } else {
23125 dupls = NULL;
23126 oldDupls = 0;
23127 }
23128
23129 parNodes = parBind->nodeTable;
23130 nbFields = bind->definition->nbFields;
23131
23132 for (i = 0; i < bind->nbNodes; i++) {
23133 node = bind->nodeTable[i];
23134 if (node == NULL)
23135 continue;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023136 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023137 * ...with every key-sequence of the parent node, already
23138 * evaluated to be a duplicate key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023139 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023140 if (oldDupls) {
23141 j = 0;
23142 while (j < oldDupls) {
23143 if (nbFields == 1) {
23144 ret = xmlSchemaAreValuesEqual(
23145 node->keys[0]->val,
23146 dupls[j]->keys[0]->val);
23147 if (ret == -1)
23148 goto internal_error;
23149 if (ret == 0) {
23150 j++;
23151 continue;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023152 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023153 } else {
23154 parNode = dupls[j];
23155 for (k = 0; k < nbFields; k++) {
23156 ret = xmlSchemaAreValuesEqual(
23157 node->keys[k]->val,
23158 parNode->keys[k]->val);
23159 if (ret == -1)
23160 goto internal_error;
23161 if (ret == 0)
23162 break;
23163 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023164 }
23165 if (ret == 1)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023166 /* Duplicate found. */
23167 break;
23168 j++;
23169 }
23170 if (j != oldDupls) {
23171 /* Duplicate found. Skip this entry. */
23172 continue;
23173 }
23174 }
23175 /*
23176 * ... and with every key-sequence of the parent node.
23177 */
23178 if (oldNum) {
23179 j = 0;
23180 while (j < oldNum) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +000023181 parNode = parNodes[j];
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023182 if (nbFields == 1) {
23183 ret = xmlSchemaAreValuesEqual(
23184 node->keys[0]->val,
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +000023185 parNode->keys[0]->val);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023186 if (ret == -1)
23187 goto internal_error;
23188 if (ret == 0) {
23189 j++;
23190 continue;
23191 }
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +000023192 } else {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023193 for (k = 0; k < nbFields; k++) {
23194 ret = xmlSchemaAreValuesEqual(
23195 node->keys[k]->val,
23196 parNode->keys[k]->val);
23197 if (ret == -1)
23198 goto internal_error;
23199 if (ret == 0)
23200 break;
23201 }
23202 }
23203 if (ret == 1)
23204 /* Duplicate found. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023205 break;
23206 j++;
23207 }
23208 if (j != oldNum) {
23209 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023210 * Handle duplicates. Move the duplicate in
23211 * the parent's node-table to the list of
23212 * duplicates.
23213 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023214 oldNum--;
23215 parBind->nbNodes--;
23216 /*
23217 * Move last old item to pos of duplicate.
23218 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023219 parNodes[j] = parNodes[oldNum];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023220
23221 if (parBind->nbNodes != oldNum) {
23222 /*
23223 * If new items exist, move last new item to
23224 * last of old items.
23225 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023226 parNodes[oldNum] =
23227 parNodes[parBind->nbNodes];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023228 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023229 if (parBind->dupls == NULL) {
23230 parBind->dupls = xmlSchemaItemListCreate();
23231 if (parBind->dupls == NULL)
23232 goto internal_error;
23233 }
23234 xmlSchemaItemListAdd(parBind->dupls, parNode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023235 } else {
23236 /*
23237 * Add the node-table entry (node and key-sequence) of
23238 * the child node to the node table of the parent node.
23239 */
23240 if (parBind->nodeTable == NULL) {
23241 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000023242 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023243 if (parBind->nodeTable == NULL) {
23244 xmlSchemaVErrMemory(NULL,
23245 "allocating IDC list of node-table items", NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023246 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023247 }
23248 parBind->sizeNodes = 1;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023249 } else if (parBind->nbNodes >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000023250 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023251 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23252 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23253 sizeof(xmlSchemaPSVIIDCNodePtr));
23254 if (parBind->nodeTable == NULL) {
23255 xmlSchemaVErrMemory(NULL,
23256 "re-allocating IDC list of node-table items", NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023257 goto internal_error;
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000023258 }
23259 }
23260 parNodes = parBind->nodeTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023261 /*
23262 * Append the new node-table entry to the 'new node-table
23263 * entries' section.
23264 */
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000023265 parNodes[parBind->nbNodes++] = node;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023266 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023267
23268 }
23269
23270 }
23271 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023272 /*
23273 * No binding for the IDC was found: create a new one and
23274 * copy all node-tables.
23275 */
23276 parBind = xmlSchemaIDCNewBinding(bind->definition);
23277 if (parBind == NULL)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023278 goto internal_error;
23279
23280 /*
23281 * TODO: Hmm, how to optimize the initial number of
23282 * allocated entries?
23283 */
23284 if (bind->nbNodes != 0) {
23285 /*
23286 * Add all IDC node-table entries.
23287 */
23288 if (! vctxt->psviExposeIDCNodeTables) {
23289 /*
23290 * Just move the entries.
23291 * NOTE: this is quite save here, since
23292 * all the keyref lookups have already been
23293 * performed.
23294 */
23295 parBind->nodeTable = bind->nodeTable;
23296 bind->nodeTable = NULL;
23297 parBind->sizeNodes = bind->sizeNodes;
23298 bind->sizeNodes = 0;
23299 parBind->nbNodes = bind->nbNodes;
23300 bind->nbNodes = 0;
23301 } else {
23302 /*
23303 * Copy the entries.
23304 */
23305 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23306 xmlMalloc(bind->nbNodes *
23307 sizeof(xmlSchemaPSVIIDCNodePtr));
23308 if (parBind->nodeTable == NULL) {
23309 xmlSchemaVErrMemory(NULL,
23310 "allocating an array of IDC node-table "
23311 "items", NULL);
23312 xmlSchemaIDCFreeBinding(parBind);
23313 goto internal_error;
23314 }
23315 parBind->sizeNodes = bind->nbNodes;
23316 parBind->nbNodes = bind->nbNodes;
23317 memcpy(parBind->nodeTable, bind->nodeTable,
23318 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23319 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023320 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023321 if (bind->dupls) {
23322 /*
23323 * Move the duplicates.
23324 */
23325 if (parBind->dupls != NULL)
23326 xmlSchemaItemListFree(parBind->dupls);
23327 parBind->dupls = bind->dupls;
23328 bind->dupls = NULL;
23329 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023330 if (*parTable == NULL)
23331 *parTable = parBind;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023332 else {
23333 parBind->next = *parTable;
23334 *parTable = parBind;
23335 }
23336 }
23337
23338next_binding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023339 bind = bind->next;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023340 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023341 return (0);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023342
23343internal_error:
23344 return(-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023345}
23346
23347/**
23348 * xmlSchemaCheckCVCIDCKeyRef:
23349 * @vctxt: the WXS validation context
23350 * @elemDecl: the element declaration
23351 *
23352 * Check the cvc-idc-keyref constraints.
23353 */
23354static int
23355xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23356{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023357 xmlSchemaIDCMatcherPtr matcher;
23358 xmlSchemaPSVIIDCBindingPtr bind;
23359
23360 matcher = vctxt->inode->idcMatchers;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023361 /*
23362 * Find a keyref.
23363 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023364 while (matcher != NULL) {
23365 if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23366 matcher->targets &&
23367 matcher->targets->nbItems)
23368 {
23369 int i, j, k, res, nbFields, hasDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023370 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023371 xmlSchemaPSVIIDCNodePtr refNode = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023372
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023373 nbFields = matcher->aidc->def->nbFields;
23374
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023375 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023376 * Find the IDC node-table for the referenced IDC key/unique.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023377 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023378 bind = vctxt->inode->idcTable;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023379 while (bind != NULL) {
23380 if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023381 bind->definition)
23382 break;
23383 bind = bind->next;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023384 }
23385 hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023386 /*
23387 * Search for a matching key-sequences.
23388 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023389 for (i = 0; i < matcher->targets->nbItems; i++) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023390 res = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023391 refNode = matcher->targets->items[i];
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023392 if (bind != NULL) {
23393 refKeys = refNode->keys;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023394 for (j = 0; j < bind->nbNodes; j++) {
23395 keys = bind->nodeTable[j]->keys;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023396 for (k = 0; k < nbFields; k++) {
23397 res = xmlSchemaAreValuesEqual(keys[k]->val,
23398 refKeys[k]->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023399 if (res == 0)
23400 break;
23401 else if (res == -1) {
23402 return (-1);
23403 }
23404 }
23405 if (res == 1) {
23406 /*
23407 * Match found.
23408 */
23409 break;
23410 }
23411 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023412 if ((res == 0) && hasDupls) {
23413 /*
23414 * Search in duplicates
23415 */
23416 for (j = 0; j < bind->dupls->nbItems; j++) {
23417 keys = ((xmlSchemaPSVIIDCNodePtr)
23418 bind->dupls->items[j])->keys;
23419 for (k = 0; k < nbFields; k++) {
23420 res = xmlSchemaAreValuesEqual(keys[k]->val,
23421 refKeys[k]->val);
23422 if (res == 0)
23423 break;
23424 else if (res == -1) {
23425 return (-1);
23426 }
23427 }
23428 if (res == 1) {
23429 /*
23430 * Match in duplicates found.
23431 */
23432 xmlChar *str = NULL, *strB = NULL;
23433 xmlSchemaKeyrefErr(vctxt,
23434 XML_SCHEMAV_CVC_IDC, refNode,
23435 (xmlSchemaTypePtr) matcher->aidc->def,
23436 "More than one match found for "
23437 "key-sequence %s of keyref '%s'",
23438 xmlSchemaFormatIDCKeySequence(vctxt, &str,
23439 refNode->keys, nbFields),
23440 xmlSchemaGetComponentQName(&strB,
23441 matcher->aidc->def));
23442 FREE_AND_NULL(str);
23443 FREE_AND_NULL(strB);
23444 break;
23445 }
23446 }
23447 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023448 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023449
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023450 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023451 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023452 xmlSchemaKeyrefErr(vctxt,
23453 XML_SCHEMAV_CVC_IDC, refNode,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023454 (xmlSchemaTypePtr) matcher->aidc->def,
23455 "No match found for key-sequence %s of keyref '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000023456 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023457 refNode->keys, nbFields),
23458 xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023459 FREE_AND_NULL(str);
23460 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023461 }
23462 }
23463 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023464 matcher = matcher->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023465 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023466 /* TODO: Return an error if any error encountered. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023467 return (0);
23468}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023469
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023470/************************************************************************
23471 * *
23472 * XML Reader validation code *
23473 * *
23474 ************************************************************************/
23475
23476static xmlSchemaAttrInfoPtr
23477xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023478{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023479 xmlSchemaAttrInfoPtr iattr;
23480 /*
23481 * Grow/create list of attribute infos.
23482 */
23483 if (vctxt->attrInfos == NULL) {
23484 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23485 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23486 vctxt->sizeAttrInfos = 1;
23487 if (vctxt->attrInfos == NULL) {
23488 xmlSchemaVErrMemory(vctxt,
23489 "allocating attribute info list", NULL);
23490 return (NULL);
23491 }
23492 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23493 vctxt->sizeAttrInfos++;
23494 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23495 xmlRealloc(vctxt->attrInfos,
23496 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23497 if (vctxt->attrInfos == NULL) {
23498 xmlSchemaVErrMemory(vctxt,
23499 "re-allocating attribute info list", NULL);
23500 return (NULL);
23501 }
23502 } else {
23503 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23504 if (iattr->localName != NULL) {
23505 VERROR_INT("xmlSchemaGetFreshAttrInfo",
23506 "attr info not cleared");
23507 return (NULL);
23508 }
23509 iattr->nodeType = XML_ATTRIBUTE_NODE;
23510 return (iattr);
23511 }
23512 /*
23513 * Create an attribute info.
23514 */
23515 iattr = (xmlSchemaAttrInfoPtr)
23516 xmlMalloc(sizeof(xmlSchemaAttrInfo));
23517 if (iattr == NULL) {
23518 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23519 return (NULL);
23520 }
23521 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23522 iattr->nodeType = XML_ATTRIBUTE_NODE;
23523 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23524
23525 return (iattr);
23526}
23527
23528static int
23529xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23530 xmlNodePtr attrNode,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023531 int nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023532 const xmlChar *localName,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023533 const xmlChar *nsName,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023534 int ownedNames,
23535 xmlChar *value,
23536 int ownedValue)
23537{
23538 xmlSchemaAttrInfoPtr attr;
23539
23540 attr = xmlSchemaGetFreshAttrInfo(vctxt);
23541 if (attr == NULL) {
23542 VERROR_INT("xmlSchemaPushAttribute",
23543 "calling xmlSchemaGetFreshAttrInfo()");
23544 return (-1);
23545 }
23546 attr->node = attrNode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023547 attr->nodeLine = nodeLine;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023548 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23549 attr->localName = localName;
23550 attr->nsName = nsName;
23551 if (ownedNames)
23552 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23553 /*
23554 * Evaluate if it's an XSI attribute.
23555 */
23556 if (nsName != NULL) {
23557 if (xmlStrEqual(localName, BAD_CAST "nil")) {
23558 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23559 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23560 }
23561 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
23562 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23563 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23564 }
23565 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23566 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23567 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23568 }
23569 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23570 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23571 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23572 }
23573 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
23574 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
23575 }
23576 }
23577 attr->value = value;
23578 if (ownedValue)
23579 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23580 if (attr->metaType != 0)
23581 attr->state = XML_SCHEMAS_ATTR_META;
23582 return (0);
23583}
23584
23585static void
23586xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
23587{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023588 ielem->hasKeyrefs = 0;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000023589 ielem->appliedXPath = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023590 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
23591 FREE_AND_NULL(ielem->localName);
23592 FREE_AND_NULL(ielem->nsName);
23593 } else {
23594 ielem->localName = NULL;
23595 ielem->nsName = NULL;
23596 }
23597 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
23598 FREE_AND_NULL(ielem->value);
23599 } else {
23600 ielem->value = NULL;
23601 }
23602 if (ielem->val != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023603 /*
23604 * PSVI TODO: Be careful not to free it when the value is
23605 * exposed via PSVI.
23606 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023607 xmlSchemaFreeValue(ielem->val);
23608 ielem->val = NULL;
23609 }
23610 if (ielem->idcMatchers != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023611 /*
23612 * URGENT OPTIMIZE TODO: Use a pool of IDC matchers.
23613 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023614 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
23615 ielem->idcMatchers = NULL;
23616 }
23617 if (ielem->idcTable != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023618 /*
23619 * OPTIMIZE TODO: Use a pool of IDC tables??.
23620 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023621 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
23622 ielem->idcTable = NULL;
23623 }
23624 if (ielem->regexCtxt != NULL) {
23625 xmlRegFreeExecCtxt(ielem->regexCtxt);
23626 ielem->regexCtxt = NULL;
23627 }
23628 if (ielem->nsBindings != NULL) {
23629 xmlFree((xmlChar **)ielem->nsBindings);
23630 ielem->nsBindings = NULL;
23631 ielem->nbNsBindings = 0;
23632 ielem->sizeNsBindings = 0;
23633 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023634}
23635
23636/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023637 * xmlSchemaGetFreshElemInfo:
23638 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023639 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023640 * Creates/reuses and initializes the element info item for
23641 * the currect tree depth.
23642 *
23643 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023644 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023645static xmlSchemaNodeInfoPtr
23646xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023647{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023648 xmlSchemaNodeInfoPtr info = NULL;
23649
23650 if (vctxt->depth > vctxt->sizeElemInfos) {
23651 VERROR_INT("xmlSchemaGetFreshElemInfo",
23652 "inconsistent depth encountered");
23653 return (NULL);
23654 }
23655 if (vctxt->elemInfos == NULL) {
23656 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
23657 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
23658 if (vctxt->elemInfos == NULL) {
23659 xmlSchemaVErrMemory(vctxt,
23660 "allocating the element info array", NULL);
23661 return (NULL);
23662 }
23663 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
23664 vctxt->sizeElemInfos = 10;
23665 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
23666 int i = vctxt->sizeElemInfos;
23667
23668 vctxt->sizeElemInfos *= 2;
23669 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
23670 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
23671 sizeof(xmlSchemaNodeInfoPtr));
23672 if (vctxt->elemInfos == NULL) {
23673 xmlSchemaVErrMemory(vctxt,
23674 "re-allocating the element info array", NULL);
23675 return (NULL);
23676 }
23677 /*
23678 * We need the new memory to be NULLed.
23679 * TODO: Use memset instead?
23680 */
23681 for (; i < vctxt->sizeElemInfos; i++)
23682 vctxt->elemInfos[i] = NULL;
23683 } else
23684 info = vctxt->elemInfos[vctxt->depth];
23685
23686 if (info == NULL) {
23687 info = (xmlSchemaNodeInfoPtr)
23688 xmlMalloc(sizeof(xmlSchemaNodeInfo));
23689 if (info == NULL) {
23690 xmlSchemaVErrMemory(vctxt,
23691 "allocating an element info", NULL);
23692 return (NULL);
23693 }
23694 vctxt->elemInfos[vctxt->depth] = info;
23695 } else {
23696 if (info->localName != NULL) {
23697 VERROR_INT("xmlSchemaGetFreshElemInfo",
23698 "elem info has not been cleared");
23699 return (NULL);
23700 }
23701 }
23702 memset(info, 0, sizeof(xmlSchemaNodeInfo));
23703 info->nodeType = XML_ELEMENT_NODE;
23704 info->depth = vctxt->depth;
23705
23706 return (info);
23707}
23708
23709#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
23710#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
23711#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
23712
23713static int
23714xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
23715 xmlNodePtr node,
23716 xmlSchemaTypePtr type,
23717 xmlSchemaValType valType,
23718 const xmlChar * value,
23719 xmlSchemaValPtr val,
23720 unsigned long length,
23721 int fireErrors)
23722{
23723 int ret, error = 0;
23724
23725 xmlSchemaTypePtr tmpType;
23726 xmlSchemaFacetLinkPtr facetLink;
23727 xmlSchemaFacetPtr facet;
23728 unsigned long len = 0;
23729 xmlSchemaWhitespaceValueType ws;
23730
23731 /*
23732 * In Libxml2, derived built-in types have currently no explicit facets.
23733 */
23734 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023735 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023736
23737 /*
23738 * NOTE: Do not jump away, if the facetSet of the given type is
23739 * empty: until now, "pattern" and "enumeration" facets of the
23740 * *base types* need to be checked as well.
23741 */
23742 if (type->facetSet == NULL)
23743 goto pattern_and_enum;
23744
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023745 if (! WXS_IS_ATOMIC(type)) {
23746 if (WXS_IS_LIST(type))
23747 goto WXS_IS_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023748 else
23749 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023750 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023751 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023752 * Whitespace handling is only of importance for string-based
23753 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023754 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023755 tmpType = xmlSchemaGetPrimitiveType(type);
23756 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023757 WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023758 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
23759 } else
23760 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
23761 /*
23762 * If the value was not computed (for string or
23763 * anySimpleType based types), then use the provided
23764 * type.
23765 */
23766 if (val == NULL)
23767 valType = valType;
23768 else
23769 valType = xmlSchemaGetValType(val);
23770
23771 ret = 0;
23772 for (facetLink = type->facetSet; facetLink != NULL;
23773 facetLink = facetLink->next) {
23774 /*
23775 * Skip the pattern "whiteSpace": it is used to
23776 * format the character content beforehand.
23777 */
23778 switch (facetLink->facet->type) {
23779 case XML_SCHEMA_FACET_WHITESPACE:
23780 case XML_SCHEMA_FACET_PATTERN:
23781 case XML_SCHEMA_FACET_ENUMERATION:
23782 continue;
23783 case XML_SCHEMA_FACET_LENGTH:
23784 case XML_SCHEMA_FACET_MINLENGTH:
23785 case XML_SCHEMA_FACET_MAXLENGTH:
23786 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
23787 valType, value, val, &len, ws);
23788 break;
23789 default:
23790 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
23791 valType, value, val, ws);
23792 break;
23793 }
23794 if (ret < 0) {
23795 AERROR_INT("xmlSchemaValidateFacets",
23796 "validating against a atomic type facet");
23797 return (-1);
23798 } else if (ret > 0) {
23799 if (fireErrors)
23800 xmlSchemaFacetErr(actxt, ret, node,
23801 value, len, type, facetLink->facet, NULL, NULL, NULL);
23802 else
23803 return (ret);
23804 if (error == 0)
23805 error = ret;
23806 }
23807 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023808 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023809
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023810WXS_IS_LIST:
23811 if (! WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023812 goto pattern_and_enum;
23813 /*
23814 * "length", "minLength" and "maxLength" of list types.
23815 */
23816 ret = 0;
23817 for (facetLink = type->facetSet; facetLink != NULL;
23818 facetLink = facetLink->next) {
23819
23820 switch (facetLink->facet->type) {
23821 case XML_SCHEMA_FACET_LENGTH:
23822 case XML_SCHEMA_FACET_MINLENGTH:
23823 case XML_SCHEMA_FACET_MAXLENGTH:
23824 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
23825 value, length, NULL);
23826 break;
23827 default:
23828 continue;
23829 }
23830 if (ret < 0) {
23831 AERROR_INT("xmlSchemaValidateFacets",
23832 "validating against a list type facet");
23833 return (-1);
23834 } else if (ret > 0) {
23835 if (fireErrors)
23836 xmlSchemaFacetErr(actxt, ret, node,
23837 value, length, type, facetLink->facet, NULL, NULL, NULL);
23838 else
23839 return (ret);
23840 if (error == 0)
23841 error = ret;
23842 }
23843 ret = 0;
23844 }
23845
23846pattern_and_enum:
23847 if (error >= 0) {
23848 int found = 0;
23849 /*
23850 * Process enumerations. Facet values are in the value space
23851 * of the defining type's base type. This seems to be a bug in the
23852 * XML Schema 1.0 spec. Use the whitespace type of the base type.
23853 * Only the first set of enumerations in the ancestor-or-self axis
23854 * is used for validation.
23855 */
23856 ret = 0;
23857 tmpType = type;
23858 do {
23859 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
23860 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
23861 continue;
23862 found = 1;
23863 ret = xmlSchemaAreValuesEqual(facet->val, val);
23864 if (ret == 1)
23865 break;
23866 else if (ret < 0) {
23867 AERROR_INT("xmlSchemaValidateFacets",
23868 "validating against an enumeration facet");
23869 return (-1);
23870 }
23871 }
23872 if (ret != 0)
23873 break;
23874 tmpType = tmpType->baseType;
23875 } while ((tmpType != NULL) &&
23876 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
23877 if (found && (ret == 0)) {
23878 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
23879 if (fireErrors) {
23880 xmlSchemaFacetErr(actxt, ret, node,
23881 value, 0, type, NULL, NULL, NULL, NULL);
23882 } else
23883 return (ret);
23884 if (error == 0)
23885 error = ret;
23886 }
23887 }
23888
23889 if (error >= 0) {
23890 int found;
23891 /*
23892 * Process patters. Pattern facets are ORed at type level
23893 * and ANDed if derived. Walk the base type axis.
23894 */
23895 tmpType = type;
23896 facet = NULL;
23897 do {
23898 found = 0;
23899 for (facetLink = tmpType->facetSet; facetLink != NULL;
23900 facetLink = facetLink->next) {
23901 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
23902 continue;
23903 found = 1;
23904 /*
23905 * NOTE that for patterns, @value needs to be the
23906 * normalized vaule.
23907 */
23908 ret = xmlRegexpExec(facetLink->facet->regexp, value);
23909 if (ret == 1)
23910 break;
23911 else if (ret < 0) {
23912 AERROR_INT("xmlSchemaValidateFacets",
23913 "validating against a pattern facet");
23914 return (-1);
23915 } else {
23916 /*
23917 * Save the last non-validating facet.
23918 */
23919 facet = facetLink->facet;
23920 }
23921 }
23922 if (found && (ret != 1)) {
23923 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
23924 if (fireErrors) {
23925 xmlSchemaFacetErr(actxt, ret, node,
23926 value, 0, type, facet, NULL, NULL, NULL);
23927 } else
23928 return (ret);
23929 if (error == 0)
23930 error = ret;
23931 break;
23932 }
23933 tmpType = tmpType->baseType;
23934 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
23935 }
23936
23937 return (error);
23938}
23939
23940static xmlChar *
23941xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
23942 const xmlChar *value)
23943{
23944 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
23945 case XML_SCHEMA_WHITESPACE_COLLAPSE:
23946 return (xmlSchemaCollapseString(value));
23947 case XML_SCHEMA_WHITESPACE_REPLACE:
23948 return (xmlSchemaWhiteSpaceReplace(value));
23949 default:
23950 return (NULL);
23951 }
23952}
23953
23954static int
23955xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
23956 const xmlChar *value,
23957 xmlSchemaValPtr *val,
23958 int valNeeded)
23959{
23960 int ret;
23961 const xmlChar *nsName;
23962 xmlChar *local, *prefix = NULL;
23963
23964 ret = xmlValidateQName(value, 1);
23965 if (ret != 0) {
23966 if (ret == -1) {
23967 VERROR_INT("xmlSchemaValidateQName",
23968 "calling xmlValidateQName()");
23969 return (-1);
23970 }
23971 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
23972 }
23973 /*
23974 * NOTE: xmlSplitQName2 will always return a duplicated
23975 * strings.
23976 */
23977 local = xmlSplitQName2(value, &prefix);
23978 if (local == NULL)
23979 local = xmlStrdup(value);
23980 /*
23981 * OPTIMIZE TODO: Use flags for:
23982 * - is there any namespace binding?
23983 * - is there a default namespace?
23984 */
23985 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
23986
23987 if (prefix != NULL) {
23988 xmlFree(prefix);
23989 /*
23990 * A namespace must be found if the prefix is
23991 * NOT NULL.
23992 */
23993 if (nsName == NULL) {
23994 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023995 xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023996 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023997 "The QName value '%s' has no "
23998 "corresponding namespace declaration in "
23999 "scope", value, NULL);
24000 if (local != NULL)
24001 xmlFree(local);
24002 return (ret);
24003 }
24004 }
24005 if (valNeeded && val) {
24006 if (nsName != NULL)
24007 *val = xmlSchemaNewQNameValue(
24008 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24009 else
24010 *val = xmlSchemaNewQNameValue(NULL,
24011 BAD_CAST local);
24012 } else
24013 xmlFree(local);
24014 return (0);
24015}
24016
24017/*
24018* cvc-simple-type
24019*/
24020static int
24021xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24022 xmlNodePtr node,
24023 xmlSchemaTypePtr type,
24024 const xmlChar *value,
24025 xmlSchemaValPtr *retVal,
24026 int fireErrors,
24027 int normalize,
24028 int isNormalized)
24029{
24030 int ret = 0, valNeeded = (retVal) ? 1 : 0;
24031 xmlSchemaValPtr val = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024032 /* xmlSchemaWhitespaceValueType ws; */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024033 xmlChar *normValue = NULL;
24034
24035#define NORMALIZE(atype) \
24036 if ((! isNormalized) && \
24037 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24038 normValue = xmlSchemaNormalizeValue(atype, value); \
24039 if (normValue != NULL) \
24040 value = normValue; \
24041 isNormalized = 1; \
24042 }
24043
24044 if ((retVal != NULL) && (*retVal != NULL)) {
24045 xmlSchemaFreeValue(*retVal);
24046 *retVal = NULL;
24047 }
24048 /*
24049 * 3.14.4 Simple Type Definition Validation Rules
24050 * Validation Rule: String Valid
24051 */
24052 /*
24053 * 1 It is schema-valid with respect to that definition as defined
24054 * by Datatype Valid in [XML Schemas: Datatypes].
24055 */
24056 /*
24057 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24058 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
24059 * the string must be a ·declared entity name·.
24060 */
24061 /*
24062 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24063 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
24064 * then every whitespace-delimited substring of the string must be a ·declared
24065 * entity name·.
24066 */
24067 /*
24068 * 2.3 otherwise no further condition applies.
24069 */
24070 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24071 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000024072 if (value == NULL)
24073 value = BAD_CAST "";
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024074 if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024075 xmlSchemaTypePtr biType; /* The built-in type. */
24076 /*
24077 * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match·
24078 * a literal in the ·lexical space· of {base type definition}"
24079 */
24080 /*
24081 * Whitespace-normalize.
24082 */
24083 NORMALIZE(type);
24084 if (type->type != XML_SCHEMA_TYPE_BASIC) {
24085 /*
24086 * Get the built-in type.
24087 */
24088 biType = type->baseType;
24089 while ((biType != NULL) &&
24090 (biType->type != XML_SCHEMA_TYPE_BASIC))
24091 biType = biType->baseType;
24092
24093 if (biType == NULL) {
24094 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24095 "could not get the built-in type");
24096 goto internal_error;
24097 }
24098 } else
24099 biType = type;
24100 /*
24101 * NOTATIONs need to be processed here, since they need
24102 * to lookup in the hashtable of NOTATION declarations of the schema.
24103 */
24104 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24105 switch (biType->builtInType) {
24106 case XML_SCHEMAS_NOTATION:
24107 ret = xmlSchemaValidateNotation(
24108 (xmlSchemaValidCtxtPtr) actxt,
24109 ((xmlSchemaValidCtxtPtr) actxt)->schema,
24110 NULL, value, &val, valNeeded);
24111 break;
24112 case XML_SCHEMAS_QNAME:
24113 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24114 value, &val, valNeeded);
24115 break;
24116 default:
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024117 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024118 if (valNeeded)
24119 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24120 value, &val, NULL);
24121 else
24122 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24123 value, NULL, NULL);
24124 break;
24125 }
24126 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24127 switch (biType->builtInType) {
24128 case XML_SCHEMAS_NOTATION:
24129 ret = xmlSchemaValidateNotation(NULL,
24130 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24131 value, &val, valNeeded);
24132 break;
24133 default:
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024134 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024135 if (valNeeded)
24136 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24137 value, &val, node);
24138 else
24139 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24140 value, NULL, node);
24141 break;
24142 }
24143 } else {
24144 /*
24145 * Validation via a public API is not implemented yet.
24146 */
24147 TODO
24148 goto internal_error;
24149 }
24150 if (ret != 0) {
24151 if (ret < 0) {
24152 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24153 "validating against a built-in type");
24154 goto internal_error;
24155 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024156 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024157 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24158 else
24159 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24160 }
24161 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24162 /*
24163 * Check facets.
24164 */
24165 ret = xmlSchemaValidateFacets(actxt, node, type,
24166 (xmlSchemaValType) biType->builtInType, value, val,
24167 0, fireErrors);
24168 if (ret != 0) {
24169 if (ret < 0) {
24170 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24171 "validating facets of atomic simple type");
24172 goto internal_error;
24173 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024174 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024175 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24176 else
24177 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24178 }
24179 }
24180 if (fireErrors && (ret > 0))
24181 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024182 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024183
24184 xmlSchemaTypePtr itemType;
24185 const xmlChar *cur, *end;
24186 xmlChar *tmpValue = NULL;
24187 unsigned long len = 0;
24188 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24189 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
24190 * of white space separated tokens, each of which ·match·es a literal
24191 * in the ·lexical space· of {item type definition}
24192 */
24193 /*
24194 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24195 * the list type has an enum or pattern facet.
24196 */
24197 NORMALIZE(type);
24198 /*
24199 * VAL TODO: Optimize validation of empty values.
24200 * VAL TODO: We do not have computed values for lists.
24201 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024202 itemType = WXS_LIST_ITEMTYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024203 cur = value;
24204 do {
24205 while (IS_BLANK_CH(*cur))
24206 cur++;
24207 end = cur;
24208 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24209 end++;
24210 if (end == cur)
24211 break;
24212 tmpValue = xmlStrndup(cur, end - cur);
24213 len++;
24214
24215 if (valNeeded)
24216 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24217 tmpValue, &curVal, fireErrors, 0, 1);
24218 else
24219 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24220 tmpValue, NULL, fireErrors, 0, 1);
24221 FREE_AND_NULL(tmpValue);
24222 if (curVal != NULL) {
24223 /*
24224 * Add to list of computed values.
24225 */
24226 if (val == NULL)
24227 val = curVal;
24228 else
24229 xmlSchemaValueAppend(prevVal, curVal);
24230 prevVal = curVal;
24231 curVal = NULL;
24232 }
24233 if (ret != 0) {
24234 if (ret < 0) {
24235 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24236 "validating an item of list simple type");
24237 goto internal_error;
24238 }
24239 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24240 break;
24241 }
24242 cur = end;
24243 } while (*cur != 0);
24244 FREE_AND_NULL(tmpValue);
24245 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24246 /*
24247 * Apply facets (pattern, enumeration).
24248 */
24249 ret = xmlSchemaValidateFacets(actxt, node, type,
24250 XML_SCHEMAS_UNKNOWN, value, val,
24251 len, fireErrors);
24252 if (ret != 0) {
24253 if (ret < 0) {
24254 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24255 "validating facets of list simple type");
24256 goto internal_error;
24257 }
24258 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24259 }
24260 }
24261 if (fireErrors && (ret > 0)) {
24262 /*
24263 * Report the normalized value.
24264 */
24265 normalize = 1;
24266 NORMALIZE(type);
24267 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24268 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024269 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024270 xmlSchemaTypeLinkPtr memberLink;
24271 /*
24272 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
24273 * not apply directly; however, the normalization behavior of ·union·
24274 * types is controlled by the value of whiteSpace on that one of the
24275 * ·memberTypes· against which the ·union· is successfully validated.
24276 *
24277 * This means that the value is normalized by the first validating
24278 * member type, then the facets of the union type are applied. This
24279 * needs changing of the value!
24280 */
24281
24282 /*
24283 * 1.2.3 if {variety} is ·union· then the string must ·match· a
24284 * literal in the ·lexical space· of at least one member of
24285 * {member type definitions}
24286 */
24287 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24288 if (memberLink == NULL) {
24289 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24290 "union simple type has no member types");
24291 goto internal_error;
24292 }
24293 /*
24294 * Always normalize union type values, since we currently
24295 * cannot store the whitespace information with the value
24296 * itself; otherwise a later value-comparison would be
24297 * not possible.
24298 */
24299 while (memberLink != NULL) {
24300 if (valNeeded)
24301 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24302 memberLink->type, value, &val, 0, 1, 0);
24303 else
24304 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24305 memberLink->type, value, NULL, 0, 1, 0);
24306 if (ret <= 0)
24307 break;
24308 memberLink = memberLink->next;
24309 }
24310 if (ret != 0) {
24311 if (ret < 0) {
24312 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24313 "validating members of union simple type");
24314 goto internal_error;
24315 }
24316 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24317 }
24318 /*
24319 * Apply facets (pattern, enumeration).
24320 */
24321 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24322 /*
24323 * The normalization behavior of ·union· types is controlled by
24324 * the value of whiteSpace on that one of the ·memberTypes·
24325 * against which the ·union· is successfully validated.
24326 */
24327 NORMALIZE(memberLink->type);
24328 ret = xmlSchemaValidateFacets(actxt, node, type,
24329 XML_SCHEMAS_UNKNOWN, value, val,
24330 0, fireErrors);
24331 if (ret != 0) {
24332 if (ret < 0) {
24333 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24334 "validating facets of union simple type");
24335 goto internal_error;
24336 }
24337 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24338 }
24339 }
24340 if (fireErrors && (ret > 0))
24341 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24342 }
24343
24344 if (normValue != NULL)
24345 xmlFree(normValue);
24346 if (ret == 0) {
24347 if (retVal != NULL)
24348 *retVal = val;
24349 else if (val != NULL)
24350 xmlSchemaFreeValue(val);
24351 } else if (val != NULL)
24352 xmlSchemaFreeValue(val);
24353 return (ret);
24354internal_error:
24355 if (normValue != NULL)
24356 xmlFree(normValue);
24357 if (val != NULL)
24358 xmlSchemaFreeValue(val);
24359 return (-1);
24360}
24361
24362static int
24363xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24364 const xmlChar *value,
24365 const xmlChar **nsName,
24366 const xmlChar **localName)
24367{
24368 int ret = 0;
24369
24370 if ((nsName == NULL) || (localName == NULL))
24371 return (-1);
24372 *nsName = NULL;
24373 *localName = NULL;
24374
24375 ret = xmlValidateQName(value, 1);
24376 if (ret == -1)
24377 return (-1);
24378 if (ret > 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024379 xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024380 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24381 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24382 return (1);
24383 }
24384 {
24385 xmlChar *local = NULL;
24386 xmlChar *prefix;
24387
24388 /*
24389 * NOTE: xmlSplitQName2 will return a duplicated
24390 * string.
24391 */
24392 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024393 if (local == NULL)
24394 *localName = xmlDictLookup(vctxt->dict, value, -1);
24395 else {
24396 *localName = xmlDictLookup(vctxt->dict, local, -1);
24397 xmlFree(local);
24398 }
24399
24400 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24401
24402 if (prefix != NULL) {
24403 xmlFree(prefix);
24404 /*
24405 * A namespace must be found if the prefix is NOT NULL.
24406 */
24407 if (*nsName == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024408 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024409 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024410 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024411 "The QName value '%s' has no "
24412 "corresponding namespace declaration in scope",
24413 value, NULL);
24414 return (2);
24415 }
24416 }
24417 }
24418 return (0);
24419}
24420
24421static int
24422xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24423 xmlSchemaAttrInfoPtr iattr,
24424 xmlSchemaTypePtr *localType,
24425 xmlSchemaElementPtr elemDecl)
24426{
24427 int ret = 0;
24428 /*
24429 * cvc-elt (3.3.4) : (4)
24430 * AND
24431 * Schema-Validity Assessment (Element) (cvc-assess-elt)
24432 * (1.2.1.2.1) - (1.2.1.2.4)
24433 * Handle 'xsi:type'.
24434 */
24435 if (localType == NULL)
24436 return (-1);
24437 *localType = NULL;
24438 if (iattr == NULL)
24439 return (0);
24440 else {
24441 const xmlChar *nsName = NULL, *local = NULL;
24442 /*
24443 * TODO: We should report a *warning* that the type was overriden
24444 * by the instance.
24445 */
24446 ACTIVATE_ATTRIBUTE(iattr);
24447 /*
24448 * (cvc-elt) (3.3.4) : (4.1)
24449 * (cvc-assess-elt) (1.2.1.2.2)
24450 */
24451 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24452 &nsName, &local);
24453 if (ret != 0) {
24454 if (ret < 0) {
24455 VERROR_INT("xmlSchemaValidateElementByDeclaration",
24456 "calling xmlSchemaQNameExpand() to validate the "
24457 "attribute 'xsi:type'");
24458 goto internal_error;
24459 }
24460 goto exit;
24461 }
24462 /*
24463 * (cvc-elt) (3.3.4) : (4.2)
24464 * (cvc-assess-elt) (1.2.1.2.3)
24465 */
24466 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24467 if (*localType == NULL) {
24468 xmlChar *str = NULL;
24469
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024470 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024471 XML_SCHEMAV_CVC_ELT_4_2, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024472 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024473 "The QName value '%s' of the xsi:type attribute does not "
24474 "resolve to a type definition",
24475 xmlSchemaFormatQName(&str, nsName, local), NULL);
24476 FREE_AND_NULL(str);
24477 ret = vctxt->err;
24478 goto exit;
24479 }
24480 if (elemDecl != NULL) {
24481 int set = 0;
24482
24483 /*
24484 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24485 * "The ·local type definition· must be validly
24486 * derived from the {type definition} given the union of
24487 * the {disallowed substitutions} and the {type definition}'s
24488 * {prohibited substitutions}, as defined in
24489 * Type Derivation OK (Complex) (§3.4.6)
24490 * (if it is a complex type definition),
24491 * or given {disallowed substitutions} as defined in Type
24492 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
24493 * definition)."
24494 *
24495 * {disallowed substitutions}: the "block" on the element decl.
24496 * {prohibited substitutions}: the "block" on the type def.
24497 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000024498 /*
24499 * OPTIMIZE TODO: We could map types already evaluated
24500 * to be validly derived from other types to avoid checking
24501 * this over and over for the same types.
24502 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024503 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24504 (elemDecl->subtypes->flags &
24505 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24506 set |= SUBSET_EXTENSION;
24507
24508 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24509 (elemDecl->subtypes->flags &
24510 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24511 set |= SUBSET_RESTRICTION;
24512
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000024513 /*
24514 * REMOVED and CHANGED since this produced a parser context
24515 * which adds to the string dict of the schema. So this would
24516 * change the schema and we don't want this. We don't need
24517 * the parser context anymore.
24518 *
24519 * if ((vctxt->pctxt == NULL) &&
24520 * (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24521 * return (-1);
24522 */
24523
24524 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024525 elemDecl->subtypes, set) != 0) {
24526 xmlChar *str = NULL;
24527
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024528 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024529 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24530 "The type definition '%s', specified by xsi:type, is "
24531 "blocked or not validly derived from the type definition "
24532 "of the element declaration",
24533 xmlSchemaFormatQName(&str,
24534 (*localType)->targetNamespace,
24535 (*localType)->name),
24536 NULL);
24537 FREE_AND_NULL(str);
24538 ret = vctxt->err;
24539 *localType = NULL;
24540 }
24541 }
24542 }
24543exit:
24544 ACTIVATE_ELEM;
24545 return (ret);
24546internal_error:
24547 ACTIVATE_ELEM;
24548 return (-1);
24549}
24550
24551static int
24552xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24553{
24554 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024555 xmlSchemaTypePtr actualType = WXS_ELEM_TYPEDEF(elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024556
24557 /*
24558 * cvc-elt (3.3.4) : 1
24559 */
24560 if (elemDecl == NULL) {
24561 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
24562 "No matching declaration available");
24563 return (vctxt->err);
24564 }
24565 /*
24566 * cvc-elt (3.3.4) : 2
24567 */
24568 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
24569 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
24570 "The element declaration is abstract");
24571 return (vctxt->err);
24572 }
24573 if (actualType == NULL) {
24574 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24575 "The type definition is absent");
24576 return (XML_SCHEMAV_CVC_TYPE_1);
24577 }
24578 if (vctxt->nbAttrInfos != 0) {
24579 int ret;
24580 xmlSchemaAttrInfoPtr iattr;
24581 /*
24582 * cvc-elt (3.3.4) : 3
24583 * Handle 'xsi:nil'.
24584 */
24585 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24586 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
24587 if (iattr) {
24588 ACTIVATE_ATTRIBUTE(iattr);
24589 /*
24590 * Validate the value.
24591 */
24592 ret = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024593 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024594 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
24595 iattr->value, &(iattr->val), 1, 0, 0);
24596 ACTIVATE_ELEM;
24597 if (ret < 0) {
24598 VERROR_INT("xmlSchemaValidateElemDecl",
24599 "calling xmlSchemaVCheckCVCSimpleType() to "
24600 "validate the attribute 'xsi:nil'");
24601 return (-1);
24602 }
24603 if (ret == 0) {
24604 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
24605 /*
24606 * cvc-elt (3.3.4) : 3.1
24607 */
24608 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
24609 "The element is not 'nillable'");
24610 /* Does not return an error on purpose. */
24611 } else {
24612 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
24613 /*
24614 * cvc-elt (3.3.4) : 3.2.2
24615 */
24616 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
24617 (elemDecl->value != NULL)) {
24618 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
24619 "The element cannot be 'nilled' because "
24620 "there is a fixed value constraint defined "
24621 "for it");
24622 /* Does not return an error on purpose. */
24623 } else
24624 vctxt->inode->flags |=
24625 XML_SCHEMA_ELEM_INFO_NILLED;
24626 }
24627 }
24628 }
24629 }
24630 /*
24631 * cvc-elt (3.3.4) : 4
24632 * Handle 'xsi:type'.
24633 */
24634 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24635 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
24636 if (iattr) {
24637 xmlSchemaTypePtr localType = NULL;
24638
24639 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
24640 elemDecl);
24641 if (ret != 0) {
24642 if (ret == -1) {
24643 VERROR_INT("xmlSchemaValidateElemDecl",
24644 "calling xmlSchemaProcessXSIType() to "
24645 "process the attribute 'xsi:type'");
24646 return (-1);
24647 }
24648 /* Does not return an error on purpose. */
24649 }
24650 if (localType != NULL) {
24651 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
24652 actualType = localType;
24653 }
24654 }
24655 }
24656 /*
24657 * IDC: Register identity-constraint XPath matchers.
24658 */
24659 if ((elemDecl->idcs != NULL) &&
24660 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
24661 return (-1);
24662 /*
24663 * No actual type definition.
24664 */
24665 if (actualType == NULL) {
24666 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24667 "The type definition is absent");
24668 return (XML_SCHEMAV_CVC_TYPE_1);
24669 }
24670 /*
24671 * Remember the actual type definition.
24672 */
24673 vctxt->inode->typeDef = actualType;
24674
24675 return (0);
24676}
24677
24678static int
24679xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
24680{
24681 xmlSchemaAttrInfoPtr iattr;
24682 int ret = 0, i;
24683
24684 /*
24685 * SPEC cvc-type (3.1.1)
24686 * "The attributes of must be empty, excepting those whose namespace
24687 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
24688 * whose local name is one of type, nil, schemaLocation or
24689 * noNamespaceSchemaLocation."
24690 */
24691 if (vctxt->nbAttrInfos == 0)
24692 return (0);
24693 for (i = 0; i < vctxt->nbAttrInfos; i++) {
24694 iattr = vctxt->attrInfos[i];
24695 if (! iattr->metaType) {
24696 ACTIVATE_ATTRIBUTE(iattr)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024697 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024698 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
24699 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
24700 }
24701 }
24702 ACTIVATE_ELEM
24703 return (ret);
24704}
24705
24706/*
24707* Cleanup currently used attribute infos.
24708*/
24709static void
24710xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
24711{
24712 int i;
24713 xmlSchemaAttrInfoPtr attr;
24714
24715 if (vctxt->nbAttrInfos == 0)
24716 return;
24717 for (i = 0; i < vctxt->nbAttrInfos; i++) {
24718 attr = vctxt->attrInfos[i];
24719 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24720 if (attr->localName != NULL)
24721 xmlFree((xmlChar *) attr->localName);
24722 if (attr->nsName != NULL)
24723 xmlFree((xmlChar *) attr->nsName);
24724 }
24725 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24726 if (attr->value != NULL)
24727 xmlFree((xmlChar *) attr->value);
24728 }
24729 if (attr->val != NULL) {
24730 xmlSchemaFreeValue(attr->val);
24731 attr->val = NULL;
24732 }
24733 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
24734 }
24735 vctxt->nbAttrInfos = 0;
24736}
24737
24738/*
24739* 3.4.4 Complex Type Definition Validation Rules
24740* Element Locally Valid (Complex Type) (cvc-complex-type)
24741* 3.2.4 Attribute Declaration Validation Rules
24742* Validation Rule: Attribute Locally Valid (cvc-attribute)
24743* Attribute Locally Valid (Use) (cvc-au)
24744*
24745* Only "assessed" attribute information items will be visible to
24746* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
24747*/
24748static int
24749xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
24750{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024751 xmlSchemaTypePtr type = vctxt->inode->typeDef;
24752 xmlSchemaItemListPtr attrUseList;
24753 xmlSchemaAttributeUsePtr attrUse = NULL;
24754 xmlSchemaAttributePtr attrDecl = NULL;
24755 xmlSchemaAttrInfoPtr iattr, tmpiattr;
24756 int i, j, found, nbAttrs, nbUses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024757 int xpathRes = 0, res, wildIDs = 0, fixed;
24758
24759 /*
24760 * SPEC (cvc-attribute)
24761 * (1) "The declaration must not be ·absent· (see Missing
24762 * Sub-components (§5.3) for how this can fail to be
24763 * the case)."
24764 * (2) "Its {type definition} must not be absent."
24765 *
24766 * NOTE (1) + (2): This is not handled here, since we currently do not
24767 * allow validation against schemas which have missing sub-components.
24768 *
24769 * SPEC (cvc-complex-type)
24770 * (3) "For each attribute information item in the element information
24771 * item's [attributes] excepting those whose [namespace name] is
24772 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
24773 * [local name] is one of type, nil, schemaLocation or
24774 * noNamespaceSchemaLocation, the appropriate case among the following
24775 * must be true:
24776 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024777 */
24778 attrUseList = (xmlSchemaItemListPtr) type->attrUses;
24779 /*
24780 * @nbAttrs is the number of attributes present in the instance.
24781 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024782 nbAttrs = vctxt->nbAttrInfos;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024783 if (attrUseList != NULL)
24784 nbUses = attrUseList->nbItems;
24785 else
24786 nbUses = 0;
24787 for (i = 0; i < nbUses; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024788 found = 0;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024789 attrUse = attrUseList->items[i];
24790 attrDecl = WXS_ATTRUSE_DECL(attrUse);
24791 for (j = 0; j < nbAttrs; j++) {
24792 iattr = vctxt->attrInfos[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024793 /*
24794 * SPEC (cvc-complex-type) (3)
24795 * Skip meta attributes.
24796 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024797 if (iattr->metaType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024798 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024799 if (iattr->localName[0] != attrDecl->name[0])
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024800 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024801 if (!xmlStrEqual(iattr->localName, attrDecl->name))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024802 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024803 if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024804 continue;
24805 found = 1;
24806 /*
24807 * SPEC (cvc-complex-type)
24808 * (3.1) "If there is among the {attribute uses} an attribute
24809 * use with an {attribute declaration} whose {name} matches
24810 * the attribute information item's [local name] and whose
24811 * {target namespace} is identical to the attribute information
24812 * item's [namespace name] (where an ·absent· {target namespace}
24813 * is taken to be identical to a [namespace name] with no value),
24814 * then the attribute information must be ·valid· with respect
24815 * to that attribute use as per Attribute Locally Valid (Use)
24816 * (§3.5.4). In this case the {attribute declaration} of that
24817 * attribute use is the ·context-determined declaration· for the
24818 * attribute information item with respect to Schema-Validity
24819 * Assessment (Attribute) (§3.2.4) and
24820 * Assessment Outcome (Attribute) (§3.2.5).
24821 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024822 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
24823 iattr->use = attrUse;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024824 /*
24825 * Context-determined declaration.
24826 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024827 iattr->decl = attrDecl;
24828 iattr->typeDef = attrDecl->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024829 break;
24830 }
24831
24832 if (found)
24833 continue;
24834
24835 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
24836 /*
24837 * Handle non-existent, required attributes.
24838 *
24839 * SPEC (cvc-complex-type)
24840 * (4) "The {attribute declaration} of each attribute use in
24841 * the {attribute uses} whose {required} is true matches one
24842 * of the attribute information items in the element information
24843 * item's [attributes] as per clause 3.1 above."
24844 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024845 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
24846 if (tmpiattr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024847 VERROR_INT(
24848 "xmlSchemaVAttributesComplex",
24849 "calling xmlSchemaGetFreshAttrInfo()");
24850 return (-1);
24851 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024852 tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
24853 tmpiattr->use = attrUse;
24854 tmpiattr->decl = attrDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024855 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
24856 ((attrUse->defValue != NULL) ||
24857 (attrDecl->defValue != NULL))) {
24858 /*
24859 * Handle non-existent, optional, default/fixed attributes.
24860 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024861 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
24862 if (tmpiattr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024863 VERROR_INT(
24864 "xmlSchemaVAttributesComplex",
24865 "calling xmlSchemaGetFreshAttrInfo()");
24866 return (-1);
24867 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024868 tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
24869 tmpiattr->use = attrUse;
24870 tmpiattr->decl = attrDecl;
24871 tmpiattr->typeDef = attrDecl->subtypes;
24872 tmpiattr->localName = attrDecl->name;
24873 tmpiattr->nsName = attrDecl->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024874 }
24875 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024876
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024877 if (vctxt->nbAttrInfos == 0)
24878 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024879 nbUses = vctxt->nbAttrInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024880 /*
24881 * Validate against the wildcard.
24882 */
24883 if (type->attributeWildcard != NULL) {
24884 /*
24885 * SPEC (cvc-complex-type)
24886 * (3.2.1) "There must be an {attribute wildcard}."
24887 */
24888 for (i = 0; i < nbAttrs; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024889 iattr = vctxt->attrInfos[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024890 /*
24891 * SPEC (cvc-complex-type) (3)
24892 * Skip meta attributes.
24893 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024894 if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024895 continue;
24896 /*
24897 * SPEC (cvc-complex-type)
24898 * (3.2.2) "The attribute information item must be ·valid· with
24899 * respect to it as defined in Item Valid (Wildcard) (§3.10.4)."
24900 *
24901 * SPEC Item Valid (Wildcard) (cvc-wildcard)
24902 * "... its [namespace name] must be ·valid· with respect to
24903 * the wildcard constraint, as defined in Wildcard allows
24904 * Namespace Name (§3.10.4)."
24905 */
24906 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024907 iattr->nsName) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024908 /*
24909 * Handle processContents.
24910 *
24911 * SPEC (cvc-wildcard):
24912 * processContents | context-determined declaration:
24913 * "strict" "mustFind"
24914 * "lax" "none"
24915 * "skip" "skip"
24916 */
24917 if (type->attributeWildcard->processContents ==
24918 XML_SCHEMAS_ANY_SKIP) {
24919 /*
24920 * context-determined declaration = "skip"
24921 *
24922 * SPEC PSVI Assessment Outcome (Attribute)
24923 * [validity] = "notKnown"
24924 * [validation attempted] = "none"
24925 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024926 iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024927 continue;
24928 }
24929 /*
24930 * Find an attribute declaration.
24931 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024932 iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
24933 iattr->localName, iattr->nsName);
24934 if (iattr->decl != NULL) {
24935 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024936 /*
24937 * SPEC (cvc-complex-type)
24938 * (5) "Let [Definition:] the wild IDs be the set of
24939 * all attribute information item to which clause 3.2
24940 * applied and whose ·validation· resulted in a
24941 * ·context-determined declaration· of mustFind or no
24942 * ·context-determined declaration· at all, and whose
24943 * [local name] and [namespace name] resolve (as
24944 * defined by QName resolution (Instance) (§3.15.4)) to
24945 * an attribute declaration whose {type definition} is
24946 * or is derived from ID. Then all of the following
24947 * must be true:"
24948 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024949 iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024950 if (xmlSchemaIsDerivedFromBuiltInType(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024951 iattr->typeDef, XML_SCHEMAS_ID)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024952 /*
24953 * SPEC (5.1) "There must be no more than one
24954 * item in ·wild IDs·."
24955 */
24956 if (wildIDs != 0) {
24957 /* VAL TODO */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024958 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024959 TODO
24960 continue;
24961 }
24962 wildIDs++;
24963 /*
24964 * SPEC (cvc-complex-type)
24965 * (5.2) "If ·wild IDs· is non-empty, there must not
24966 * be any attribute uses among the {attribute uses}
24967 * whose {attribute declaration}'s {type definition}
24968 * is or is derived from ID."
24969 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024970 for (j = 0; j < attrUseList->nbItems; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024971 if (xmlSchemaIsDerivedFromBuiltInType(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024972 WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024973 XML_SCHEMAS_ID)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024974 /* URGENT VAL TODO: implement */
24975 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024976 TODO
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024977 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024978 }
24979 }
24980 }
24981 } else if (type->attributeWildcard->processContents ==
24982 XML_SCHEMAS_ANY_LAX) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024983 iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024984 /*
24985 * SPEC PSVI Assessment Outcome (Attribute)
24986 * [validity] = "notKnown"
24987 * [validation attempted] = "none"
24988 */
24989 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024990 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024991 }
24992 }
24993 }
24994 }
24995
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024996 if (vctxt->nbAttrInfos == 0)
24997 return (0);
24998
24999 /*
25000 * Validate values, create default attributes, evaluate IDCs.
25001 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025002 for (i = 0; i < vctxt->nbAttrInfos; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025003 iattr = vctxt->attrInfos[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025004 /*
25005 * VAL TODO: Note that we won't try to resolve IDCs to
25006 * "lax" and "skip" validated attributes. Check what to
25007 * do in this case.
25008 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025009 if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25010 (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025011 continue;
25012 /*
25013 * VAL TODO: What to do if the type definition is missing?
25014 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025015 if (iattr->typeDef == NULL) {
25016 iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025017 continue;
25018 }
25019
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025020 ACTIVATE_ATTRIBUTE(iattr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000025021 fixed = 0;
25022 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025023
25024 if (vctxt->xpathStates != NULL) {
25025 /*
25026 * Evaluate IDCs.
25027 */
25028 xpathRes = xmlSchemaXPathEvaluate(vctxt,
25029 XML_ATTRIBUTE_NODE);
25030 if (xpathRes == -1) {
25031 VERROR_INT("xmlSchemaVAttributesComplex",
25032 "calling xmlSchemaXPathEvaluate()");
25033 goto internal_error;
25034 }
25035 }
25036
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025037 if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025038 /*
25039 * Default/fixed attributes.
25040 */
25041 if (xpathRes) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025042 if (iattr->use->defValue != NULL) {
25043 iattr->value = (xmlChar *) iattr->use->defValue;
25044 iattr->val = iattr->use->defVal;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025045 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025046 iattr->value = (xmlChar *) iattr->decl->defValue;
25047 iattr->val = iattr->decl->defVal;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025048 }
25049 /*
25050 * IDCs will consume the precomputed default value,
25051 * so we need to clone it.
25052 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025053 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025054 VERROR_INT("xmlSchemaVAttributesComplex",
25055 "default/fixed value on an attribute use was "
25056 "not precomputed");
25057 goto internal_error;
25058 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025059 iattr->val = xmlSchemaCopyValue(iattr->val);
25060 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025061 VERROR_INT("xmlSchemaVAttributesComplex",
25062 "calling xmlSchemaCopyValue()");
25063 goto internal_error;
25064 }
25065 }
25066 /*
25067 * PSVI: Add the default attribute to the current element.
25068 * VAL TODO: Should we use the *normalized* value? This currently
25069 * uses the *initial* value.
25070 */
25071 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025072 (iattr->node != NULL) && (iattr->node->doc != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025073 xmlChar *normValue;
25074 const xmlChar *value;
25075
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025076 value = iattr->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025077 /*
25078 * Normalize the value.
25079 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025080 normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25081 iattr->value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025082 if (normValue != NULL)
25083 value = BAD_CAST normValue;
25084
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025085 if (iattr->nsName == NULL) {
25086 if (xmlNewProp(iattr->node->parent,
25087 iattr->localName, value) == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025088 VERROR_INT("xmlSchemaVAttributesComplex",
25089 "callling xmlNewProp()");
25090 if (normValue != NULL)
25091 xmlFree(normValue);
25092 goto internal_error;
25093 }
25094 } else {
25095 xmlNsPtr ns;
25096
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025097 ns = xmlSearchNsByHref(iattr->node->doc,
25098 iattr->node->parent, iattr->nsName);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025099 if (ns == NULL) {
25100 xmlChar prefix[12];
25101 int counter = 0;
25102
25103 /*
25104 * Create a namespace declaration on the validation
25105 * root node if no namespace declaration is in scope.
25106 */
25107 do {
25108 snprintf((char *) prefix, 12, "p%d", counter++);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025109 ns = xmlSearchNs(iattr->node->doc,
25110 iattr->node->parent, BAD_CAST prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025111 if (counter > 1000) {
25112 VERROR_INT(
25113 "xmlSchemaVAttributesComplex",
25114 "could not compute a ns prefix for a "
25115 "default/fixed attribute");
25116 if (normValue != NULL)
25117 xmlFree(normValue);
25118 goto internal_error;
25119 }
25120 } while (ns != NULL);
25121 ns = xmlNewNs(vctxt->validationRoot,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025122 iattr->nsName, BAD_CAST prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025123 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025124 /*
25125 * TODO:
25126 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25127 * If we have QNames: do we need to ensure there's a
25128 * prefix defined for the QName?
25129 */
25130 xmlNewNsProp(iattr->node->parent, ns,
25131 iattr->localName, value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025132 }
25133 if (normValue != NULL)
25134 xmlFree(normValue);
25135 }
25136 /*
25137 * Go directly to IDC evaluation.
25138 */
25139 goto eval_idcs;
25140 }
25141 /*
25142 * Validate the value.
25143 */
25144 if (vctxt->value != NULL) {
25145 /*
25146 * Free last computed value; just for safety reasons.
25147 */
25148 xmlSchemaFreeValue(vctxt->value);
25149 vctxt->value = NULL;
25150 }
25151 /*
25152 * Note that the attribute *use* can be unavailable, if
25153 * the attribute was a wild attribute.
25154 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025155 if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25156 ((iattr->use != NULL) &&
25157 (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025158 fixed = 1;
25159 else
25160 fixed = 0;
25161 /*
25162 * SPEC (cvc-attribute)
25163 * (3) "The item's ·normalized value· must be locally ·valid·
25164 * with respect to that {type definition} as per
25165 * String Valid (§3.14.4)."
25166 *
25167 * VAL TODO: Do we already have the
25168 * "normalized attribute value" here?
25169 */
25170 if (xpathRes || fixed) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025171 iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025172 /*
25173 * Request a computed value.
25174 */
25175 res = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025176 ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025177 iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025178 1, 1, 0);
25179 } else {
25180 res = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025181 ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025182 iattr->node, iattr->typeDef, iattr->value, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025183 1, 0, 0);
25184 }
25185
25186 if (res != 0) {
25187 if (res == -1) {
25188 VERROR_INT("xmlSchemaVAttributesComplex",
25189 "calling xmlSchemaStreamValidateSimpleTypeValue()");
25190 goto internal_error;
25191 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025192 iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025193 /*
25194 * SPEC PSVI Assessment Outcome (Attribute)
25195 * [validity] = "invalid"
25196 */
25197 goto eval_idcs;
25198 }
25199
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025200 if (fixed) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025201 /*
25202 * SPEC Attribute Locally Valid (Use) (cvc-au)
25203 * "For an attribute information item to be·valid·
25204 * with respect to an attribute use its *normalized*
25205 * value· must match the *canonical* lexical
25206 * representation of the attribute use's {value
25207 * constraint}value, if it is present and fixed."
25208 *
25209 * VAL TODO: The requirement for the *canonical* value
25210 * will be removed in XML Schema 1.1.
25211 */
25212 /*
25213 * SPEC Attribute Locally Valid (cvc-attribute)
25214 * (4) "The item's *actual* value· must match the *value* of
25215 * the {value constraint}, if it is present and fixed."
25216 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025217 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025218 /* VAL TODO: A value was not precomputed. */
25219 TODO
25220 goto eval_idcs;
25221 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025222 if ((iattr->use != NULL) &&
25223 (iattr->use->defValue != NULL)) {
25224 if (iattr->use->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025225 /* VAL TODO: A default value was not precomputed. */
25226 TODO
25227 goto eval_idcs;
25228 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025229 iattr->vcValue = iattr->use->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025230 /*
25231 if (xmlSchemaCompareValuesWhtsp(attr->val,
25232 (xmlSchemaWhitespaceValueType) ws,
25233 attr->use->defVal,
25234 (xmlSchemaWhitespaceValueType) ws) != 0) {
25235 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025236 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25237 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025238 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025239 if (iattr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025240 /* VAL TODO: A default value was not precomputed. */
25241 TODO
25242 goto eval_idcs;
25243 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025244 iattr->vcValue = iattr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025245 /*
25246 if (xmlSchemaCompareValuesWhtsp(attr->val,
25247 (xmlSchemaWhitespaceValueType) ws,
25248 attrDecl->defVal,
25249 (xmlSchemaWhitespaceValueType) ws) != 0) {
25250 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025251 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25252 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025253 }
25254 /*
25255 * [validity] = "valid"
25256 */
25257 }
25258eval_idcs:
25259 /*
25260 * Evaluate IDCs.
25261 */
25262 if (xpathRes) {
25263 if (xmlSchemaXPathProcessHistory(vctxt,
25264 vctxt->depth +1) == -1) {
25265 VERROR_INT("xmlSchemaVAttributesComplex",
25266 "calling xmlSchemaXPathEvaluate()");
25267 goto internal_error;
25268 }
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000025269 } else if (vctxt->xpathStates != NULL)
25270 xmlSchemaXPathPop(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025271 }
25272
25273 /*
25274 * Report errors.
25275 */
25276 for (i = 0; i < vctxt->nbAttrInfos; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025277 iattr = vctxt->attrInfos[i];
25278 if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25279 (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25280 (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25281 (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025282 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025283 ACTIVATE_ATTRIBUTE(iattr);
25284 switch (iattr->state) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025285 case XML_SCHEMAS_ATTR_ERR_MISSING: {
25286 xmlChar *str = NULL;
25287 ACTIVATE_ELEM;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025288 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025289 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25290 "The attribute '%s' is required but missing",
25291 xmlSchemaFormatQName(&str,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025292 iattr->decl->targetNamespace,
25293 iattr->decl->name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025294 NULL);
25295 FREE_AND_NULL(str)
25296 break;
25297 }
25298 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25299 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25300 "The type definition is absent");
25301 break;
25302 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025303 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025304 XML_SCHEMAV_CVC_AU, NULL, NULL,
25305 "The value '%s' does not match the fixed "
25306 "value constraint '%s'",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025307 iattr->value, iattr->vcValue);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025308 break;
25309 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25310 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25311 "No matching global attribute declaration available, but "
25312 "demanded by the strict wildcard");
25313 break;
25314 case XML_SCHEMAS_ATTR_UNKNOWN:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025315 if (iattr->metaType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025316 break;
25317 /*
25318 * MAYBE VAL TODO: One might report different error messages
25319 * for the following errors.
25320 */
25321 if (type->attributeWildcard == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025322 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025323 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025324 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025325 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025326 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025327 }
25328 break;
25329 default:
25330 break;
25331 }
25332 }
25333
25334 ACTIVATE_ELEM;
25335 return (0);
25336internal_error:
25337 ACTIVATE_ELEM;
25338 return (-1);
25339}
25340
25341static int
25342xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25343 int *skip)
25344{
25345 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25346 /*
25347 * The namespace of the element was already identified to be
25348 * matching the wildcard.
25349 */
25350 if ((skip == NULL) || (wild == NULL) ||
25351 (wild->type != XML_SCHEMA_TYPE_ANY)) {
25352 VERROR_INT("xmlSchemaValidateElemWildcard",
25353 "bad arguments");
25354 return (-1);
25355 }
25356 *skip = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025357 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25358 /*
25359 * URGENT VAL TODO: Either we need to position the stream to the
25360 * next sibling, or walk the whole subtree.
25361 */
25362 *skip = 1;
25363 return (0);
25364 }
25365 {
25366 xmlSchemaElementPtr decl = NULL;
25367
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025368 decl = xmlSchemaGetElem(vctxt->schema,
25369 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025370 if (decl != NULL) {
25371 vctxt->inode->decl = decl;
25372 return (0);
25373 }
25374 }
25375 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25376 /* VAL TODO: Change to proper error code. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025377 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025378 "No matching global element declaration available, but "
25379 "demanded by the strict wildcard");
25380 return (vctxt->err);
25381 }
25382 if (vctxt->nbAttrInfos != 0) {
25383 xmlSchemaAttrInfoPtr iattr;
25384 /*
25385 * SPEC Validation Rule: Schema-Validity Assessment (Element)
25386 * (1.2.1.2.1) - (1.2.1.2.3 )
25387 *
25388 * Use the xsi:type attribute for the type definition.
25389 */
25390 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25391 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25392 if (iattr != NULL) {
25393 if (xmlSchemaProcessXSIType(vctxt, iattr,
25394 &(vctxt->inode->typeDef), NULL) == -1) {
25395 VERROR_INT("xmlSchemaValidateElemWildcard",
25396 "calling xmlSchemaProcessXSIType() to "
25397 "process the attribute 'xsi:nil'");
25398 return (-1);
25399 }
25400 /*
25401 * Don't return an error on purpose.
25402 */
25403 return (0);
25404 }
25405 }
25406 /*
25407 * SPEC Validation Rule: Schema-Validity Assessment (Element)
25408 *
25409 * Fallback to "anyType".
25410 */
25411 vctxt->inode->typeDef =
25412 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25413 return (0);
25414}
25415
25416/*
25417* xmlSchemaCheckCOSValidDefault:
25418*
25419* This will be called if: not nilled, no content and a default/fixed
25420* value is provided.
25421*/
25422
25423static int
25424xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25425 const xmlChar *value,
25426 xmlSchemaValPtr *val)
25427{
25428 int ret = 0;
25429 xmlSchemaNodeInfoPtr inode = vctxt->inode;
25430
25431 /*
25432 * cos-valid-default:
25433 * Schema Component Constraint: Element Default Valid (Immediate)
25434 * For a string to be a valid default with respect to a type
25435 * definition the appropriate case among the following must be true:
25436 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025437 if WXS_IS_COMPLEX(inode->typeDef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025438 /*
25439 * Complex type.
25440 *
25441 * SPEC (2.1) "its {content type} must be a simple type definition
25442 * or mixed."
25443 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
25444 * type}'s particle must be ·emptiable· as defined by
25445 * Particle Emptiable (§3.9.6)."
25446 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025447 if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25448 ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25449 (! WXS_EMPTIABLE(inode->typeDef)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025450 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25451 /* NOTE that this covers (2.2.2) as well. */
25452 VERROR(ret, NULL,
25453 "For a string to be a valid default, the type definition "
25454 "must be a simple type or a complex type with simple content "
25455 "or mixed content and a particle emptiable");
25456 return(ret);
25457 }
25458 }
25459 /*
25460 * 1 If the type definition is a simple type definition, then the string
25461 * must be ·valid· with respect to that definition as defined by String
25462 * Valid (§3.14.4).
25463 *
25464 * AND
25465 *
25466 * 2.2.1 If the {content type} is a simple type definition, then the
25467 * string must be ·valid· with respect to that simple type definition
25468 * as defined by String Valid (§3.14.4).
25469 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025470 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025471
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025472 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025473 NULL, inode->typeDef, value, val, 1, 1, 0);
25474
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025475 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025476
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025477 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025478 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25479 }
25480 if (ret < 0) {
25481 VERROR_INT("xmlSchemaCheckCOSValidDefault",
25482 "calling xmlSchemaVCheckCVCSimpleType()");
25483 }
25484 return (ret);
25485}
25486
25487static void
25488xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25489 const xmlChar * name ATTRIBUTE_UNUSED,
25490 xmlSchemaElementPtr item,
25491 xmlSchemaNodeInfoPtr inode)
25492{
25493 inode->decl = item;
25494#ifdef DEBUG_CONTENT
25495 {
25496 xmlChar *str = NULL;
25497
25498 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25499 xmlGenericError(xmlGenericErrorContext,
25500 "AUTOMATON callback for '%s' [declaration]\n",
25501 xmlSchemaFormatQName(&str,
25502 inode->localName, inode->nsName));
25503 } else {
25504 xmlGenericError(xmlGenericErrorContext,
25505 "AUTOMATON callback for '%s' [wildcard]\n",
25506 xmlSchemaFormatQName(&str,
25507 inode->localName, inode->nsName));
25508
25509 }
25510 FREE_AND_NULL(str)
25511 }
25512#endif
25513}
25514
25515static int
25516xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000025517{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025518 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25519 if (vctxt->inode == NULL) {
25520 VERROR_INT("xmlSchemaValidatorPushElem",
25521 "calling xmlSchemaGetFreshElemInfo()");
25522 return (-1);
25523 }
25524 vctxt->nbAttrInfos = 0;
25525 return (0);
25526}
25527
25528static int
25529xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25530 xmlSchemaNodeInfoPtr inode,
25531 xmlSchemaTypePtr type,
25532 const xmlChar *value)
25533{
25534 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25535 return (xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025536 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025537 type, value, &(inode->val), 1, 1, 0));
25538 else
25539 return (xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025540 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025541 type, value, NULL, 1, 0, 0));
25542}
25543
25544
25545
25546/*
25547* Process END of element.
25548*/
25549static int
25550xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
25551{
25552 int ret = 0;
25553 xmlSchemaNodeInfoPtr inode = vctxt->inode;
25554
25555 if (vctxt->nbAttrInfos != 0)
25556 xmlSchemaClearAttrInfos(vctxt);
25557 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
25558 /*
25559 * This element was not expected;
25560 * we will not validate child elements of broken parents.
25561 * Skip validation of all content of the parent.
25562 */
25563 vctxt->skipDepth = vctxt->depth -1;
25564 goto end_elem;
25565 }
25566 if ((inode->typeDef == NULL) ||
25567 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
25568 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000025569 * 1. the type definition might be missing if the element was
25570 * error prone
25571 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025572 */
25573 goto end_elem;
25574 }
25575 /*
25576 * Check the content model.
25577 */
25578 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
25579 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
25580
25581 /*
25582 * Workaround for "anyType".
25583 */
25584 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
25585 goto character_content;
25586
25587 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
25588 xmlChar *values[10];
25589 int terminal, nbval = 10, nbneg;
25590
25591 if (inode->regexCtxt == NULL) {
25592 /*
25593 * Create the regex context.
25594 */
25595 inode->regexCtxt =
25596 xmlRegNewExecCtxt(inode->typeDef->contModel,
25597 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
25598 vctxt);
25599 if (inode->regexCtxt == NULL) {
25600 VERROR_INT("xmlSchemaValidatorPopElem",
25601 "failed to create a regex context");
25602 goto internal_error;
25603 }
25604#ifdef DEBUG_AUTOMATA
25605 xmlGenericError(xmlGenericErrorContext,
25606 "AUTOMATON create on '%s'\n", inode->localName);
25607#endif
25608 }
25609 /*
25610 * Get hold of the still expected content, since a further
25611 * call to xmlRegExecPushString() will loose this information.
25612 */
25613 xmlRegExecNextValues(inode->regexCtxt,
25614 &nbval, &nbneg, &values[0], &terminal);
25615 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
25616 if (ret <= 0) {
25617 /*
25618 * Still missing something.
25619 */
25620 ret = 1;
25621 inode->flags |=
25622 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025623 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025624 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
25625 "Missing child element(s)",
25626 nbval, nbneg, values);
25627#ifdef DEBUG_AUTOMATA
25628 xmlGenericError(xmlGenericErrorContext,
25629 "AUTOMATON missing ERROR on '%s'\n",
25630 inode->localName);
25631#endif
25632 } else {
25633 /*
25634 * Content model is satisfied.
25635 */
25636 ret = 0;
25637#ifdef DEBUG_AUTOMATA
25638 xmlGenericError(xmlGenericErrorContext,
25639 "AUTOMATON succeeded on '%s'\n",
25640 inode->localName);
25641#endif
25642 }
25643
25644 }
25645 }
25646 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
25647 goto end_elem;
25648
25649character_content:
25650
25651 if (vctxt->value != NULL) {
25652 xmlSchemaFreeValue(vctxt->value);
25653 vctxt->value = NULL;
25654 }
25655 /*
25656 * Check character content.
25657 */
25658 if (inode->decl == NULL) {
25659 /*
25660 * Speedup if no declaration exists.
25661 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025662 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025663 ret = xmlSchemaVCheckINodeDataType(vctxt,
25664 inode, inode->typeDef, inode->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025665 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025666 ret = xmlSchemaVCheckINodeDataType(vctxt,
25667 inode, inode->typeDef->contentTypeDef,
25668 inode->value);
25669 }
25670 if (ret < 0) {
25671 VERROR_INT("xmlSchemaValidatorPopElem",
25672 "calling xmlSchemaVCheckCVCSimpleType()");
25673 goto internal_error;
25674 }
25675 goto end_elem;
25676 }
25677 /*
25678 * cvc-elt (3.3.4) : 5
25679 * The appropriate case among the following must be true:
25680 */
25681 /*
25682 * cvc-elt (3.3.4) : 5.1
25683 * If the declaration has a {value constraint},
25684 * the item has neither element nor character [children] and
25685 * clause 3.2 has not applied, then all of the following must be true:
25686 */
25687 if ((inode->decl->value != NULL) &&
25688 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
25689 (! INODE_NILLED(inode))) {
25690 /*
25691 * cvc-elt (3.3.4) : 5.1.1
25692 * If the ·actual type definition· is a ·local type definition·
25693 * then the canonical lexical representation of the {value constraint}
25694 * value must be a valid default for the ·actual type definition· as
25695 * defined in Element Default Valid (Immediate) (§3.3.6).
25696 */
25697 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025698 * NOTE: 'local' above means types acquired by xsi:type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025699 * NOTE: Although the *canonical* value is stated, it is not
25700 * relevant if canonical or not. Additionally XML Schema 1.1
25701 * will removed this requirement as well.
25702 */
25703 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
25704
25705 ret = xmlSchemaCheckCOSValidDefault(vctxt,
25706 inode->decl->value, &(inode->val));
25707 if (ret != 0) {
25708 if (ret < 0) {
25709 VERROR_INT("xmlSchemaValidatorPopElem",
25710 "calling xmlSchemaCheckCOSValidDefault()");
25711 goto internal_error;
25712 }
25713 goto end_elem;
25714 }
25715 /*
25716 * Stop here, to avoid redundant validation of the value
25717 * (see following).
25718 */
25719 goto default_psvi;
25720 }
25721 /*
25722 * cvc-elt (3.3.4) : 5.1.2
25723 * The element information item with the canonical lexical
25724 * representation of the {value constraint} value used as its
25725 * ·normalized value· must be ·valid· with respect to the
25726 * ·actual type definition· as defined by Element Locally Valid (Type)
25727 * (§3.3.4).
25728 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025729 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025730 ret = xmlSchemaVCheckINodeDataType(vctxt,
25731 inode, inode->typeDef, inode->decl->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025732 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025733 ret = xmlSchemaVCheckINodeDataType(vctxt,
25734 inode, inode->typeDef->contentTypeDef,
25735 inode->decl->value);
25736 }
25737 if (ret != 0) {
25738 if (ret < 0) {
25739 VERROR_INT("xmlSchemaValidatorPopElem",
25740 "calling xmlSchemaVCheckCVCSimpleType()");
25741 goto internal_error;
25742 }
25743 goto end_elem;
25744 }
25745
25746default_psvi:
25747 /*
25748 * PSVI: Create a text node on the instance element.
25749 */
25750 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
25751 (inode->node != NULL)) {
25752 xmlNodePtr textChild;
25753 xmlChar *normValue;
25754 /*
25755 * VAL TODO: Normalize the value.
25756 */
25757 normValue = xmlSchemaNormalizeValue(inode->typeDef,
25758 inode->decl->value);
25759 if (normValue != NULL) {
25760 textChild = xmlNewText(BAD_CAST normValue);
25761 xmlFree(normValue);
25762 } else
25763 textChild = xmlNewText(inode->decl->value);
25764 if (textChild == NULL) {
25765 VERROR_INT("xmlSchemaValidatorPopElem",
25766 "calling xmlNewText()");
25767 goto internal_error;
25768 } else
25769 xmlAddChild(inode->node, textChild);
25770 }
25771
25772 } else if (! INODE_NILLED(inode)) {
25773 /*
25774 * 5.2.1 The element information item must be ·valid· with respect
25775 * to the ·actual type definition· as defined by Element Locally
25776 * Valid (Type) (§3.3.4).
25777 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025778 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025779 /*
25780 * SPEC (cvc-type) (3.1)
25781 * "If the type definition is a simple type definition, ..."
25782 * (3.1.3) "If clause 3.2 of Element Locally Valid
25783 * (Element) (§3.3.4) did not apply, then the ·normalized value·
25784 * must be ·valid· with respect to the type definition as defined
25785 * by String Valid (§3.14.4).
25786 */
25787 ret = xmlSchemaVCheckINodeDataType(vctxt,
25788 inode, inode->typeDef, inode->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025789 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025790 /*
25791 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
25792 * definition, then the element information item must be
25793 * ·valid· with respect to the type definition as per
25794 * Element Locally Valid (Complex Type) (§3.4.4);"
25795 *
25796 * SPEC (cvc-complex-type) (2.2)
25797 * "If the {content type} is a simple type definition, ...
25798 * the ·normalized value· of the element information item is
25799 * ·valid· with respect to that simple type definition as
25800 * defined by String Valid (§3.14.4)."
25801 */
25802 ret = xmlSchemaVCheckINodeDataType(vctxt,
25803 inode, inode->typeDef->contentTypeDef, inode->value);
25804 }
25805 if (ret != 0) {
25806 if (ret < 0) {
25807 VERROR_INT("xmlSchemaValidatorPopElem",
25808 "calling xmlSchemaVCheckCVCSimpleType()");
25809 goto internal_error;
25810 }
25811 goto end_elem;
25812 }
25813 /*
25814 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
25815 * not applied, all of the following must be true:
25816 */
25817 if ((inode->decl->value != NULL) &&
25818 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
25819
25820 /*
25821 * TODO: We will need a computed value, when comparison is
25822 * done on computed values.
25823 */
25824 /*
25825 * 5.2.2.1 The element information item must have no element
25826 * information item [children].
25827 */
25828 if (inode->flags &
25829 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
25830 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
25831 VERROR(ret, NULL,
25832 "The content must not containt element nodes since "
25833 "there is a fixed value constraint");
25834 goto end_elem;
25835 } else {
25836 /*
25837 * 5.2.2.2 The appropriate case among the following must
25838 * be true:
25839 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025840 if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025841 /*
25842 * 5.2.2.2.1 If the {content type} of the ·actual type
25843 * definition· is mixed, then the *initial value* of the
25844 * item must match the canonical lexical representation
25845 * of the {value constraint} value.
25846 *
25847 * ... the *initial value* of an element information
25848 * item is the string composed of, in order, the
25849 * [character code] of each character information item in
25850 * the [children] of that element information item.
25851 */
25852 if (! xmlStrEqual(inode->value, inode->decl->value)){
25853 /*
25854 * VAL TODO: Report invalid & expected values as well.
25855 * VAL TODO: Implement the canonical stuff.
25856 */
25857 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025858 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025859 ret, NULL, NULL,
25860 "The initial value '%s' does not match the fixed "
25861 "value constraint '%s'",
25862 inode->value, inode->decl->value);
25863 goto end_elem;
25864 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025865 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025866 /*
25867 * 5.2.2.2.2 If the {content type} of the ·actual type
25868 * definition· is a simple type definition, then the
25869 * *actual value* of the item must match the canonical
25870 * lexical representation of the {value constraint} value.
25871 */
25872 /*
25873 * VAL TODO: *actual value* is the normalized value, impl.
25874 * this.
25875 * VAL TODO: Report invalid & expected values as well.
25876 * VAL TODO: Implement a comparison with the computed values.
25877 */
25878 if (! xmlStrEqual(inode->value,
25879 inode->decl->value)) {
25880 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025881 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025882 ret, NULL, NULL,
25883 "The actual value '%s' does not match the fixed "
25884 "value constraint '%s'",
25885 inode->value,
25886 inode->decl->value);
25887 goto end_elem;
25888 }
25889 }
25890 }
25891 }
25892 }
25893
25894end_elem:
25895 if (vctxt->depth < 0) {
25896 /* TODO: raise error? */
25897 return (0);
25898 }
25899 if (vctxt->depth == vctxt->skipDepth)
25900 vctxt->skipDepth = -1;
25901 /*
25902 * Evaluate the history of XPath state objects.
25903 */
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000025904 if (inode->appliedXPath &&
25905 (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025906 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025907 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025908 * MAYBE TODO:
25909 * SPEC (6) "The element information item must be ·valid· with
25910 * respect to each of the {identity-constraint definitions} as per
25911 * Identity-constraint Satisfied (§3.11.4)."
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025912 */
25913 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025914 * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
25915 * need to be built in any case.
25916 * We will currently build IDC node-tables and bubble them only if
25917 * keyrefs do exist.
25918 */
25919
25920 /*
25921 * Add the current IDC target-nodes to the IDC node-tables.
25922 */
25923 if ((inode->idcMatchers != NULL) &&
25924 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
25925 {
25926 if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
25927 goto internal_error;
25928 }
25929 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025930 * Validate IDC keyrefs.
25931 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025932 if (vctxt->inode->hasKeyrefs)
25933 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
25934 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025935 /*
25936 * Merge/free the IDC table.
25937 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025938 if (inode->idcTable != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025939#ifdef DEBUG_IDC_NODE_TABLE
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025940 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025941 inode->nsName,
25942 inode->localName,
25943 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025944#endif
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025945 if ((vctxt->depth > 0) &&
25946 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
25947 {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025948 /*
25949 * Merge the IDC node table with the table of the parent node.
25950 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025951 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
25952 goto internal_error;
25953 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025954 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025955 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025956 * Clear the current ielem.
25957 * VAL TODO: Don't free the PSVI IDC tables if they are
25958 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025959 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025960 xmlSchemaClearElemInfo(inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025961 /*
25962 * Skip further processing if we are on the validation root.
25963 */
25964 if (vctxt->depth == 0) {
25965 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025966 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000025967 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025968 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025969 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025970 * Reset the keyrefDepth if needed.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025971 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025972 if (vctxt->aidcs != NULL) {
25973 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
25974 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025975 if (aidc->keyrefDepth == vctxt->depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025976 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025977 * A 'keyrefDepth' of a key/unique IDC matches the current
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025978 * depth, this means that we are leaving the scope of the
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025979 * top-most keyref IDC which refers to this IDC.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025980 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025981 aidc->keyrefDepth = -1;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025982 }
25983 aidc = aidc->next;
25984 } while (aidc != NULL);
25985 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025986 vctxt->depth--;
25987 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000025988 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025989 * VAL TODO: 7 If the element information item is the ·validation root·, it must be
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000025990 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
25991 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025992 return (ret);
25993
25994internal_error:
25995 vctxt->err = -1;
25996 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000025997}
25998
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025999/*
26000* 3.4.4 Complex Type Definition Validation Rules
26001* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26002*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000026003static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026004xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000026005{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026006 xmlSchemaNodeInfoPtr pielem;
26007 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000026008 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000026009
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026010 if (vctxt->depth <= 0) {
26011 VERROR_INT("xmlSchemaValidateChildElem",
26012 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026013 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026014 }
26015 pielem = vctxt->elemInfos[vctxt->depth -1];
26016 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26017 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026018 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026019 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026020 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026021 if (INODE_NILLED(pielem)) {
26022 /*
26023 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
26024 */
26025 ACTIVATE_PARENT_ELEM;
26026 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26027 VERROR(ret, NULL,
26028 "Neither character nor element content is allowed, "
26029 "because the element was 'nilled'");
26030 ACTIVATE_ELEM;
26031 goto unexpected_elem;
26032 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026033
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026034 ptype = pielem->typeDef;
26035
26036 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26037 /*
26038 * Workaround for "anyType": we have currently no content model
26039 * assigned for "anyType", so handle it explicitely.
26040 * "anyType" has an unbounded, lax "any" wildcard.
26041 */
26042 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26043 vctxt->inode->localName,
26044 vctxt->inode->nsName);
26045
26046 if (vctxt->inode->decl == NULL) {
26047 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026048 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026049 * Process "xsi:type".
26050 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026051 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026052 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26053 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26054 if (iattr != NULL) {
26055 ret = xmlSchemaProcessXSIType(vctxt, iattr,
26056 &(vctxt->inode->typeDef), NULL);
26057 if (ret != 0) {
26058 if (ret == -1) {
26059 VERROR_INT("xmlSchemaValidateChildElem",
26060 "calling xmlSchemaProcessXSIType() to "
26061 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000026062 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000026063 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026064 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000026065 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026066 } else {
26067 /*
26068 * Fallback to "anyType".
26069 *
26070 * SPEC (cvc-assess-elt)
26071 * "If the item cannot be ·strictly assessed·, [...]
26072 * an element information item's schema validity may be laxly
26073 * assessed if its ·context-determined declaration· is not
26074 * skip by ·validating· with respect to the ·ur-type
26075 * definition· as per Element Locally Valid (Type) (§3.3.4)."
26076 */
26077 vctxt->inode->typeDef =
26078 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026079 }
26080 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026081 return (0);
26082 }
26083
26084 switch (ptype->contentType) {
26085 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026086 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026087 * SPEC (2.1) "If the {content type} is empty, then the
26088 * element information item has no character or element
26089 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026090 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026091 ACTIVATE_PARENT_ELEM
26092 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26093 VERROR(ret, NULL,
26094 "Element content is not allowed, "
26095 "because the content type is empty");
26096 ACTIVATE_ELEM
26097 goto unexpected_elem;
26098 break;
26099
26100 case XML_SCHEMA_CONTENT_MIXED:
26101 case XML_SCHEMA_CONTENT_ELEMENTS: {
26102 xmlRegExecCtxtPtr regexCtxt;
26103 xmlChar *values[10];
26104 int terminal, nbval = 10, nbneg;
26105
26106 /* VAL TODO: Optimized "anyType" validation.*/
26107
26108 if (ptype->contModel == NULL) {
26109 VERROR_INT("xmlSchemaValidateChildElem",
26110 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026111 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000026112 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026113 /*
26114 * Safety belf for evaluation if the cont. model was already
26115 * examined to be invalid.
26116 */
26117 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26118 VERROR_INT("xmlSchemaValidateChildElem",
26119 "validating elem, but elem content is already invalid");
26120 return (-1);
26121 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000026122
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026123 regexCtxt = pielem->regexCtxt;
26124 if (regexCtxt == NULL) {
26125 /*
26126 * Create the regex context.
26127 */
26128 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26129 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26130 vctxt);
26131 if (regexCtxt == NULL) {
26132 VERROR_INT("xmlSchemaValidateChildElem",
26133 "failed to create a regex context");
26134 return (-1);
26135 }
26136 pielem->regexCtxt = regexCtxt;
26137#ifdef DEBUG_AUTOMATA
26138 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26139 pielem->localName);
26140#endif
26141 }
26142
26143 /*
26144 * SPEC (2.4) "If the {content type} is element-only or mixed,
26145 * then the sequence of the element information item's
26146 * element information item [children], if any, taken in
26147 * order, is ·valid· with respect to the {content type}'s
26148 * particle, as defined in Element Sequence Locally Valid
26149 * (Particle) (§3.9.4)."
26150 */
26151 ret = xmlRegExecPushString2(regexCtxt,
26152 vctxt->inode->localName,
26153 vctxt->inode->nsName,
26154 vctxt->inode);
26155#ifdef DEBUG_AUTOMATA
26156 if (ret < 0)
26157 xmlGenericError(xmlGenericErrorContext,
26158 "AUTOMATON push ERROR for '%s' on '%s'\n",
26159 vctxt->inode->localName, pielem->localName);
26160 else
26161 xmlGenericError(xmlGenericErrorContext,
26162 "AUTOMATON push OK for '%s' on '%s'\n",
26163 vctxt->inode->localName, pielem->localName);
26164#endif
26165 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26166 VERROR_INT("xmlSchemaValidateChildElem",
26167 "calling xmlRegExecPushString2()");
26168 return (-1);
26169 }
26170 if (ret < 0) {
26171 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26172 &values[0], &terminal);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026173 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026174 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26175 "This element is not expected",
26176 nbval, nbneg, values);
26177 ret = vctxt->err;
26178 goto unexpected_elem;
26179 } else
26180 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000026181 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026182 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026183 case XML_SCHEMA_CONTENT_SIMPLE:
26184 case XML_SCHEMA_CONTENT_BASIC:
26185 ACTIVATE_PARENT_ELEM
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026186 if (WXS_IS_COMPLEX(ptype)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026187 /*
26188 * SPEC (cvc-complex-type) (2.2)
26189 * "If the {content type} is a simple type definition, then
26190 * the element information item has no element information
26191 * item [children], ..."
26192 */
26193 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26194 VERROR(ret, NULL, "Element content is not allowed, "
26195 "because the content type is a simple type definition");
26196 } else {
26197 /*
26198 * SPEC (cvc-type) (3.1.2) "The element information item must
26199 * have no element information item [children]."
26200 */
26201 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26202 VERROR(ret, NULL, "Element content is not allowed, "
26203 "because the type definition is simple");
26204 }
26205 ACTIVATE_ELEM
26206 ret = vctxt->err;
26207 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026208 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026209
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026210 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026211 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026212 }
26213 return (ret);
26214unexpected_elem:
26215 /*
26216 * Pop this element and set the skipDepth to skip
26217 * all further content of the parent element.
26218 */
26219 vctxt->skipDepth = vctxt->depth;
26220 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26221 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26222 return (ret);
26223}
26224
26225#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26226#define XML_SCHEMA_PUSH_TEXT_CREATED 2
26227#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26228
26229static int
26230xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26231 int nodeType, const xmlChar *value, int len,
26232 int mode, int *consumed)
26233{
26234 /*
26235 * Unfortunately we have to duplicate the text sometimes.
26236 * OPTIMIZE: Maybe we could skip it, if:
26237 * 1. content type is simple
26238 * 2. whitespace is "collapse"
26239 * 3. it consists of whitespace only
26240 *
26241 * Process character content.
26242 */
26243 if (consumed != NULL)
26244 *consumed = 0;
26245 if (INODE_NILLED(vctxt->inode)) {
26246 /*
26247 * SPEC cvc-elt (3.3.4 - 3.2.1)
26248 * "The element information item must have no character or
26249 * element information item [children]."
26250 */
26251 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26252 "Neither character nor element content is allowed "
26253 "because the element is 'nilled'");
26254 return (vctxt->err);
26255 }
26256 /*
26257 * SPEC (2.1) "If the {content type} is empty, then the
26258 * element information item has no character or element
26259 * information item [children]."
26260 */
26261 if (vctxt->inode->typeDef->contentType ==
26262 XML_SCHEMA_CONTENT_EMPTY) {
26263 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26264 "Character content is not allowed, "
26265 "because the content type is empty");
26266 return (vctxt->err);
26267 }
26268
26269 if (vctxt->inode->typeDef->contentType ==
26270 XML_SCHEMA_CONTENT_ELEMENTS) {
26271 if ((nodeType != XML_TEXT_NODE) ||
26272 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26273 /*
26274 * SPEC cvc-complex-type (2.3)
26275 * "If the {content type} is element-only, then the
26276 * element information item has no character information
26277 * item [children] other than those whose [character
26278 * code] is defined as a white space in [XML 1.0 (Second
26279 * Edition)]."
26280 */
26281 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26282 "Character content other than whitespace is not allowed "
26283 "because the content type is 'element-only'");
26284 return (vctxt->err);
26285 }
26286 return (0);
26287 }
26288
26289 if ((value == NULL) || (value[0] == 0))
26290 return (0);
26291 /*
26292 * Save the value.
26293 * NOTE that even if the content type is *mixed*, we need the
26294 * *initial value* for default/fixed value constraints.
26295 */
26296 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26297 ((vctxt->inode->decl == NULL) ||
26298 (vctxt->inode->decl->value == NULL)))
26299 return (0);
26300
26301 if (vctxt->inode->value == NULL) {
26302 /*
26303 * Set the value.
26304 */
26305 switch (mode) {
26306 case XML_SCHEMA_PUSH_TEXT_PERSIST:
26307 /*
26308 * When working on a tree.
26309 */
26310 vctxt->inode->value = value;
26311 break;
26312 case XML_SCHEMA_PUSH_TEXT_CREATED:
26313 /*
26314 * When working with the reader.
26315 * The value will be freed by the element info.
26316 */
26317 vctxt->inode->value = value;
26318 if (consumed != NULL)
26319 *consumed = 1;
26320 vctxt->inode->flags |=
26321 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26322 break;
26323 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26324 /*
26325 * When working with SAX.
26326 * The value will be freed by the element info.
26327 */
26328 if (len != -1)
26329 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26330 else
26331 vctxt->inode->value = BAD_CAST xmlStrdup(value);
26332 vctxt->inode->flags |=
26333 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26334 break;
26335 default:
26336 break;
26337 }
26338 } else {
26339 /*
26340 * Concat the value.
26341 */
26342 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000026343 vctxt->inode->value = BAD_CAST xmlStrncat(
26344 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026345 } else {
26346 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026347 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026348 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26349 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026350 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026351
26352 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000026353}
26354
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026355static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026356xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000026357{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026358 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000026359
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026360 if ((vctxt->skipDepth != -1) &&
26361 (vctxt->depth >= vctxt->skipDepth)) {
26362 VERROR_INT("xmlSchemaValidateElem",
26363 "in skip-state");
26364 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026365 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026366 if (vctxt->xsiAssemble) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026367 /*
Kasimier T. Buchcik215406f2005-12-07 12:14:09 +000026368 * We will stop validation if there was an error during
26369 * dynamic schema construction.
26370 * Note that we simply set @skipDepth to 0, this could
26371 * mean that a streaming document via SAX would be
26372 * still read to the end but it won't be validated any more.
26373 * TODO: If we are sure how to stop the validation at once
26374 * for all input scenarios, then this should be changed to
26375 * instantly stop the validation.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026376 */
Kasimier T. Buchcik215406f2005-12-07 12:14:09 +000026377 ret = xmlSchemaAssembleByXSI(vctxt);
26378 if (ret != 0) {
26379 if (ret == -1)
26380 goto internal_error;
26381 vctxt->skipDepth = 0;
26382 return(ret);
26383 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026384 }
26385 if (vctxt->depth > 0) {
26386 /*
26387 * Validate this element against the content model
26388 * of the parent.
26389 */
26390 ret = xmlSchemaValidateChildElem(vctxt);
26391 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026392 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026393 VERROR_INT("xmlSchemaValidateElem",
26394 "calling xmlSchemaStreamValidateChildElement()");
26395 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026396 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026397 goto exit;
26398 }
26399 if (vctxt->depth == vctxt->skipDepth)
26400 goto exit;
26401 if ((vctxt->inode->decl == NULL) &&
26402 (vctxt->inode->typeDef == NULL)) {
26403 VERROR_INT("xmlSchemaValidateElem",
26404 "the child element was valid but neither the "
26405 "declaration nor the type was set");
26406 goto internal_error;
26407 }
26408 } else {
26409 /*
26410 * Get the declaration of the validation root.
26411 */
26412 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26413 vctxt->inode->localName,
26414 vctxt->inode->nsName);
26415 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026416 ret = XML_SCHEMAV_CVC_ELT_1;
26417 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026418 "No matching global declaration available "
26419 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026420 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026421 }
26422 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026423
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026424 if (vctxt->inode->decl == NULL)
26425 goto type_validation;
26426
26427 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26428 int skip;
26429 /*
26430 * Wildcards.
26431 */
26432 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26433 if (ret != 0) {
26434 if (ret < 0) {
26435 VERROR_INT("xmlSchemaValidateElem",
26436 "calling xmlSchemaValidateElemWildcard()");
26437 goto internal_error;
26438 }
26439 goto exit;
26440 }
26441 if (skip) {
26442 vctxt->skipDepth = vctxt->depth;
26443 goto exit;
26444 }
26445 /*
26446 * The declaration might be set by the wildcard validation,
26447 * when the processContents is "lax" or "strict".
26448 */
26449 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26450 /*
26451 * Clear the "decl" field to not confuse further processing.
26452 */
26453 vctxt->inode->decl = NULL;
26454 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026455 }
Daniel Veillard4255d502002-04-16 15:50:10 +000026456 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026457 /*
26458 * Validate against the declaration.
26459 */
26460 ret = xmlSchemaValidateElemDecl(vctxt);
26461 if (ret != 0) {
26462 if (ret < 0) {
26463 VERROR_INT("xmlSchemaValidateElem",
26464 "calling xmlSchemaValidateElemDecl()");
26465 goto internal_error;
26466 }
26467 goto exit;
26468 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026469 /*
26470 * Validate against the type definition.
26471 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026472type_validation:
26473
26474 if (vctxt->inode->typeDef == NULL) {
26475 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26476 ret = XML_SCHEMAV_CVC_TYPE_1;
26477 VERROR(ret, NULL,
26478 "The type definition is absent");
26479 goto exit;
26480 }
26481 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26482 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26483 ret = XML_SCHEMAV_CVC_TYPE_2;
26484 VERROR(ret, NULL,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026485 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026486 goto exit;
26487 }
26488 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026489 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026490 * during validation against the declaration. This must be done
26491 * _before_ attribute validation.
26492 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026493 if (vctxt->xpathStates != NULL) {
26494 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000026495 vctxt->inode->appliedXPath = 1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026496 if (ret == -1) {
26497 VERROR_INT("xmlSchemaValidateElem",
26498 "calling xmlSchemaXPathEvaluate()");
26499 goto internal_error;
26500 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026501 }
26502 /*
26503 * Validate attributes.
26504 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026505 if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026506 if ((vctxt->nbAttrInfos != 0) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026507 (vctxt->inode->typeDef->attrUses != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026508
26509 ret = xmlSchemaVAttributesComplex(vctxt);
26510 }
26511 } else if (vctxt->nbAttrInfos != 0) {
26512
26513 ret = xmlSchemaVAttributesSimple(vctxt);
26514 }
26515 /*
26516 * Clear registered attributes.
26517 */
26518 if (vctxt->nbAttrInfos != 0)
26519 xmlSchemaClearAttrInfos(vctxt);
26520 if (ret == -1) {
26521 VERROR_INT("xmlSchemaValidateElem",
26522 "calling attributes validation");
26523 goto internal_error;
26524 }
26525 /*
26526 * Don't return an error if attributes are invalid on purpose.
26527 */
26528 ret = 0;
26529
26530exit:
26531 if (ret != 0)
26532 vctxt->skipDepth = vctxt->depth;
26533 return (ret);
26534internal_error:
26535 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000026536}
26537
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026538#ifdef XML_SCHEMA_READER_ENABLED
26539static int
26540xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000026541{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026542 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
26543 int depth, nodeType, ret = 0, consumed;
26544 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000026545
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026546 vctxt->depth = -1;
26547 ret = xmlTextReaderRead(vctxt->reader);
26548 /*
26549 * Move to the document element.
26550 */
26551 while (ret == 1) {
26552 nodeType = xmlTextReaderNodeType(vctxt->reader);
26553 if (nodeType == XML_ELEMENT_NODE)
26554 goto root_found;
26555 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026556 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026557 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026558
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026559root_found:
26560
26561 do {
26562 depth = xmlTextReaderDepth(vctxt->reader);
26563 nodeType = xmlTextReaderNodeType(vctxt->reader);
26564
26565 if (nodeType == XML_ELEMENT_NODE) {
26566
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026567 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026568 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26569 VERROR_INT("xmlSchemaVReaderWalk",
26570 "calling xmlSchemaValidatorPushElem()");
26571 goto internal_error;
26572 }
26573 ielem = vctxt->inode;
26574 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
26575 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
26576 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
26577 /*
26578 * Is the element empty?
26579 */
26580 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
26581 if (ret == -1) {
26582 VERROR_INT("xmlSchemaVReaderWalk",
26583 "calling xmlTextReaderIsEmptyElement()");
26584 goto internal_error;
26585 }
26586 if (ret) {
26587 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26588 }
26589 /*
26590 * Register attributes.
26591 */
26592 vctxt->nbAttrInfos = 0;
26593 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
26594 if (ret == -1) {
26595 VERROR_INT("xmlSchemaVReaderWalk",
26596 "calling xmlTextReaderMoveToFirstAttribute()");
26597 goto internal_error;
26598 }
26599 if (ret == 1) {
26600 do {
26601 /*
26602 * VAL TODO: How do we know that the reader works on a
26603 * node tree, to be able to pass a node here?
26604 */
26605 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
26606 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
26607 xmlTextReaderNamespaceUri(vctxt->reader), 1,
26608 xmlTextReaderValue(vctxt->reader), 1) == -1) {
26609
26610 VERROR_INT("xmlSchemaVReaderWalk",
26611 "calling xmlSchemaValidatorPushAttribute()");
26612 goto internal_error;
26613 }
26614 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
26615 if (ret == -1) {
26616 VERROR_INT("xmlSchemaVReaderWalk",
26617 "calling xmlTextReaderMoveToFirstAttribute()");
26618 goto internal_error;
26619 }
26620 } while (ret == 1);
26621 /*
26622 * Back to element position.
26623 */
26624 ret = xmlTextReaderMoveToElement(vctxt->reader);
26625 if (ret == -1) {
26626 VERROR_INT("xmlSchemaVReaderWalk",
26627 "calling xmlTextReaderMoveToElement()");
26628 goto internal_error;
26629 }
26630 }
26631 /*
26632 * Validate the element.
26633 */
26634 ret= xmlSchemaValidateElem(vctxt);
26635 if (ret != 0) {
26636 if (ret == -1) {
26637 VERROR_INT("xmlSchemaVReaderWalk",
26638 "calling xmlSchemaValidateElem()");
26639 goto internal_error;
26640 }
26641 goto exit;
26642 }
26643 if (vctxt->depth == vctxt->skipDepth) {
26644 int curDepth;
26645 /*
26646 * Skip all content.
26647 */
26648 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
26649 ret = xmlTextReaderRead(vctxt->reader);
26650 curDepth = xmlTextReaderDepth(vctxt->reader);
26651 while ((ret == 1) && (curDepth != depth)) {
26652 ret = xmlTextReaderRead(vctxt->reader);
26653 curDepth = xmlTextReaderDepth(vctxt->reader);
26654 }
26655 if (ret < 0) {
26656 /*
26657 * VAL TODO: A reader error occured; what to do here?
26658 */
26659 ret = 1;
26660 goto exit;
26661 }
26662 }
26663 goto leave_elem;
26664 }
26665 /*
26666 * READER VAL TODO: Is an END_ELEM really never called
26667 * if the elem is empty?
26668 */
26669 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26670 goto leave_elem;
26671 } else if (nodeType == END_ELEM) {
26672 /*
26673 * Process END of element.
26674 */
26675leave_elem:
26676 ret = xmlSchemaValidatorPopElem(vctxt);
26677 if (ret != 0) {
26678 if (ret < 0) {
26679 VERROR_INT("xmlSchemaVReaderWalk",
26680 "calling xmlSchemaValidatorPopElem()");
26681 goto internal_error;
26682 }
26683 goto exit;
26684 }
26685 if (vctxt->depth >= 0)
26686 ielem = vctxt->inode;
26687 else
26688 ielem = NULL;
26689 } else if ((nodeType == XML_TEXT_NODE) ||
26690 (nodeType == XML_CDATA_SECTION_NODE) ||
26691 (nodeType == WHTSP) ||
26692 (nodeType == SIGN_WHTSP)) {
26693 /*
26694 * Process character content.
26695 */
26696 xmlChar *value;
26697
26698 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
26699 nodeType = XML_TEXT_NODE;
26700
26701 value = xmlTextReaderValue(vctxt->reader);
26702 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
26703 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
26704 if (! consumed)
26705 xmlFree(value);
26706 if (ret == -1) {
26707 VERROR_INT("xmlSchemaVReaderWalk",
26708 "calling xmlSchemaVPushText()");
26709 goto internal_error;
26710 }
26711 } else if ((nodeType == XML_ENTITY_NODE) ||
26712 (nodeType == XML_ENTITY_REF_NODE)) {
26713 /*
26714 * VAL TODO: What to do with entities?
26715 */
26716 TODO
26717 }
26718 /*
26719 * Read next node.
26720 */
26721 ret = xmlTextReaderRead(vctxt->reader);
26722 } while (ret == 1);
26723
26724exit:
26725 return (ret);
26726internal_error:
26727 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000026728}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026729#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000026730
26731/************************************************************************
26732 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026733 * SAX validation handlers *
Daniel Veillard4255d502002-04-16 15:50:10 +000026734 * *
26735 ************************************************************************/
26736
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026737/*
26738* Process text content.
26739*/
26740static void
26741xmlSchemaSAXHandleText(void *ctx,
26742 const xmlChar * ch,
26743 int len)
26744{
26745 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26746
26747 if (vctxt->depth < 0)
26748 return;
26749 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26750 return;
26751 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26752 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26753 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
26754 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
26755 VERROR_INT("xmlSchemaSAXHandleCDataSection",
26756 "calling xmlSchemaVPushText()");
26757 vctxt->err = -1;
26758 xmlStopParser(vctxt->parserCtxt);
26759 }
26760}
26761
26762/*
26763* Process CDATA content.
26764*/
26765static void
26766xmlSchemaSAXHandleCDataSection(void *ctx,
26767 const xmlChar * ch,
26768 int len)
26769{
26770 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26771
26772 if (vctxt->depth < 0)
26773 return;
26774 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26775 return;
26776 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26777 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26778 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
26779 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
26780 VERROR_INT("xmlSchemaSAXHandleCDataSection",
26781 "calling xmlSchemaVPushText()");
26782 vctxt->err = -1;
26783 xmlStopParser(vctxt->parserCtxt);
26784 }
26785}
26786
26787static void
26788xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
26789 const xmlChar * name ATTRIBUTE_UNUSED)
26790{
26791 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26792
26793 if (vctxt->depth < 0)
26794 return;
26795 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26796 return;
26797 /* SAX VAL TODO: What to do here? */
26798 TODO
26799}
26800
26801static void
26802xmlSchemaSAXHandleStartElementNs(void *ctx,
26803 const xmlChar * localname,
26804 const xmlChar * prefix ATTRIBUTE_UNUSED,
26805 const xmlChar * URI,
26806 int nb_namespaces,
26807 const xmlChar ** namespaces,
26808 int nb_attributes,
26809 int nb_defaulted ATTRIBUTE_UNUSED,
26810 const xmlChar ** attributes)
26811{
26812 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26813 int ret;
26814 xmlSchemaNodeInfoPtr ielem;
26815 int i, j;
26816
26817 /*
26818 * SAX VAL TODO: What to do with nb_defaulted?
26819 */
26820 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026821 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026822 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026823 vctxt->depth++;
26824 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026825 return;
26826 /*
26827 * Push the element.
26828 */
26829 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26830 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26831 "calling xmlSchemaValidatorPushElem()");
26832 goto internal_error;
26833 }
26834 ielem = vctxt->inode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026835 /*
26836 * TODO: Is this OK?
26837 */
26838 ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026839 ielem->localName = localname;
26840 ielem->nsName = URI;
26841 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26842 /*
26843 * Register namespaces on the elem info.
26844 */
26845 if (nb_namespaces != 0) {
26846 /*
26847 * Although the parser builds its own namespace list,
26848 * we have no access to it, so we'll use an own one.
26849 */
26850 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
26851 /*
26852 * Store prefix and namespace name.
26853 */
26854 if (ielem->nsBindings == NULL) {
26855 ielem->nsBindings =
26856 (const xmlChar **) xmlMalloc(10 *
26857 sizeof(const xmlChar *));
26858 if (ielem->nsBindings == NULL) {
26859 xmlSchemaVErrMemory(vctxt,
26860 "allocating namespace bindings for SAX validation",
26861 NULL);
26862 goto internal_error;
26863 }
26864 ielem->nbNsBindings = 0;
26865 ielem->sizeNsBindings = 5;
26866 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
26867 ielem->sizeNsBindings *= 2;
26868 ielem->nsBindings =
26869 (const xmlChar **) xmlRealloc(
26870 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026871 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026872 if (ielem->nsBindings == NULL) {
26873 xmlSchemaVErrMemory(vctxt,
26874 "re-allocating namespace bindings for SAX validation",
26875 NULL);
26876 goto internal_error;
26877 }
26878 }
26879
26880 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
26881 if (namespaces[j+1][0] == 0) {
26882 /*
26883 * Handle xmlns="".
26884 */
26885 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
26886 } else
26887 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
26888 namespaces[j+1];
26889 ielem->nbNsBindings++;
26890 }
26891 }
26892 /*
26893 * Register attributes.
26894 * SAX VAL TODO: We are not adding namespace declaration
26895 * attributes yet.
26896 */
26897 if (nb_attributes != 0) {
26898 xmlChar *value;
26899
26900 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
26901 /*
26902 * Duplicate the value.
26903 */
26904 value = xmlStrndup(attributes[j+3],
26905 attributes[j+4] - attributes[j+3]);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026906 /*
26907 * TODO: Set the node line.
26908 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026909 ret = xmlSchemaValidatorPushAttribute(vctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026910 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026911 value, 1);
26912 if (ret == -1) {
26913 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26914 "calling xmlSchemaValidatorPushAttribute()");
26915 goto internal_error;
26916 }
26917 }
26918 }
26919 /*
26920 * Validate the element.
26921 */
26922 ret = xmlSchemaValidateElem(vctxt);
26923 if (ret != 0) {
26924 if (ret == -1) {
26925 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26926 "calling xmlSchemaValidateElem()");
26927 goto internal_error;
26928 }
26929 goto exit;
26930 }
26931
26932exit:
26933 return;
26934internal_error:
26935 vctxt->err = -1;
26936 xmlStopParser(vctxt->parserCtxt);
26937 return;
26938}
26939
26940static void
26941xmlSchemaSAXHandleEndElementNs(void *ctx,
26942 const xmlChar * localname ATTRIBUTE_UNUSED,
26943 const xmlChar * prefix ATTRIBUTE_UNUSED,
26944 const xmlChar * URI ATTRIBUTE_UNUSED)
26945{
26946 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26947 int res;
26948
26949 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026950 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026951 */
26952 if (vctxt->skipDepth != -1) {
26953 if (vctxt->depth > vctxt->skipDepth) {
26954 vctxt->depth--;
26955 return;
26956 } else
26957 vctxt->skipDepth = -1;
26958 }
26959 /*
26960 * SAX VAL TODO: Just a temporary check.
26961 */
26962 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
26963 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
26964 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
26965 "elem pop mismatch");
26966 }
26967 res = xmlSchemaValidatorPopElem(vctxt);
26968 if (res != 0) {
26969 if (res < 0) {
26970 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
26971 "calling xmlSchemaValidatorPopElem()");
26972 goto internal_error;
26973 }
26974 goto exit;
26975 }
26976exit:
26977 return;
26978internal_error:
26979 vctxt->err = -1;
26980 xmlStopParser(vctxt->parserCtxt);
26981 return;
26982}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026983
Daniel Veillard4255d502002-04-16 15:50:10 +000026984/************************************************************************
26985 * *
26986 * Validation interfaces *
26987 * *
26988 ************************************************************************/
26989
26990/**
26991 * xmlSchemaNewValidCtxt:
26992 * @schema: a precompiled XML Schemas
26993 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026994 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000026995 *
26996 * Returns the validation context or NULL in case of error
26997 */
26998xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000026999xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27000{
Daniel Veillard4255d502002-04-16 15:50:10 +000027001 xmlSchemaValidCtxtPtr ret;
27002
27003 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27004 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027005 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000027006 return (NULL);
27007 }
27008 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027009 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027010 ret->dict = xmlDictCreate();
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000027011 ret->nodeQNames = xmlSchemaItemListCreate();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027012 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000027013 return (ret);
27014}
27015
27016/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027017 * xmlSchemaClearValidCtxt:
27018 * @ctxt: the schema validation context
27019 *
27020 * Free the resources associated to the schema validation context;
27021 * leaves some fields alive intended for reuse of the context.
27022 */
27023static void
27024xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27025{
27026 if (vctxt == NULL)
27027 return;
27028
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027029 /*
27030 * TODO: Should we clear the flags?
27031 * Might be problematic if one reuses the context
27032 * and assumes that the options remain the same.
27033 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000027034 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027035 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027036 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000027037#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027038 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000027039#endif
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027040 vctxt->hasKeyrefs = 0;
27041
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027042 if (vctxt->value != NULL) {
27043 xmlSchemaFreeValue(vctxt->value);
27044 vctxt->value = NULL;
27045 }
27046 /*
27047 * Augmented IDC information.
27048 */
27049 if (vctxt->aidcs != NULL) {
27050 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27051 do {
27052 next = cur->next;
27053 xmlFree(cur);
27054 cur = next;
27055 } while (cur != NULL);
27056 vctxt->aidcs = NULL;
27057 }
27058 if (vctxt->idcNodes != NULL) {
27059 int i;
27060 xmlSchemaPSVIIDCNodePtr item;
27061
27062 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027063 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027064 xmlFree(item->keys);
27065 xmlFree(item);
27066 }
27067 xmlFree(vctxt->idcNodes);
27068 vctxt->idcNodes = NULL;
27069 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027070 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027071 * Note that we won't delete the XPath state pool here.
27072 */
27073 if (vctxt->xpathStates != NULL) {
27074 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27075 vctxt->xpathStates = NULL;
27076 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027077 /*
27078 * Attribute info.
27079 */
27080 if (vctxt->nbAttrInfos != 0) {
27081 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027082 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027083 /*
27084 * Element info.
27085 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027086 if (vctxt->elemInfos != NULL) {
27087 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027088 xmlSchemaNodeInfoPtr ei;
27089
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027090 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027091 ei = vctxt->elemInfos[i];
27092 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027093 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027094 xmlSchemaClearElemInfo(ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027095 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027096 }
27097 xmlSchemaItemListClear(vctxt->nodeQNames);
27098 /* Recreate the dict. */
27099 xmlDictFree(vctxt->dict);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027100 /*
27101 * TODO: Is is save to recreate it? Do we have a scenario
27102 * where the user provides the dict?
27103 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027104 vctxt->dict = xmlDictCreate();
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027105}
27106
27107/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027108 * xmlSchemaFreeValidCtxt:
27109 * @ctxt: the schema validation context
27110 *
27111 * Free the resources associated to the schema validation context
27112 */
27113void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027114xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27115{
Daniel Veillard4255d502002-04-16 15:50:10 +000027116 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027117 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000027118 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027119 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027120 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027121 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027122 if (ctxt->idcNodes != NULL) {
27123 int i;
27124 xmlSchemaPSVIIDCNodePtr item;
27125
27126 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027127 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027128 xmlFree(item->keys);
27129 xmlFree(item);
27130 }
27131 xmlFree(ctxt->idcNodes);
27132 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027133 if (ctxt->idcKeys != NULL) {
27134 int i;
27135 for (i = 0; i < ctxt->nbIdcKeys; i++)
27136 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27137 xmlFree(ctxt->idcKeys);
27138 }
27139
27140 if (ctxt->xpathStates != NULL)
27141 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27142 if (ctxt->xpathStatePool != NULL)
27143 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27144
27145 /*
27146 * Augmented IDC information.
27147 */
27148 if (ctxt->aidcs != NULL) {
27149 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27150 do {
27151 next = cur->next;
27152 xmlFree(cur);
27153 cur = next;
27154 } while (cur != NULL);
27155 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027156 if (ctxt->attrInfos != NULL) {
27157 int i;
27158 xmlSchemaAttrInfoPtr attr;
27159
27160 /* Just a paranoid call to the cleanup. */
27161 if (ctxt->nbAttrInfos != 0)
27162 xmlSchemaClearAttrInfos(ctxt);
27163 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27164 attr = ctxt->attrInfos[i];
27165 xmlFree(attr);
27166 }
27167 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000027168 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027169 if (ctxt->elemInfos != NULL) {
27170 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027171 xmlSchemaNodeInfoPtr ei;
27172
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027173 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027174 ei = ctxt->elemInfos[i];
27175 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027176 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027177 xmlSchemaClearElemInfo(ei);
27178 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027179 }
27180 xmlFree(ctxt->elemInfos);
27181 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027182 if (ctxt->nodeQNames != NULL)
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000027183 xmlSchemaItemListFree(ctxt->nodeQNames);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027184 if (ctxt->dict != NULL)
27185 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000027186 xmlFree(ctxt);
27187}
27188
27189/**
Daniel Veillardf10ae122005-07-10 19:03:16 +000027190 * xmlSchemaIsValid:
27191 * @ctxt: the schema validation context
27192 *
27193 * Check if any error was detected during validation.
27194 *
27195 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27196 * of internal error.
27197 */
27198int
27199xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27200{
27201 if (ctxt == NULL)
27202 return(-1);
27203 return(ctxt->err == 0);
27204}
27205
27206/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027207 * xmlSchemaSetValidErrors:
27208 * @ctxt: a schema validation context
27209 * @err: the error function
27210 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000027211 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000027212 *
William M. Brack2f2a6632004-08-20 23:09:47 +000027213 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000027214 */
27215void
27216xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027217 xmlSchemaValidityErrorFunc err,
27218 xmlSchemaValidityWarningFunc warn, void *ctx)
27219{
Daniel Veillard4255d502002-04-16 15:50:10 +000027220 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027221 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000027222 ctxt->error = err;
27223 ctxt->warning = warn;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027224 ctxt->errCtxt = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027225 if (ctxt->pctxt != NULL)
27226 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000027227}
27228
27229/**
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027230 * xmlSchemaSetValidStructuredErrors:
27231 * @ctxt: a schema validation context
27232 * @serror: the structured error function
27233 * @ctx: the functions context
27234 *
27235 * Set the structured error callback
27236 */
27237void
27238xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027239 xmlStructuredErrorFunc serror, void *ctx)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027240{
27241 if (ctxt == NULL)
27242 return;
27243 ctxt->serror = serror;
27244 ctxt->error = NULL;
27245 ctxt->warning = NULL;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027246 ctxt->errCtxt = ctx;
27247 if (ctxt->pctxt != NULL)
27248 xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027249}
27250
27251/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000027252 * xmlSchemaGetValidErrors:
27253 * @ctxt: a XML-Schema validation context
27254 * @err: the error function result
27255 * @warn: the warning function result
27256 * @ctx: the functions context result
27257 *
27258 * Get the error and warning callback informations
27259 *
27260 * Returns -1 in case of error and 0 otherwise
27261 */
27262int
27263xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027264 xmlSchemaValidityErrorFunc * err,
27265 xmlSchemaValidityWarningFunc * warn, void **ctx)
Daniel Veillard259f0df2004-08-18 09:13:18 +000027266{
27267 if (ctxt == NULL)
27268 return (-1);
27269 if (err != NULL)
27270 *err = ctxt->error;
27271 if (warn != NULL)
27272 *warn = ctxt->warning;
27273 if (ctx != NULL)
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027274 *ctx = ctxt->errCtxt;
Daniel Veillard259f0df2004-08-18 09:13:18 +000027275 return (0);
27276}
27277
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027278
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027279/**
Daniel Veillard6927b102004-10-27 17:29:04 +000027280 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027281 * @ctxt: a schema validation context
27282 * @options: a combination of xmlSchemaValidOption
27283 *
27284 * Sets the options to be used during the validation.
27285 *
27286 * Returns 0 in case of success, -1 in case of an
27287 * API error.
27288 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027289int
27290xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27291 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027292
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027293{
27294 int i;
27295
27296 if (ctxt == NULL)
27297 return (-1);
27298 /*
27299 * WARNING: Change the start value if adding to the
27300 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027301 * TODO: Is there an other, more easy to maintain,
27302 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027303 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027304 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027305 if (options & 1<<i)
27306 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027307 }
27308 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027309 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027310}
27311
27312/**
Daniel Veillard6927b102004-10-27 17:29:04 +000027313 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027314 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027315 *
William M. Brack21e4ef22005-01-02 09:53:13 +000027316 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027317 *
William M. Brack21e4ef22005-01-02 09:53:13 +000027318 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027319 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027320int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027321xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027322
27323{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027324 if (ctxt == NULL)
27325 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027326 else
27327 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027328}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027329
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027330static int
27331xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27332{
27333 xmlAttrPtr attr;
27334 int ret = 0;
27335 xmlSchemaNodeInfoPtr ielem = NULL;
27336 xmlNodePtr node, valRoot;
27337 const xmlChar *nsName;
27338
27339 /* DOC VAL TODO: Move this to the start function. */
27340 valRoot = xmlDocGetRootElement(vctxt->doc);
27341 if (valRoot == NULL) {
27342 /* VAL TODO: Error code? */
27343 VERROR(1, NULL, "The document has no document element");
27344 return (1);
27345 }
27346 vctxt->depth = -1;
27347 vctxt->validationRoot = valRoot;
27348 node = valRoot;
27349 while (node != NULL) {
27350 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27351 goto next_sibling;
27352 if (node->type == XML_ELEMENT_NODE) {
27353
27354 /*
27355 * Init the node-info.
27356 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000027357 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027358 if (xmlSchemaValidatorPushElem(vctxt) == -1)
27359 goto internal_error;
27360 ielem = vctxt->inode;
27361 ielem->node = node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027362 ielem->nodeLine = node->line;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027363 ielem->localName = node->name;
27364 if (node->ns != NULL)
27365 ielem->nsName = node->ns->href;
27366 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27367 /*
27368 * Register attributes.
27369 * DOC VAL TODO: We do not register namespace declaration
27370 * attributes yet.
27371 */
27372 vctxt->nbAttrInfos = 0;
27373 if (node->properties != NULL) {
27374 attr = node->properties;
27375 do {
27376 if (attr->ns != NULL)
27377 nsName = attr->ns->href;
27378 else
27379 nsName = NULL;
27380 ret = xmlSchemaValidatorPushAttribute(vctxt,
27381 (xmlNodePtr) attr,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027382 /*
27383 * Note that we give it the line number of the
27384 * parent element.
27385 */
27386 ielem->nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027387 attr->name, nsName, 0,
27388 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27389 if (ret == -1) {
27390 VERROR_INT("xmlSchemaDocWalk",
27391 "calling xmlSchemaValidatorPushAttribute()");
27392 goto internal_error;
27393 }
27394 attr = attr->next;
27395 } while (attr);
27396 }
27397 /*
27398 * Validate the element.
27399 */
27400 ret = xmlSchemaValidateElem(vctxt);
27401 if (ret != 0) {
27402 if (ret == -1) {
27403 VERROR_INT("xmlSchemaDocWalk",
27404 "calling xmlSchemaValidateElem()");
27405 goto internal_error;
27406 }
27407 /*
27408 * Don't stop validation; just skip the content
27409 * of this element.
27410 */
27411 goto leave_node;
27412 }
27413 if ((vctxt->skipDepth != -1) &&
27414 (vctxt->depth >= vctxt->skipDepth))
27415 goto leave_node;
27416 } else if ((node->type == XML_TEXT_NODE) ||
27417 (node->type == XML_CDATA_SECTION_NODE)) {
27418 /*
27419 * Process character content.
27420 */
27421 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27422 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27423 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27424 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27425 if (ret < 0) {
27426 VERROR_INT("xmlSchemaVDocWalk",
27427 "calling xmlSchemaVPushText()");
27428 goto internal_error;
27429 }
27430 /*
27431 * DOC VAL TODO: Should we skip further validation of the
27432 * element content here?
27433 */
27434 } else if ((node->type == XML_ENTITY_NODE) ||
27435 (node->type == XML_ENTITY_REF_NODE)) {
27436 /*
27437 * DOC VAL TODO: What to do with entities?
27438 */
27439 TODO
27440 } else {
27441 goto leave_node;
27442 /*
27443 * DOC VAL TODO: XInclude nodes, etc.
27444 */
27445 }
27446 /*
27447 * Walk the doc.
27448 */
27449 if (node->children != NULL) {
27450 node = node->children;
27451 continue;
27452 }
27453leave_node:
27454 if (node->type == XML_ELEMENT_NODE) {
27455 /*
27456 * Leaving the scope of an element.
27457 */
27458 if (node != vctxt->inode->node) {
27459 VERROR_INT("xmlSchemaVDocWalk",
27460 "element position mismatch");
27461 goto internal_error;
27462 }
27463 ret = xmlSchemaValidatorPopElem(vctxt);
27464 if (ret != 0) {
27465 if (ret < 0) {
27466 VERROR_INT("xmlSchemaVDocWalk",
27467 "calling xmlSchemaValidatorPopElem()");
27468 goto internal_error;
27469 }
27470 }
27471 if (node == valRoot)
27472 goto exit;
27473 }
27474next_sibling:
27475 if (node->next != NULL)
27476 node = node->next;
27477 else {
27478 node = node->parent;
27479 goto leave_node;
27480 }
27481 }
27482
27483exit:
27484 return (ret);
27485internal_error:
27486 return (-1);
27487}
27488
27489static int
Daniel Veillardf10ae122005-07-10 19:03:16 +000027490xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027491 /*
27492 * Some initialization.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027493 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027494 vctxt->err = 0;
27495 vctxt->nberrors = 0;
27496 vctxt->depth = -1;
27497 vctxt->skipDepth = -1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027498 vctxt->xsiAssemble = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027499 vctxt->hasKeyrefs = 0;
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000027500#ifdef ENABLE_IDC_NODE_TABLES_TEST
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027501 vctxt->createIDCNodeTables = 1;
27502#else
27503 vctxt->createIDCNodeTables = 0;
27504#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027505 /*
27506 * Create a schema + parser if necessary.
27507 */
27508 if (vctxt->schema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027509 xmlSchemaParserCtxtPtr pctxt;
27510
27511 vctxt->xsiAssemble = 1;
27512 /*
27513 * If not schema was given then we will create a schema
27514 * dynamically using XSI schema locations.
27515 *
27516 * Create the schema parser context.
27517 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027518 if ((vctxt->pctxt == NULL) &&
27519 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
27520 return (-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027521 pctxt = vctxt->pctxt;
27522 pctxt->xsiAssemble = 1;
27523 /*
27524 * Create the schema.
27525 */
27526 vctxt->schema = xmlSchemaNewSchema(pctxt);
27527 if (vctxt->schema == NULL)
27528 return (-1);
27529 /*
27530 * Create the schema construction context.
27531 */
27532 pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
27533 if (pctxt->constructor == NULL)
27534 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000027535 pctxt->constructor->mainSchema = vctxt->schema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027536 /*
27537 * Take ownership of the constructor to be able to free it.
27538 */
27539 pctxt->ownsConstructor = 1;
27540 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027541 /*
27542 * Augment the IDC definitions.
27543 */
27544 if (vctxt->schema->idcDef != NULL) {
27545 xmlHashScan(vctxt->schema->idcDef,
27546 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
27547 }
Daniel Veillardf10ae122005-07-10 19:03:16 +000027548 return(0);
27549}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027550
Daniel Veillardf10ae122005-07-10 19:03:16 +000027551static void
27552xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027553 if (vctxt->xsiAssemble) {
27554 if (vctxt->schema != NULL) {
27555 xmlSchemaFree(vctxt->schema);
27556 vctxt->schema = NULL;
27557 }
27558 }
27559 xmlSchemaClearValidCtxt(vctxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +000027560}
27561
27562static int
27563xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
27564{
27565 int ret = 0;
27566
27567 if (xmlSchemaPreRun(vctxt) < 0)
27568 return(-1);
27569
27570 if (vctxt->doc != NULL) {
27571 /*
27572 * Tree validation.
27573 */
27574 ret = xmlSchemaVDocWalk(vctxt);
27575#ifdef LIBXML_READER_ENABLED
27576 } else if (vctxt->reader != NULL) {
27577 /*
27578 * XML Reader validation.
27579 */
27580#ifdef XML_SCHEMA_READER_ENABLED
27581 ret = xmlSchemaVReaderWalk(vctxt);
27582#endif
27583#endif
27584 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
27585 /*
27586 * SAX validation.
27587 */
27588 ret = xmlParseDocument(vctxt->parserCtxt);
27589 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027590 VERROR_INT("xmlSchemaVStart",
Daniel Veillardf10ae122005-07-10 19:03:16 +000027591 "no instance to validate");
27592 ret = -1;
27593 }
27594
27595 xmlSchemaPostRun(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027596 if (ret == 0)
27597 ret = vctxt->err;
27598 return (ret);
27599}
27600
27601/**
27602 * xmlSchemaValidateOneElement:
27603 * @ctxt: a schema validation context
27604 * @elem: an element node
27605 *
27606 * Validate a branch of a tree, starting with the given @elem.
27607 *
27608 * Returns 0 if the element and its subtree is valid, a positive error
27609 * code number otherwise and -1 in case of an internal or API error.
27610 */
27611int
27612xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
27613{
27614 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
27615 return (-1);
27616
27617 if (ctxt->schema == NULL)
27618 return (-1);
27619
27620 ctxt->doc = elem->doc;
27621 ctxt->node = elem;
27622 ctxt->validationRoot = elem;
27623 return(xmlSchemaVStart(ctxt));
27624}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027625
Daniel Veillard259f0df2004-08-18 09:13:18 +000027626/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027627 * xmlSchemaValidateDoc:
27628 * @ctxt: a schema validation context
27629 * @doc: a parsed document tree
27630 *
27631 * Validate a document tree in memory.
27632 *
27633 * Returns 0 if the document is schemas valid, a positive error code
27634 * number otherwise and -1 in case of internal or API error.
27635 */
27636int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027637xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
27638{
Daniel Veillard4255d502002-04-16 15:50:10 +000027639 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027640 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000027641
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027642 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027643 ctxt->node = xmlDocGetRootElement(doc);
27644 if (ctxt->node == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027645 xmlSchemaCustomErr(ACTXT_CAST ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027646 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
27647 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027648 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027649 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027650 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027651 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027652 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000027653}
27654
Daniel Veillardcdc82732005-07-08 15:04:06 +000027655
27656/************************************************************************
27657 * *
27658 * Function and data for SAX streaming API *
27659 * *
27660 ************************************************************************/
27661typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
27662typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
27663
27664struct _xmlSchemaSplitSAXData {
27665 xmlSAXHandlerPtr user_sax;
27666 void *user_data;
27667 xmlSchemaValidCtxtPtr ctxt;
27668 xmlSAXHandlerPtr schemas_sax;
27669};
27670
Daniel Veillard971771e2005-07-09 17:32:57 +000027671#define XML_SAX_PLUG_MAGIC 0xdc43ba21
27672
27673struct _xmlSchemaSAXPlug {
27674 unsigned int magic;
27675
27676 /* the original callbacks informations */
27677 xmlSAXHandlerPtr *user_sax_ptr;
27678 xmlSAXHandlerPtr user_sax;
27679 void **user_data_ptr;
27680 void *user_data;
27681
27682 /* the block plugged back and validation informations */
27683 xmlSAXHandler schemas_sax;
27684 xmlSchemaValidCtxtPtr ctxt;
27685};
27686
Daniel Veillardcdc82732005-07-08 15:04:06 +000027687/* All those functions just bounces to the user provided SAX handlers */
27688static void
27689internalSubsetSplit(void *ctx, const xmlChar *name,
27690 const xmlChar *ExternalID, const xmlChar *SystemID)
27691{
Daniel Veillard971771e2005-07-09 17:32:57 +000027692 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027693 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27694 (ctxt->user_sax->internalSubset != NULL))
27695 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
27696 SystemID);
27697}
27698
27699static int
27700isStandaloneSplit(void *ctx)
27701{
Daniel Veillard971771e2005-07-09 17:32:57 +000027702 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027703 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27704 (ctxt->user_sax->isStandalone != NULL))
27705 return(ctxt->user_sax->isStandalone(ctxt->user_data));
27706 return(0);
27707}
27708
27709static int
27710hasInternalSubsetSplit(void *ctx)
27711{
Daniel Veillard971771e2005-07-09 17:32:57 +000027712 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027713 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27714 (ctxt->user_sax->hasInternalSubset != NULL))
27715 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
27716 return(0);
27717}
27718
27719static int
27720hasExternalSubsetSplit(void *ctx)
27721{
Daniel Veillard971771e2005-07-09 17:32:57 +000027722 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027723 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27724 (ctxt->user_sax->hasExternalSubset != NULL))
27725 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
27726 return(0);
27727}
27728
27729static void
27730externalSubsetSplit(void *ctx, const xmlChar *name,
27731 const xmlChar *ExternalID, const xmlChar *SystemID)
27732{
Daniel Veillard971771e2005-07-09 17:32:57 +000027733 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027734 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27735 (ctxt->user_sax->internalSubset != NULL))
27736 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
27737 SystemID);
27738}
27739
27740static xmlParserInputPtr
27741resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
27742{
Daniel Veillard971771e2005-07-09 17:32:57 +000027743 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027744 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27745 (ctxt->user_sax->resolveEntity != NULL))
27746 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
27747 systemId));
27748 return(NULL);
27749}
27750
27751static xmlEntityPtr
27752getEntitySplit(void *ctx, const xmlChar *name)
27753{
Daniel Veillard971771e2005-07-09 17:32:57 +000027754 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027755 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27756 (ctxt->user_sax->getEntity != NULL))
27757 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
27758 return(NULL);
27759}
27760
27761static xmlEntityPtr
27762getParameterEntitySplit(void *ctx, const xmlChar *name)
27763{
Daniel Veillard971771e2005-07-09 17:32:57 +000027764 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027765 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27766 (ctxt->user_sax->getParameterEntity != NULL))
27767 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
27768 return(NULL);
27769}
27770
27771
27772static void
27773entityDeclSplit(void *ctx, const xmlChar *name, int type,
27774 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
27775{
Daniel Veillard971771e2005-07-09 17:32:57 +000027776 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027777 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27778 (ctxt->user_sax->entityDecl != NULL))
27779 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
27780 systemId, content);
27781}
27782
27783static void
27784attributeDeclSplit(void *ctx, const xmlChar * elem,
27785 const xmlChar * name, int type, int def,
27786 const xmlChar * defaultValue, xmlEnumerationPtr tree)
27787{
Daniel Veillard971771e2005-07-09 17:32:57 +000027788 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027789 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27790 (ctxt->user_sax->attributeDecl != NULL)) {
27791 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
27792 def, defaultValue, tree);
27793 } else {
27794 xmlFreeEnumeration(tree);
27795 }
27796}
27797
27798static void
27799elementDeclSplit(void *ctx, const xmlChar *name, int type,
27800 xmlElementContentPtr content)
27801{
Daniel Veillard971771e2005-07-09 17:32:57 +000027802 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027803 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27804 (ctxt->user_sax->elementDecl != NULL))
27805 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
27806}
27807
27808static void
27809notationDeclSplit(void *ctx, const xmlChar *name,
27810 const xmlChar *publicId, const xmlChar *systemId)
27811{
Daniel Veillard971771e2005-07-09 17:32:57 +000027812 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027813 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27814 (ctxt->user_sax->notationDecl != NULL))
27815 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
27816 systemId);
27817}
27818
27819static void
27820unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
27821 const xmlChar *publicId, const xmlChar *systemId,
27822 const xmlChar *notationName)
27823{
Daniel Veillard971771e2005-07-09 17:32:57 +000027824 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027825 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27826 (ctxt->user_sax->unparsedEntityDecl != NULL))
27827 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
27828 systemId, notationName);
27829}
27830
27831static void
27832setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
27833{
Daniel Veillard971771e2005-07-09 17:32:57 +000027834 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027835 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27836 (ctxt->user_sax->setDocumentLocator != NULL))
27837 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
27838}
27839
27840static void
27841startDocumentSplit(void *ctx)
27842{
Daniel Veillard971771e2005-07-09 17:32:57 +000027843 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027844 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27845 (ctxt->user_sax->startDocument != NULL))
27846 ctxt->user_sax->startDocument(ctxt->user_data);
27847}
27848
27849static void
27850endDocumentSplit(void *ctx)
27851{
Daniel Veillard971771e2005-07-09 17:32:57 +000027852 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027853 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27854 (ctxt->user_sax->endDocument != NULL))
27855 ctxt->user_sax->endDocument(ctxt->user_data);
27856}
27857
27858static void
27859processingInstructionSplit(void *ctx, const xmlChar *target,
27860 const xmlChar *data)
27861{
Daniel Veillard971771e2005-07-09 17:32:57 +000027862 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027863 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27864 (ctxt->user_sax->processingInstruction != NULL))
27865 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
27866}
27867
27868static void
27869commentSplit(void *ctx, const xmlChar *value)
27870{
Daniel Veillard971771e2005-07-09 17:32:57 +000027871 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027872 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27873 (ctxt->user_sax->comment != NULL))
27874 ctxt->user_sax->comment(ctxt->user_data, value);
27875}
27876
27877/*
27878 * Varargs error callbacks to the user application, harder ...
27879 */
27880
Daniel Veillardffa3c742005-07-21 13:24:09 +000027881static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027882warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027883 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027884 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27885 (ctxt->user_sax->warning != NULL)) {
27886 TODO
27887 }
27888}
Daniel Veillardffa3c742005-07-21 13:24:09 +000027889static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027890errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027891 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027892 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27893 (ctxt->user_sax->error != NULL)) {
27894 TODO
27895 }
27896}
Daniel Veillardffa3c742005-07-21 13:24:09 +000027897static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027898fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027899 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027900 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27901 (ctxt->user_sax->fatalError != NULL)) {
27902 TODO
27903 }
27904}
27905
27906/*
27907 * Those are function where both the user handler and the schemas handler
27908 * need to be called.
27909 */
27910static void
27911charactersSplit(void *ctx, const xmlChar *ch, int len)
27912{
Daniel Veillard971771e2005-07-09 17:32:57 +000027913 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027914 if (ctxt == NULL)
27915 return;
27916 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
27917 ctxt->user_sax->characters(ctxt->user_data, ch, len);
27918 if (ctxt->ctxt != NULL)
27919 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
27920}
27921
27922static void
27923ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
27924{
Daniel Veillard971771e2005-07-09 17:32:57 +000027925 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027926 if (ctxt == NULL)
27927 return;
27928 if ((ctxt->user_sax != NULL) &&
27929 (ctxt->user_sax->ignorableWhitespace != NULL))
27930 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
27931 if (ctxt->ctxt != NULL)
27932 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
27933}
27934
27935static void
27936cdataBlockSplit(void *ctx, const xmlChar *value, int len)
27937{
Daniel Veillard971771e2005-07-09 17:32:57 +000027938 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027939 if (ctxt == NULL)
27940 return;
27941 if ((ctxt->user_sax != NULL) &&
27942 (ctxt->user_sax->ignorableWhitespace != NULL))
27943 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, value, len);
27944 if (ctxt->ctxt != NULL)
27945 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
27946}
27947
27948static void
27949referenceSplit(void *ctx, const xmlChar *name)
27950{
Daniel Veillard971771e2005-07-09 17:32:57 +000027951 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027952 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27953 (ctxt->user_sax->reference != NULL))
27954 ctxt->user_sax->reference(ctxt->user_data, name);
27955 if (ctxt->ctxt != NULL)
27956 xmlSchemaSAXHandleReference(ctxt->user_data, name);
27957}
27958
27959static void
27960startElementNsSplit(void *ctx, const xmlChar * localname,
27961 const xmlChar * prefix, const xmlChar * URI,
27962 int nb_namespaces, const xmlChar ** namespaces,
27963 int nb_attributes, int nb_defaulted,
27964 const xmlChar ** attributes) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027965 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027966 if (ctxt == NULL)
27967 return;
27968 if ((ctxt->user_sax != NULL) &&
27969 (ctxt->user_sax->startElementNs != NULL))
27970 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
27971 URI, nb_namespaces, namespaces,
27972 nb_attributes, nb_defaulted,
27973 attributes);
27974 if (ctxt->ctxt != NULL)
27975 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
27976 URI, nb_namespaces, namespaces,
27977 nb_attributes, nb_defaulted,
27978 attributes);
27979}
27980
27981static void
27982endElementNsSplit(void *ctx, const xmlChar * localname,
27983 const xmlChar * prefix, const xmlChar * URI) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027984 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027985 if (ctxt == NULL)
27986 return;
27987 if ((ctxt->user_sax != NULL) &&
27988 (ctxt->user_sax->endElementNs != NULL))
27989 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
27990 if (ctxt->ctxt != NULL)
27991 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
27992}
27993
Daniel Veillard4255d502002-04-16 15:50:10 +000027994/**
Daniel Veillard971771e2005-07-09 17:32:57 +000027995 * xmlSchemaSAXPlug:
27996 * @ctxt: a schema validation context
Daniel Veillard1f33c4d2005-07-10 21:38:31 +000027997 * @sax: a pointer to the original xmlSAXHandlerPtr
27998 * @user_data: a pointer to the original SAX user data pointer
Daniel Veillard971771e2005-07-09 17:32:57 +000027999 *
28000 * Plug a SAX based validation layer in a SAX parsing event flow.
28001 * The original @saxptr and @dataptr data are replaced by new pointers
28002 * but the calls to the original will be maintained.
28003 *
28004 * Returns a pointer to a data structure needed to unplug the validation layer
28005 * or NULL in case of errors.
28006 */
28007xmlSchemaSAXPlugPtr
28008xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28009 xmlSAXHandlerPtr *sax, void **user_data)
28010{
28011 xmlSchemaSAXPlugPtr ret;
28012 xmlSAXHandlerPtr old_sax;
28013
28014 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28015 return(NULL);
28016
28017 /*
28018 * We only allow to plug into SAX2 event streams
28019 */
28020 old_sax = *sax;
28021 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28022 return(NULL);
28023 if ((old_sax != NULL) &&
28024 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28025 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28026 return(NULL);
28027
28028 /*
28029 * everything seems right allocate the local data needed for that layer
28030 */
28031 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28032 if (ret == NULL) {
28033 return(NULL);
28034 }
28035 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28036 ret->magic = XML_SAX_PLUG_MAGIC;
28037 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28038 ret->ctxt = ctxt;
28039 ret->user_sax_ptr = sax;
28040 ret->user_sax = old_sax;
28041 if (old_sax == NULL) {
28042 /*
28043 * go direct, no need for the split block and functions.
28044 */
28045 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28046 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28047 /*
28048 * Note that we use the same text-function for both, to prevent
28049 * the parser from testing for ignorable whitespace.
28050 */
28051 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28052 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28053
28054 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28055 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28056
28057 ret->user_data = ctxt;
28058 *user_data = ctxt;
28059 } else {
28060 /*
28061 * for each callback unused by Schemas initialize it to the Split
28062 * routine only if non NULL in the user block, this can speed up
28063 * things at the SAX level.
28064 */
28065 if (old_sax->internalSubset != NULL)
28066 ret->schemas_sax.internalSubset = internalSubsetSplit;
28067 if (old_sax->isStandalone != NULL)
28068 ret->schemas_sax.isStandalone = isStandaloneSplit;
28069 if (old_sax->hasInternalSubset != NULL)
28070 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28071 if (old_sax->hasExternalSubset != NULL)
28072 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28073 if (old_sax->resolveEntity != NULL)
28074 ret->schemas_sax.resolveEntity = resolveEntitySplit;
28075 if (old_sax->getEntity != NULL)
28076 ret->schemas_sax.getEntity = getEntitySplit;
28077 if (old_sax->entityDecl != NULL)
28078 ret->schemas_sax.entityDecl = entityDeclSplit;
28079 if (old_sax->notationDecl != NULL)
28080 ret->schemas_sax.notationDecl = notationDeclSplit;
28081 if (old_sax->attributeDecl != NULL)
28082 ret->schemas_sax.attributeDecl = attributeDeclSplit;
28083 if (old_sax->elementDecl != NULL)
28084 ret->schemas_sax.elementDecl = elementDeclSplit;
28085 if (old_sax->unparsedEntityDecl != NULL)
28086 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28087 if (old_sax->setDocumentLocator != NULL)
28088 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28089 if (old_sax->startDocument != NULL)
28090 ret->schemas_sax.startDocument = startDocumentSplit;
28091 if (old_sax->endDocument != NULL)
28092 ret->schemas_sax.endDocument = endDocumentSplit;
28093 if (old_sax->processingInstruction != NULL)
28094 ret->schemas_sax.processingInstruction = processingInstructionSplit;
28095 if (old_sax->comment != NULL)
28096 ret->schemas_sax.comment = commentSplit;
28097 if (old_sax->warning != NULL)
28098 ret->schemas_sax.warning = warningSplit;
28099 if (old_sax->error != NULL)
28100 ret->schemas_sax.error = errorSplit;
28101 if (old_sax->fatalError != NULL)
28102 ret->schemas_sax.fatalError = fatalErrorSplit;
28103 if (old_sax->getParameterEntity != NULL)
28104 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28105 if (old_sax->externalSubset != NULL)
28106 ret->schemas_sax.externalSubset = externalSubsetSplit;
28107
28108 /*
28109 * the 6 schemas callback have to go to the splitter functions
28110 * Note that we use the same text-function for ignorableWhitespace
28111 * if possible, to prevent the parser from testing for ignorable
28112 * whitespace.
28113 */
28114 ret->schemas_sax.characters = charactersSplit;
28115 if ((old_sax->ignorableWhitespace != NULL) &&
28116 (old_sax->ignorableWhitespace != old_sax->characters))
28117 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28118 else
28119 ret->schemas_sax.ignorableWhitespace = charactersSplit;
28120 ret->schemas_sax.cdataBlock = cdataBlockSplit;
28121 ret->schemas_sax.reference = referenceSplit;
28122 ret->schemas_sax.startElementNs = startElementNsSplit;
28123 ret->schemas_sax.endElementNs = endElementNsSplit;
28124
28125 ret->user_data_ptr = user_data;
28126 ret->user_data = *user_data;
28127 *user_data = ret;
28128 }
28129
28130 /*
28131 * plug the pointers back.
28132 */
28133 *sax = &(ret->schemas_sax);
Daniel Veillardf10ae122005-07-10 19:03:16 +000028134 ctxt->sax = *sax;
28135 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28136 xmlSchemaPreRun(ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000028137 return(ret);
28138}
28139
28140/**
28141 * xmlSchemaSAXUnplug:
28142 * @plug: a data structure returned by xmlSchemaSAXPlug
28143 *
28144 * Unplug a SAX based validation layer in a SAX parsing event flow.
28145 * The original pointers used in the call are restored.
28146 *
28147 * Returns 0 in case of success and -1 in case of failure.
28148 */
28149int
28150xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28151{
28152 xmlSAXHandlerPtr *sax;
28153 void **user_data;
28154
28155 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28156 return(-1);
28157 plug->magic = 0;
28158
Daniel Veillardf10ae122005-07-10 19:03:16 +000028159 xmlSchemaPostRun(plug->ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000028160 /* restore the data */
28161 sax = plug->user_sax_ptr;
28162 *sax = plug->user_sax;
28163 if (plug->user_sax != NULL) {
28164 user_data = plug->user_data_ptr;
28165 *user_data = plug->user_data;
28166 }
28167
28168 /* free and return */
28169 xmlFree(plug);
28170 return(0);
28171}
28172
28173/**
Daniel Veillard4255d502002-04-16 15:50:10 +000028174 * xmlSchemaValidateStream:
28175 * @ctxt: a schema validation context
28176 * @input: the input to use for reading the data
28177 * @enc: an optional encoding information
28178 * @sax: a SAX handler for the resulting events
28179 * @user_data: the context to provide to the SAX handler.
28180 *
Daniel Veillardcdc82732005-07-08 15:04:06 +000028181 * Validate an input based on a flow of SAX event from the parser
28182 * and forward the events to the @sax handler with the provided @user_data
28183 * the user provided @sax handler must be a SAX2 one.
Daniel Veillard4255d502002-04-16 15:50:10 +000028184 *
28185 * Returns 0 if the document is schemas valid, a positive error code
28186 * number otherwise and -1 in case of internal or API error.
28187 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028188int
Daniel Veillard4255d502002-04-16 15:50:10 +000028189xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028190 xmlParserInputBufferPtr input, xmlCharEncoding enc,
28191 xmlSAXHandlerPtr sax, void *user_data)
28192{
Daniel Veillard971771e2005-07-09 17:32:57 +000028193 xmlSchemaSAXPlugPtr plug = NULL;
28194 xmlSAXHandlerPtr old_sax = NULL;
28195 xmlParserCtxtPtr pctxt = NULL;
28196 xmlParserInputPtr inputStream = NULL;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028197 int ret;
28198
Daniel Veillard4255d502002-04-16 15:50:10 +000028199 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028200 return (-1);
Daniel Veillardcdc82732005-07-08 15:04:06 +000028201
Daniel Veillardcdc82732005-07-08 15:04:06 +000028202 /*
28203 * prepare the parser
28204 */
28205 pctxt = xmlNewParserCtxt();
28206 if (pctxt == NULL)
28207 return (-1);
28208 old_sax = pctxt->sax;
Daniel Veillard971771e2005-07-09 17:32:57 +000028209 pctxt->sax = sax;
28210 pctxt->userData = user_data;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028211#if 0
28212 if (options)
28213 xmlCtxtUseOptions(pctxt, options);
28214#endif
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000028215 pctxt->linenumbers = 1;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028216
Daniel Veillardf0af8ec2005-07-08 17:27:33 +000028217 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028218 if (inputStream == NULL) {
28219 ret = -1;
28220 goto done;
28221 }
28222 inputPush(pctxt, inputStream);
28223 ctxt->parserCtxt = pctxt;
28224 ctxt->input = input;
28225
28226 /*
Daniel Veillard971771e2005-07-09 17:32:57 +000028227 * Plug the validation and launch the parsing
Daniel Veillardcdc82732005-07-08 15:04:06 +000028228 */
Daniel Veillard971771e2005-07-09 17:32:57 +000028229 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28230 if (plug == NULL) {
28231 ret = -1;
28232 goto done;
28233 }
28234 ctxt->input = input;
28235 ctxt->enc = enc;
28236 ctxt->sax = pctxt->sax;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028237 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28238 ret = xmlSchemaVStart(ctxt);
28239
28240 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28241 ret = ctxt->parserCtxt->errNo;
28242 if (ret == 0)
28243 ret = 1;
28244 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028245
28246done:
Daniel Veillard971771e2005-07-09 17:32:57 +000028247 ctxt->parserCtxt = NULL;
28248 ctxt->sax = NULL;
28249 ctxt->input = NULL;
28250 if (plug != NULL) {
28251 xmlSchemaSAXUnplug(plug);
28252 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028253 /* cleanup */
Daniel Veillard971771e2005-07-09 17:32:57 +000028254 if (pctxt != NULL) {
28255 pctxt->sax = old_sax;
28256 xmlFreeParserCtxt(pctxt);
28257 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028258 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000028259}
28260
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028261/**
28262 * xmlSchemaValidateFile:
28263 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000028264 * @filename: the URI of the instance
28265 * @options: a future set of options, currently unused
28266 *
28267 * Do a schemas validation of the given resource, it will use the
28268 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028269 *
28270 * Returns 0 if the document is valid, a positive error code
28271 * number otherwise and -1 in case of an internal or API error.
28272 */
28273int
28274xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000028275 const char * filename,
28276 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028277{
28278 int ret;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028279 xmlParserInputBufferPtr input;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028280
28281 if ((ctxt == NULL) || (filename == NULL))
28282 return (-1);
28283
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028284 input = xmlParserInputBufferCreateFilename(filename,
28285 XML_CHAR_ENCODING_NONE);
28286 if (input == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028287 return (-1);
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028288 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28289 NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028290 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000028291}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028292
Daniel Veillard5d4644e2005-04-01 13:11:58 +000028293#define bottom_xmlschemas
28294#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000028295#endif /* LIBXML_SCHEMAS_ENABLED */