blob: 85fe1413c9e915aea3649fc12fd0baf48523efc7 [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. Buchcik4efd90d2005-06-09 10:32:53 +000083#define DEBUG_ATTR_VALIDATION 0
Daniel Veillardc0826a72004-08-10 14:17:33 +000084
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000085/* #define DEBUG_IDC */
86
87/* #define DEBUG_IDC_NODE_TABLE */
88
89#ifdef DEBUG_IDC
90 #ifndef DEBUG_IDC_NODE_TABLE
91 #define DEBUG_IDC_NODE_TABLE
92 #endif
93#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000094
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000095/* #define ENABLE_PARTICLE_RESTRICTION 1 */
96
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000097#define ENABLE_REDEFINE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000098
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000099/* #define ENABLE_NAMED_LOCALS */
100
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000101#define ENABLE_IDC_NODE_TABLES
102
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000103#define DUMP_CONTENT_MODEL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000104
105#ifdef LIBXML_READER_ENABLED
106/* #define XML_SCHEMA_READER_ENABLED */
107#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +0000108
Daniel Veillard4255d502002-04-16 15:50:10 +0000109#define UNBOUNDED (1 << 30)
110#define TODO \
111 xmlGenericError(xmlGenericErrorContext, \
112 "Unimplemented block at %s:%d\n", \
113 __FILE__, __LINE__);
114
William M. Brack2f2a6632004-08-20 23:09:47 +0000115#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +0000116
Daniel Veillard4255d502002-04-16 15:50:10 +0000117/*
118 * The XML Schemas namespaces
119 */
120static const xmlChar *xmlSchemaNs = (const xmlChar *)
121 "http://www.w3.org/2001/XMLSchema";
122
123static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
124 "http://www.w3.org/2001/XMLSchema-instance";
125
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000126static const xmlChar *xmlNamespaceNs = (const xmlChar *)
127 "http://www.w3.org/2000/xmlns/";
128
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000129/*
130* Come casting macros.
131*/
132#define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
133#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;
581 void *userData; /* user specific data block */
582 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;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000958 void *userData; /* user specific data block */
959 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,
1050 xmlSchemaParserCtxtPtr 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. Buchcik570faa52005-10-10 13:18:40 +00001076xmlSchemaCheckCOSSTDerivedOK(xmlSchemaParserCtxtPtr ctxt,
1077 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;
1881 data = ctxt->userData;
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;
1947 data = ctxt->userData;
1948 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;
2027 data = vctxt->userData;
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;
2079 data = pctxt->userData;
2080 __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. Buchcik4efd90d2005-06-09 10:32:53 +00002138 if (node != NULL) {
2139 /*
2140 * Work on tree nodes.
2141 */
2142 if (node->type == XML_ATTRIBUTE_NODE) {
2143 xmlNodePtr elem = node->parent;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002144
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002145 *msg = xmlStrdup(BAD_CAST "Element '");
2146 if (elem->ns != NULL)
2147 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2148 elem->ns->href, elem->name));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002149 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002150 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2151 NULL, elem->name));
2152 FREE_AND_NULL(str);
2153 *msg = xmlStrcat(*msg, BAD_CAST "', ");
2154 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2155 } else {
2156 *msg = xmlStrdup(BAD_CAST "Element '");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002157 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002158 if (node->ns != NULL)
2159 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2160 node->ns->href, node->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002161 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002162 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2163 NULL, node->name));
2164 FREE_AND_NULL(str);
2165 *msg = xmlStrcat(*msg, BAD_CAST "': ");
2166 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2167 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2168 /*
2169 * Work on node infos.
2170 */
2171 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2172 xmlSchemaNodeInfoPtr ielem =
2173 vctxt->elemInfos[vctxt->depth];
2174
2175 *msg = xmlStrdup(BAD_CAST "Element '");
2176 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2177 ielem->nsName, ielem->localName));
2178 FREE_AND_NULL(str);
2179 *msg = xmlStrcat(*msg, BAD_CAST "', ");
2180 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2181 } else {
2182 *msg = xmlStrdup(BAD_CAST "Element '");
2183 }
2184 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2185 vctxt->inode->nsName, vctxt->inode->localName));
2186 FREE_AND_NULL(str);
2187 *msg = xmlStrcat(*msg, BAD_CAST "': ");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002188 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2189 /*
2190 * Hmm, no node while parsing?
2191 * Return an empty string, in case NULL will break something.
2192 */
2193 *msg = xmlStrdup(BAD_CAST "");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002194 } else {
2195 TODO
2196 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002197 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002198 /*
2199 * VAL TODO: The output of the given schema component is currently
2200 * disabled.
2201 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002202#if 0
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002203 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2204 *msg = xmlStrcat(*msg, BAD_CAST " [");
2205 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2206 NULL, type, NULL, 0));
2207 FREE_AND_NULL(str)
2208 *msg = xmlStrcat(*msg, BAD_CAST "]");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002209 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002210#endif
2211 return (*msg);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002212}
2213
Daniel Veillardc0826a72004-08-10 14:17:33 +00002214static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002215xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002216 const char *funcName,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002217 const char *message,
2218 const xmlChar *str1,
2219 const xmlChar *str2)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002220{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002221 xmlChar *msg = NULL;
2222
2223 msg = xmlStrdup(BAD_CAST "Internal error: ");
2224 msg = xmlStrcat(msg, BAD_CAST funcName);
2225 msg = xmlStrcat(msg, BAD_CAST ", ");
2226 msg = xmlStrcat(msg, BAD_CAST message);
2227 msg = xmlStrcat(msg, BAD_CAST ".\n");
2228
2229 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2230 xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002231 (const char *) msg, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002232
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002233 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002234 xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002235 (const char *) msg, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002236
2237 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002238}
2239
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002240static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002241xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2242 const char *funcName,
2243 const char *message)
2244{
2245 xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2246}
2247
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002248#if 0
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002249static void
2250xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2251 const char *funcName,
2252 const char *message,
2253 const xmlChar *str1,
2254 const xmlChar *str2)
2255{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002256 xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002257 str1, str2);
2258}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002259#endif
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002260
2261static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002262xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2263 xmlParserErrors error,
2264 xmlNodePtr node,
2265 xmlSchemaBasicItemPtr item,
2266 const char *message,
2267 const xmlChar *str1, const xmlChar *str2,
2268 const xmlChar *str3, const xmlChar *str4)
2269{
2270 xmlChar *msg = NULL;
2271
2272 if ((node == NULL) && (item != NULL) &&
2273 (actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2274 node = WXS_ITEM_NODE(item);
2275 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2276 msg = xmlStrcat(msg, BAD_CAST ": ");
2277 } else
2278 xmlSchemaFormatNodeForError(&msg, actxt, node);
2279 msg = xmlStrcat(msg, (const xmlChar *) message);
2280 msg = xmlStrcat(msg, BAD_CAST ".\n");
2281 xmlSchemaErr4(actxt, error, node,
2282 (const char *) msg, str1, str2, str3, str4);
2283 FREE_AND_NULL(msg)
2284}
2285
2286static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002287xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2288 xmlParserErrors error,
2289 xmlNodePtr node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002290 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002291 const char *message,
2292 const xmlChar *str1,
2293 const xmlChar *str2)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002294{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002295 xmlSchemaCustomErr4(actxt, error, node, item,
2296 message, str1, str2, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002297}
2298
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002299
2300
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002301static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002302xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2303 xmlParserErrors error,
2304 xmlNodePtr node,
2305 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2306 const char *message,
2307 const xmlChar *str1,
2308 const xmlChar *str2,
2309 const xmlChar *str3)
2310{
2311 xmlChar *msg = NULL;
2312
2313 xmlSchemaFormatNodeForError(&msg, actxt, node);
2314 msg = xmlStrcat(msg, (const xmlChar *) message);
2315 msg = xmlStrcat(msg, BAD_CAST ".\n");
2316
2317 /* URGENT TODO: Set the error code to something sane. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002318 xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2319 (const char *) msg, str1, str2, str3, NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002320
2321 FREE_AND_NULL(msg)
2322}
2323
2324
2325
2326static void
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002327xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2328 xmlParserErrors error,
2329 xmlSchemaPSVIIDCNodePtr idcNode,
2330 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2331 const char *message,
2332 const xmlChar *str1,
2333 const xmlChar *str2)
2334{
2335 xmlChar *msg = NULL, *qname = NULL;
2336
2337 msg = xmlStrdup(BAD_CAST "Element '%s': ");
2338 msg = xmlStrcat(msg, (const xmlChar *) message);
2339 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002340 xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002341 error, NULL, idcNode->nodeLine, (const char *) msg,
2342 xmlSchemaFormatQName(&qname,
2343 vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2344 vctxt->nodeQNames->items[idcNode->nodeQNameID]),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002345 str1, str2, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002346 FREE_AND_NULL(qname);
2347 FREE_AND_NULL(msg);
2348}
2349
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002350static int
2351xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2352 xmlNodePtr node)
2353{
2354 if (node != NULL)
2355 return (node->type);
2356 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2357 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2358 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2359 return (-1);
2360}
2361
2362static int
2363xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2364{
2365 switch (item->type) {
2366 case XML_SCHEMA_TYPE_COMPLEX:
2367 case XML_SCHEMA_TYPE_SIMPLE:
2368 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2369 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002370 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002371 case XML_SCHEMA_TYPE_GROUP:
2372 return (1);
2373 case XML_SCHEMA_TYPE_ELEMENT:
2374 if ( ((xmlSchemaElementPtr) item)->flags &
2375 XML_SCHEMAS_ELEM_GLOBAL)
2376 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002377 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002378 case XML_SCHEMA_TYPE_ATTRIBUTE:
2379 if ( ((xmlSchemaAttributePtr) item)->flags &
2380 XML_SCHEMAS_ATTR_GLOBAL)
2381 return(1);
2382 break;
2383 /* Note that attribute groups are always global. */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002384 default:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002385 return(1);
2386 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002387 return (0);
2388}
2389
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002390static void
2391xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2392 xmlParserErrors error,
2393 xmlNodePtr node,
2394 const xmlChar *value,
2395 xmlSchemaTypePtr type,
2396 int displayValue)
2397{
2398 xmlChar *msg = NULL;
2399
2400 xmlSchemaFormatNodeForError(&msg, actxt, node);
2401
2402 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2403 XML_ATTRIBUTE_NODE))
2404 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2405 else
2406 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2407 "value of ");
2408
2409 if (! xmlSchemaIsGlobalItem(type))
2410 msg = xmlStrcat(msg, BAD_CAST "the local ");
2411 else
2412 msg = xmlStrcat(msg, BAD_CAST "the ");
2413
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002414 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002415 msg = xmlStrcat(msg, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002416 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002417 msg = xmlStrcat(msg, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002418 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002419 msg = xmlStrcat(msg, BAD_CAST "union type");
2420
2421 if (xmlSchemaIsGlobalItem(type)) {
2422 xmlChar *str = NULL;
2423 msg = xmlStrcat(msg, BAD_CAST " '");
2424 if (type->builtInType != 0) {
2425 msg = xmlStrcat(msg, BAD_CAST "xs:");
2426 msg = xmlStrcat(msg, type->name);
2427 } else
2428 msg = xmlStrcat(msg,
2429 xmlSchemaFormatQName(&str,
2430 type->targetNamespace, type->name));
2431 msg = xmlStrcat(msg, BAD_CAST "'");
2432 FREE_AND_NULL(str);
2433 }
2434 msg = xmlStrcat(msg, BAD_CAST ".\n");
2435 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2436 XML_ATTRIBUTE_NODE))
2437 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2438 else
2439 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2440 FREE_AND_NULL(msg)
2441}
2442
Daniel Veillardc0826a72004-08-10 14:17:33 +00002443static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002444xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2445 xmlSchemaNodeInfoPtr ni,
2446 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002447{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002448 if (node != NULL) {
2449 if (node->ns != NULL)
2450 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2451 else
2452 return (xmlSchemaFormatQName(str, NULL, node->name));
2453 } else if (ni != NULL)
2454 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2455 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002456}
2457
Daniel Veillardc0826a72004-08-10 14:17:33 +00002458static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002459xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2460 xmlParserErrors error,
2461 xmlSchemaAttrInfoPtr ni,
2462 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002463{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002464 xmlChar *msg = NULL, *str = NULL;
2465
2466 xmlSchemaFormatNodeForError(&msg, actxt, node);
2467 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2468 xmlSchemaErr(actxt, error, node, (const char *) msg,
2469 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2470 NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002471 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002472 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002473}
2474
Daniel Veillardc0826a72004-08-10 14:17:33 +00002475static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002476xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2477 xmlParserErrors error,
2478 xmlNodePtr node,
2479 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002480 const char *message,
2481 int nbval,
2482 int nbneg,
2483 xmlChar **values)
2484{
2485 xmlChar *str = NULL, *msg = NULL;
2486 xmlChar *localName, *nsName;
2487 const xmlChar *cur, *end;
Daniel Veillard77005e62005-07-19 16:26:18 +00002488 int i, is_not;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002489
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002490 xmlSchemaFormatNodeForError(&msg, actxt, node);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002491 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002492 msg = xmlStrcat(msg, BAD_CAST ".");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002493 /*
2494 * Note that is does not make sense to report that we have a
2495 * wildcard here, since the wildcard might be unfolded into
2496 * multiple transitions.
2497 */
2498 if (nbval + nbneg > 0) {
2499 if (nbval + nbneg > 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002500 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002501 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002502 str = xmlStrdup(BAD_CAST " Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002503 nsName = NULL;
2504
2505 for (i = 0; i < nbval + nbneg; i++) {
2506 cur = values[i];
Daniel Veillard77005e62005-07-19 16:26:18 +00002507 if (cur == NULL)
2508 continue;
2509 if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2510 (cur[3] == ' ')) {
2511 is_not = 1;
2512 cur += 4;
Daniel Veillard6e65e152005-08-09 11:09:52 +00002513 str = xmlStrcat(str, BAD_CAST "##other");
Daniel Veillard77005e62005-07-19 16:26:18 +00002514 } else {
2515 is_not = 0;
2516 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002517 /*
2518 * Get the local name.
2519 */
2520 localName = NULL;
2521
2522 end = cur;
2523 if (*end == '*') {
2524 localName = xmlStrdup(BAD_CAST "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00002525 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002526 } else {
2527 while ((*end != 0) && (*end != '|'))
2528 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002529 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002530 }
2531 if (*end != 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00002532 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002533 /*
2534 * Skip "*|*" if they come with negated expressions, since
2535 * they represent the same negated wildcard.
2536 */
2537 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2538 /*
2539 * Get the namespace name.
2540 */
2541 cur = end;
2542 if (*end == '*') {
2543 nsName = xmlStrdup(BAD_CAST "{*}");
2544 } else {
2545 while (*end != 0)
2546 end++;
2547
2548 if (i >= nbval)
2549 nsName = xmlStrdup(BAD_CAST "{##other:");
2550 else
2551 nsName = xmlStrdup(BAD_CAST "{");
2552
2553 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2554 nsName = xmlStrcat(nsName, BAD_CAST "}");
2555 }
2556 str = xmlStrcat(str, BAD_CAST nsName);
2557 FREE_AND_NULL(nsName)
2558 } else {
2559 FREE_AND_NULL(localName);
2560 continue;
2561 }
2562 }
2563 str = xmlStrcat(str, BAD_CAST localName);
2564 FREE_AND_NULL(localName);
2565
2566 if (i < nbval + nbneg -1)
2567 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00002568 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002569 str = xmlStrcat(str, BAD_CAST " ).\n");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002570 msg = xmlStrcat(msg, BAD_CAST str);
2571 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002572 } else
2573 msg = xmlStrcat(msg, BAD_CAST "\n");
2574 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002575 xmlFree(msg);
2576}
2577
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002578static void
2579xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2580 xmlParserErrors error,
2581 xmlNodePtr node,
2582 const xmlChar *value,
2583 unsigned long length,
2584 xmlSchemaTypePtr type,
2585 xmlSchemaFacetPtr facet,
2586 const char *message,
2587 const xmlChar *str1,
2588 const xmlChar *str2)
2589{
2590 xmlChar *str = NULL, *msg = NULL;
2591 xmlSchemaTypeType facetType;
2592 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2593
2594 xmlSchemaFormatNodeForError(&msg, actxt, node);
2595 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2596 facetType = XML_SCHEMA_FACET_ENUMERATION;
2597 /*
2598 * If enumerations are validated, one must not expect the
2599 * facet to be given.
2600 */
2601 } else
2602 facetType = facet->type;
2603 msg = xmlStrcat(msg, BAD_CAST "[");
2604 msg = xmlStrcat(msg, BAD_CAST "facet '");
2605 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2606 msg = xmlStrcat(msg, BAD_CAST "'] ");
2607 if (message == NULL) {
2608 /*
2609 * Use a default message.
2610 */
2611 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2612 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2613 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2614
2615 char len[25], actLen[25];
2616
2617 /* FIXME, TODO: What is the max expected string length of the
2618 * this value?
2619 */
2620 if (nodeType == XML_ATTRIBUTE_NODE)
2621 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2622 else
2623 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2624
2625 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2626 snprintf(actLen, 24, "%lu", length);
2627
2628 if (facetType == XML_SCHEMA_FACET_LENGTH)
2629 msg = xmlStrcat(msg,
2630 BAD_CAST "this differs from the allowed length of '%s'.\n");
2631 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2632 msg = xmlStrcat(msg,
2633 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2634 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2635 msg = xmlStrcat(msg,
2636 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2637
2638 if (nodeType == XML_ATTRIBUTE_NODE)
2639 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2640 value, (const xmlChar *) actLen, (const xmlChar *) len);
2641 else
2642 xmlSchemaErr(actxt, error, node, (const char *) msg,
2643 (const xmlChar *) actLen, (const xmlChar *) len);
2644
2645 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2646 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2647 "of the set {%s}.\n");
2648 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2649 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2650 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2651 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2652 "by the pattern '%s'.\n");
2653 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2654 facet->value);
2655 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2656 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2657 "minimum value allowed ('%s').\n");
2658 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2659 facet->value);
2660 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2661 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2662 "maximum value allowed ('%s').\n");
2663 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2664 facet->value);
2665 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2666 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2667 "'%s'.\n");
2668 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2669 facet->value);
2670 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2671 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be more than "
2672 "'%s'.\n");
2673 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2674 facet->value);
2675 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2676 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2677 "digits than are allowed ('%s').\n");
2678 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2679 facet->value);
2680 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2681 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2682 "digits than are allowed ('%s').\n");
2683 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2684 facet->value);
2685 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2686 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2687 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2688 } else {
2689 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2690 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2691 }
2692 } else {
2693 msg = xmlStrcat(msg, (const xmlChar *) message);
2694 msg = xmlStrcat(msg, BAD_CAST ".\n");
2695 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2696 }
2697 FREE_AND_NULL(str)
2698 xmlFree(msg);
2699}
2700
2701#define VERROR(err, type, msg) \
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002702 xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002703
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002704#define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002705
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002706#define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2707#define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002708
2709#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2710
2711
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002712/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00002713 * xmlSchemaPMissingAttrErr:
2714 * @ctxt: the schema validation context
2715 * @ownerDes: the designation of the owner
2716 * @ownerName: the name of the owner
2717 * @ownerItem: the owner as a schema object
2718 * @ownerElem: the owner as an element node
2719 * @node: the parent element node of the missing attribute node
2720 * @type: the corresponding type of the attribute node
2721 *
2722 * Reports an illegal attribute.
2723 */
2724static void
2725xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002726 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002727 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002728 xmlNodePtr ownerElem,
2729 const char *name,
2730 const char *message)
2731{
2732 xmlChar *des = NULL;
2733
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002734 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2735
Daniel Veillardc0826a72004-08-10 14:17:33 +00002736 if (message != NULL)
2737 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002738 else
2739 xmlSchemaPErr(ctxt, ownerElem, error,
2740 "%s: The attribute '%s' is required but missing.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002741 BAD_CAST des, BAD_CAST name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002742 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002743}
2744
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002745
Daniel Veillardc0826a72004-08-10 14:17:33 +00002746/**
2747 * xmlSchemaPResCompAttrErr:
2748 * @ctxt: the schema validation context
2749 * @error: the error code
2750 * @ownerDes: the designation of the owner
2751 * @ownerItem: the owner as a schema object
2752 * @ownerElem: the owner as an element node
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002753 * @name: the name of the attribute holding the QName
Daniel Veillardc0826a72004-08-10 14:17:33 +00002754 * @refName: the referenced local name
2755 * @refURI: the referenced namespace URI
2756 * @message: optional message
2757 *
2758 * Used to report QName attribute values that failed to resolve
2759 * to schema components.
2760 */
2761static void
2762xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002763 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002764 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002765 xmlNodePtr ownerElem,
2766 const char *name,
2767 const xmlChar *refName,
2768 const xmlChar *refURI,
2769 xmlSchemaTypeType refType,
2770 const char *refTypeStr)
2771{
2772 xmlChar *des = NULL, *strA = NULL;
2773
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002774 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002775 if (refTypeStr == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002776 refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002777 xmlSchemaPErrExt(ctxt, ownerElem, error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002778 NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002779 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2780 "%s.\n", BAD_CAST des, BAD_CAST name,
2781 xmlSchemaFormatQName(&strA, refURI, refName),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002782 BAD_CAST refTypeStr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002783 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002784 FREE_AND_NULL(strA)
2785}
2786
William M. Brack2f2a6632004-08-20 23:09:47 +00002787/**
2788 * xmlSchemaPCustomAttrErr:
2789 * @ctxt: the schema parser context
2790 * @error: the error code
2791 * @ownerDes: the designation of the owner
2792 * @ownerItem: the owner as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002793 * @attr: the illegal attribute node
William M. Brack2f2a6632004-08-20 23:09:47 +00002794 *
2795 * Reports an illegal attribute during the parse.
2796 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002797static void
2798xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002799 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002800 xmlChar **ownerDes,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002801 xmlSchemaBasicItemPtr ownerItem,
William M. Brack2f2a6632004-08-20 23:09:47 +00002802 xmlAttrPtr attr,
2803 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002804{
2805 xmlChar *des = NULL;
2806
2807 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002808 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002809 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002810 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002811 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002812 } else
2813 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002814 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002815 "%s, attribute '%s': %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002816 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2817 if (ownerDes == NULL)
2818 FREE_AND_NULL(des);
2819}
2820
2821/**
2822 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002823 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002824 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002825 * @ownerDes: the designation of the attribute's owner
2826 * @ownerItem: the attribute's owner item
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002827 * @attr: the illegal attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00002828 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002829 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002830 */
2831static void
2832xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002833 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002834 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002835 xmlAttrPtr attr)
2836{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002837 xmlChar *strA = NULL, *strB = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002838
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002839 xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2840 xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2841 "%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2842 xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2843 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002844 FREE_AND_NULL(strA);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002845 FREE_AND_NULL(strB);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002846}
2847
William M. Brack2f2a6632004-08-20 23:09:47 +00002848/**
2849 * xmlSchemaPCustomErr:
2850 * @ctxt: the schema parser context
2851 * @error: the error code
2852 * @itemDes: the designation of the schema item
2853 * @item: the schema item
2854 * @itemElem: the node of the schema item
2855 * @message: the error message
2856 * @str1: an optional param for the error message
2857 * @str2: an optional param for the error message
2858 * @str3: an optional param for the error message
2859 *
2860 * Reports an error during parsing.
2861 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002862static void
2863xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002864 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002865 xmlSchemaBasicItemPtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002866 xmlNodePtr itemElem,
2867 const char *message,
2868 const xmlChar *str1,
2869 const xmlChar *str2,
2870 const xmlChar *str3)
2871{
2872 xmlChar *des = NULL, *msg = NULL;
2873
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002874 xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002875 msg = xmlStrdup(BAD_CAST "%s: ");
2876 msg = xmlStrcat(msg, (const xmlChar *) message);
2877 msg = xmlStrcat(msg, BAD_CAST ".\n");
2878 if ((itemElem == NULL) && (item != NULL))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002879 itemElem = WXS_ITEM_NODE(item);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002880 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002881 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002882 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002883 FREE_AND_NULL(msg);
2884}
2885
William M. Brack2f2a6632004-08-20 23:09:47 +00002886/**
2887 * xmlSchemaPCustomErr:
2888 * @ctxt: the schema parser context
2889 * @error: the error code
2890 * @itemDes: the designation of the schema item
2891 * @item: the schema item
2892 * @itemElem: the node of the schema item
2893 * @message: the error message
2894 * @str1: the optional param for the error message
2895 *
2896 * Reports an error during parsing.
2897 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002898static void
2899xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002900 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002901 xmlSchemaBasicItemPtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002902 xmlNodePtr itemElem,
2903 const char *message,
2904 const xmlChar *str1)
2905{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002906 xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002907 str1, NULL, NULL);
2908}
2909
William M. Brack2f2a6632004-08-20 23:09:47 +00002910/**
2911 * xmlSchemaPAttrUseErr:
2912 * @ctxt: the schema parser context
2913 * @error: the error code
2914 * @itemDes: the designation of the schema type
2915 * @item: the schema type
2916 * @itemElem: the node of the schema type
2917 * @attr: the invalid schema attribute
2918 * @message: the error message
2919 * @str1: the optional param for the error message
2920 *
2921 * Reports an attribute use error during parsing.
2922 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002923static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002924xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002925 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002926 xmlNodePtr node,
2927 xmlSchemaBasicItemPtr ownerItem,
2928 const xmlSchemaAttributeUsePtr attruse,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002929 const char *message,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002930 const xmlChar *str1, const xmlChar *str2,
2931 const xmlChar *str3,const xmlChar *str4)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002932{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002933 xmlChar *str = NULL, *msg = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002934
2935 xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
2936 msg = xmlStrcat(msg, BAD_CAST ", ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002937 msg = xmlStrcat(msg,
2938 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002939 WXS_BASIC_CAST attruse, NULL));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002940 FREE_AND_NULL(str);
2941 msg = xmlStrcat(msg, BAD_CAST ": ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002942 msg = xmlStrcat(msg, (const xmlChar *) message);
2943 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002944 xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
2945 (const char *) msg, str1, str2, str3, str4);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002946 xmlFree(msg);
2947}
2948
William M. Brack2f2a6632004-08-20 23:09:47 +00002949/**
2950 * xmlSchemaPIllegalFacetAtomicErr:
2951 * @ctxt: the schema parser context
2952 * @error: the error code
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002953 * @type: the schema type
2954 * @baseType: the base type of type
William M. Brack2f2a6632004-08-20 23:09:47 +00002955 * @facet: the illegal facet
2956 *
2957 * Reports an illegal facet for atomic simple types.
2958 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002959static void
2960xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002961 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002962 xmlSchemaTypePtr type,
2963 xmlSchemaTypePtr baseType,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002964 xmlSchemaFacetPtr facet)
2965{
2966 xmlChar *des = NULL, *strT = NULL;
2967
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002968 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
2969 xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002970 "%s: The facet '%s' is not allowed on types derived from the "
2971 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002972 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002973 xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002974 NULL, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002975 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002976 FREE_AND_NULL(strT);
2977}
2978
William M. Brack2f2a6632004-08-20 23:09:47 +00002979/**
2980 * xmlSchemaPIllegalFacetListUnionErr:
2981 * @ctxt: the schema parser context
2982 * @error: the error code
2983 * @itemDes: the designation of the schema item involved
2984 * @item: the schema item involved
2985 * @facet: the illegal facet
2986 *
2987 * Reports an illegal facet for <list> and <union>.
2988 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002989static void
2990xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002991 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002992 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002993 xmlSchemaFacetPtr facet)
2994{
2995 xmlChar *des = NULL, *strT = NULL;
2996
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002997 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
2998 type->node);
2999 xmlSchemaPErr(ctxt, type->node, error,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003000 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00003001 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003002 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003003 FREE_AND_NULL(strT);
3004}
3005
3006/**
3007 * xmlSchemaPMutualExclAttrErr:
3008 * @ctxt: the schema validation context
3009 * @error: the error code
3010 * @elemDes: the designation of the parent element node
3011 * @attr: the bad attribute node
3012 * @type: the corresponding type of the attribute node
3013 *
3014 * Reports an illegal attribute.
3015 */
3016static void
3017xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3018 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003019 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003020 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003021 const char *name1,
3022 const char *name2)
3023{
3024 xmlChar *des = NULL;
3025
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003026 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003027 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003028 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003029 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003030 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003031}
3032
3033/**
3034 * xmlSchemaPSimpleTypeErr:
3035 * @ctxt: the schema validation context
3036 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00003037 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00003038 * @ownerDes: the designation of the owner
3039 * @ownerItem: the schema object if existent
3040 * @node: the validated node
3041 * @value: the validated value
3042 *
3043 * Reports a simple type validation error.
3044 * TODO: Should this report the value of an element as well?
3045 */
3046static void
3047xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3048 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003049 xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003050 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00003051 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003052 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003053 const xmlChar *value,
3054 const char *message,
3055 const xmlChar *str1,
3056 const xmlChar *str2)
3057{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003058 xmlChar *msg = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003059
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003060 xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003061 if (message == NULL) {
3062 /*
3063 * Use default messages.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003064 */
3065 if (type != NULL) {
3066 if (node->type == XML_ATTRIBUTE_NODE)
3067 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3068 else
3069 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3070 "valid value of ");
3071 if (! xmlSchemaIsGlobalItem(type))
3072 msg = xmlStrcat(msg, BAD_CAST "the local ");
3073 else
3074 msg = xmlStrcat(msg, BAD_CAST "the ");
3075
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003076 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003077 msg = xmlStrcat(msg, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003078 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003079 msg = xmlStrcat(msg, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003080 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003081 msg = xmlStrcat(msg, BAD_CAST "union type");
3082
3083 if (xmlSchemaIsGlobalItem(type)) {
3084 xmlChar *str = NULL;
3085 msg = xmlStrcat(msg, BAD_CAST " '");
3086 if (type->builtInType != 0) {
3087 msg = xmlStrcat(msg, BAD_CAST "xs:");
3088 msg = xmlStrcat(msg, type->name);
3089 } else
3090 msg = xmlStrcat(msg,
3091 xmlSchemaFormatQName(&str,
3092 type->targetNamespace, type->name));
3093 msg = xmlStrcat(msg, BAD_CAST "'.");
3094 FREE_AND_NULL(str);
3095 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003096 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003097 if (node->type == XML_ATTRIBUTE_NODE)
3098 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3099 else
3100 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3101 "valid.");
3102 }
3103 if (expected) {
3104 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3105 msg = xmlStrcat(msg, BAD_CAST expected);
3106 msg = xmlStrcat(msg, BAD_CAST "'.\n");
3107 } else
3108 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00003109 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003110 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3111 else
3112 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3113 } else {
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00003114 msg = xmlStrcat(msg, BAD_CAST message);
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00003115 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003116 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00003117 (const char*) msg, str1, str2, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003118 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003119 /* Cleanup. */
3120 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003121}
3122
William M. Brack2f2a6632004-08-20 23:09:47 +00003123/**
3124 * xmlSchemaPContentErr:
3125 * @ctxt: the schema parser context
3126 * @error: the error code
3127 * @onwerDes: the designation of the holder of the content
3128 * @ownerItem: the owner item of the holder of the content
3129 * @ownerElem: the node of the holder of the content
3130 * @child: the invalid child node
3131 * @message: the optional error message
3132 * @content: the optional string describing the correct content
3133 *
3134 * Reports an error concerning the content of a schema element.
3135 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00003136static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003137xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003138 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003139 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003140 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003141 xmlNodePtr child,
3142 const char *message,
3143 const char *content)
3144{
3145 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003146
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003147 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003148 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003149 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3150 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003151 BAD_CAST des, BAD_CAST message);
3152 else {
3153 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003154 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3155 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003156 BAD_CAST des, BAD_CAST content);
3157 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003158 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3159 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003160 BAD_CAST des, NULL);
3161 }
3162 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003163 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003164}
3165
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003166/************************************************************************
3167 * *
3168 * Streamable error functions *
3169 * *
3170 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00003171
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003172
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003173
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003174
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003175/************************************************************************
3176 * *
3177 * Validation helper functions *
3178 * *
3179 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003180
Daniel Veillardc0826a72004-08-10 14:17:33 +00003181
Daniel Veillard4255d502002-04-16 15:50:10 +00003182/************************************************************************
3183 * *
3184 * Allocation functions *
3185 * *
3186 ************************************************************************/
3187
3188/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003189 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00003190 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00003191 *
3192 * Allocate a new Schema structure.
3193 *
3194 * Returns the newly allocated structure or NULL in case or error
3195 */
3196static xmlSchemaPtr
3197xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3198{
3199 xmlSchemaPtr ret;
3200
3201 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3202 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003203 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003204 return (NULL);
3205 }
3206 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003207 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003208 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003209
3210 return (ret);
3211}
3212
3213/**
3214 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00003215 *
3216 * Allocate a new Facet structure.
3217 *
3218 * Returns the newly allocated structure or NULL in case or error
3219 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003220xmlSchemaFacetPtr
3221xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00003222{
3223 xmlSchemaFacetPtr ret;
3224
3225 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3226 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003227 return (NULL);
3228 }
3229 memset(ret, 0, sizeof(xmlSchemaFacet));
3230
3231 return (ret);
3232}
3233
3234/**
3235 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00003236 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00003237 * @node: a node
3238 *
3239 * Allocate a new annotation structure.
3240 *
3241 * Returns the newly allocated structure or NULL in case or error
3242 */
3243static xmlSchemaAnnotPtr
3244xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3245{
3246 xmlSchemaAnnotPtr ret;
3247
3248 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3249 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003250 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003251 return (NULL);
3252 }
3253 memset(ret, 0, sizeof(xmlSchemaAnnot));
3254 ret->content = node;
3255 return (ret);
3256}
3257
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003258static xmlSchemaItemListPtr
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003259xmlSchemaItemListCreate(void)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003260{
3261 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003262
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003263 ret = xmlMalloc(sizeof(xmlSchemaItemList));
3264 if (ret == NULL) {
3265 xmlSchemaPErrMemory(NULL,
3266 "allocating an item list structure", NULL);
3267 return (NULL);
3268 }
3269 memset(ret, 0, sizeof(xmlSchemaItemList));
3270 return (ret);
3271}
3272
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00003273static void
3274xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3275{
3276 if (list->items != NULL) {
3277 xmlFree(list->items);
3278 list->items = NULL;
3279 }
3280 list->nbItems = 0;
3281 list->sizeItems = 0;
3282}
3283
3284static int
3285xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3286{
3287 if (list->items == NULL) {
3288 list->items = (void **) xmlMalloc(
3289 20 * sizeof(void *));
3290 if (list->items == NULL) {
3291 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3292 return(-1);
3293 }
3294 list->sizeItems = 20;
3295 } else if (list->sizeItems <= list->nbItems) {
3296 list->sizeItems *= 2;
3297 list->items = (void **) xmlRealloc(list->items,
3298 list->sizeItems * sizeof(void *));
3299 if (list->items == NULL) {
3300 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3301 list->sizeItems = 0;
3302 return(-1);
3303 }
3304 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00003305 list->items[list->nbItems++] = item;
3306 return(0);
3307}
3308
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003309static int
3310xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3311 int initialSize,
3312 void *item)
3313{
3314 if (list->items == NULL) {
3315 if (initialSize <= 0)
3316 initialSize = 1;
3317 list->items = (void **) xmlMalloc(
3318 initialSize * sizeof(void *));
3319 if (list->items == NULL) {
3320 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3321 return(-1);
3322 }
3323 list->sizeItems = initialSize;
3324 } else if (list->sizeItems <= list->nbItems) {
3325 list->sizeItems *= 2;
3326 list->items = (void **) xmlRealloc(list->items,
3327 list->sizeItems * sizeof(void *));
3328 if (list->items == NULL) {
3329 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3330 list->sizeItems = 0;
3331 return(-1);
3332 }
3333 }
3334 list->items[list->nbItems++] = item;
3335 return(0);
3336}
3337
3338static int
3339xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3340{
3341 if (list->items == NULL) {
3342 list->items = (void **) xmlMalloc(
3343 20 * sizeof(void *));
3344 if (list->items == NULL) {
3345 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3346 return(-1);
3347 }
3348 list->sizeItems = 20;
3349 } else if (list->sizeItems <= list->nbItems) {
3350 list->sizeItems *= 2;
3351 list->items = (void **) xmlRealloc(list->items,
3352 list->sizeItems * sizeof(void *));
3353 if (list->items == NULL) {
3354 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3355 list->sizeItems = 0;
3356 return(-1);
3357 }
3358 }
3359 /*
3360 * Just append if the index is greater/equal than the item count.
3361 */
3362 if (idx >= list->nbItems) {
3363 list->items[list->nbItems++] = item;
3364 } else {
3365 int i;
3366 for (i = list->nbItems; i > idx; i--)
3367 list->items[i] = list->items[i-1];
3368 list->items[idx] = item;
3369 list->nbItems++;
3370 }
3371 return(0);
3372}
3373
3374#if 0 /* enable if ever needed */
3375static int
3376xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3377 int initialSize,
3378 void *item,
3379 int idx)
3380{
3381 if (list->items == NULL) {
3382 if (initialSize <= 0)
3383 initialSize = 1;
3384 list->items = (void **) xmlMalloc(
3385 initialSize * sizeof(void *));
3386 if (list->items == NULL) {
3387 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3388 return(-1);
3389 }
3390 list->sizeItems = initialSize;
3391 } else if (list->sizeItems <= list->nbItems) {
3392 list->sizeItems *= 2;
3393 list->items = (void **) xmlRealloc(list->items,
3394 list->sizeItems * sizeof(void *));
3395 if (list->items == NULL) {
3396 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3397 list->sizeItems = 0;
3398 return(-1);
3399 }
3400 }
3401 /*
3402 * Just append if the index is greater/equal than the item count.
3403 */
3404 if (idx >= list->nbItems) {
3405 list->items[list->nbItems++] = item;
3406 } else {
3407 int i;
3408 for (i = list->nbItems; i > idx; i--)
3409 list->items[i] = list->items[i-1];
3410 list->items[idx] = item;
3411 list->nbItems++;
3412 }
3413 return(0);
3414}
3415#endif
3416
3417static int
3418xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3419{
3420 int i;
3421 if ((list->items == NULL) || (idx >= list->nbItems)) {
3422 xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3423 "index error.\n");
3424 return(-1);
3425 }
3426
3427 if (list->nbItems == 1) {
3428 /* TODO: Really free the list? */
3429 xmlFree(list->items);
3430 list->items = NULL;
3431 list->nbItems = 0;
3432 list->sizeItems = 0;
3433 } else if (list->nbItems -1 == idx) {
3434 list->nbItems--;
3435 } else {
3436 for (i = idx; i < list->nbItems -1; i++)
3437 list->items[i] = list->items[i+1];
3438 list->nbItems--;
3439 }
3440 return(0);
3441}
3442
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003443/**
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003444 * xmlSchemaItemListFree:
3445 * @annot: a schema type structure
3446 *
3447 * Deallocate a annotation structure
3448 */
3449static void
3450xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3451{
3452 if (list == NULL)
3453 return;
3454 if (list->items != NULL)
3455 xmlFree(list->items);
3456 xmlFree(list);
3457}
3458
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003459static void
3460xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003461{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003462 if (bucket == NULL)
3463 return;
3464 if (bucket->globals != NULL) {
3465 xmlSchemaComponentListFree(bucket->globals);
3466 xmlSchemaItemListFree(bucket->globals);
3467 }
3468 if (bucket->locals != NULL) {
3469 xmlSchemaComponentListFree(bucket->locals);
3470 xmlSchemaItemListFree(bucket->locals);
3471 }
3472 if (bucket->relations != NULL) {
3473 xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3474 do {
3475 prev = cur;
3476 cur = cur->next;
3477 xmlFree(prev);
3478 } while (cur != NULL);
3479 }
3480 if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3481 xmlFreeDoc(bucket->doc);
3482 }
3483 if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003484 if (WXS_IMPBUCKET(bucket)->schema != NULL)
3485 xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003486 }
3487 xmlFree(bucket);
3488}
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003489
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003490static xmlSchemaBucketPtr
3491xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003492 int type, const xmlChar *targetNamespace)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003493{
3494 xmlSchemaBucketPtr ret;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003495 int size;
3496 xmlSchemaPtr mainSchema;
3497
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003498 if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003499 PERROR_INT("xmlSchemaBucketCreate",
3500 "no main schema on constructor");
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003501 return(NULL);
3502 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003503 mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003504 /* Create the schema bucket. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003505 if (WXS_IS_BUCKET_INCREDEF(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003506 size = sizeof(xmlSchemaInclude);
3507 else
3508 size = sizeof(xmlSchemaImport);
3509 ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3510 if (ret == NULL) {
3511 xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3512 return(NULL);
3513 }
3514 memset(ret, 0, size);
3515 ret->targetNamespace = targetNamespace;
3516 ret->type = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003517 ret->globals = xmlSchemaItemListCreate();
3518 if (ret->globals == NULL) {
3519 xmlFree(ret);
3520 return(NULL);
3521 }
3522 ret->locals = xmlSchemaItemListCreate();
3523 if (ret->locals == NULL) {
3524 xmlFree(ret);
3525 return(NULL);
3526 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003527 /*
3528 * The following will assure that only the first bucket is marked as
3529 * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3530 * For each following import buckets an xmlSchema will be created.
3531 */
3532 if (! WXS_HAS_BUCKETS(pctxt)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003533 if (WXS_IS_BUCKET_INCREDEF(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003534 PERROR_INT("xmlSchemaBucketCreate",
3535 "first bucket but it's an include or redefine");
3536 xmlSchemaBucketFree(ret);
3537 return(NULL);
3538 }
3539 /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3540 ret->type = XML_SCHEMA_SCHEMA_MAIN;
3541 /* Point to the *main* schema. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003542 WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3543 WXS_IMPBUCKET(ret)->schema = mainSchema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003544 } else {
3545 if (type == XML_SCHEMA_SCHEMA_MAIN) {
3546 PERROR_INT("xmlSchemaBucketCreate",
3547 "main bucket but it's not the first one");
3548 xmlSchemaBucketFree(ret);
3549 return(NULL);
3550 } else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3551 /*
3552 * Create a schema for imports.
3553 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003554 WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3555 if (WXS_IMPBUCKET(ret)->schema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003556 xmlSchemaBucketFree(ret);
3557 return(NULL);
3558 }
3559 }
3560 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003561 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003562 int res;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003563 /* Imports go into the "schemasImports" slot of the main *schema*. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003564 if (mainSchema->schemasImports == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003565 mainSchema->schemasImports = xmlHashCreateDict(5,
3566 WXS_CONSTRUCTOR(pctxt)->dict);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003567 if (mainSchema->schemasImports == NULL) {
3568 xmlSchemaBucketFree(ret);
3569 return(NULL);
3570 }
3571 }
3572 if (targetNamespace == NULL)
3573 res = xmlHashAddEntry(mainSchema->schemasImports,
3574 XML_SCHEMAS_NO_NAMESPACE, ret);
3575 else
3576 res = xmlHashAddEntry(mainSchema->schemasImports,
3577 targetNamespace, ret);
3578 if (res != 0) {
3579 PERROR_INT("xmlSchemaBucketCreate",
3580 "failed to add the schema bucket to the hash");
3581 xmlSchemaBucketFree(ret);
3582 return(NULL);
3583 }
3584 } else {
3585 /* Set the @ownerImport of an include bucket. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003586 if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3587 WXS_INCBUCKET(ret)->ownerImport =
3588 WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003589 else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003590 WXS_INCBUCKET(ret)->ownerImport =
3591 WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003592
3593 /* Includes got into the "includes" slot of the *main* schema. */
3594 if (mainSchema->includes == NULL) {
3595 mainSchema->includes = xmlSchemaItemListCreate();
3596 if (mainSchema->includes == NULL) {
3597 xmlSchemaBucketFree(ret);
3598 return(NULL);
3599 }
3600 }
3601 xmlSchemaItemListAdd(mainSchema->includes, ret);
3602 }
3603 /*
3604 * Add to list of all buckets; this is used for lookup
3605 * during schema construction time only.
3606 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003607 if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003608 return(NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003609 return(ret);
3610}
3611
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003612static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003613xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003614{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003615 if (*list == NULL) {
3616 *list = xmlSchemaItemListCreate();
3617 if (*list == NULL)
3618 return(-1);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003619 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003620 xmlSchemaItemListAddSize(*list, initialSize, item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003621 return(0);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003622}
3623
3624/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00003625 * xmlSchemaFreeAnnot:
3626 * @annot: a schema type structure
3627 *
3628 * Deallocate a annotation structure
3629 */
3630static void
3631xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3632{
3633 if (annot == NULL)
3634 return;
Kasimier T. Buchcik004b5462005-08-08 12:43:09 +00003635 if (annot->next == NULL) {
3636 xmlFree(annot);
3637 } else {
3638 xmlSchemaAnnotPtr prev;
3639
3640 do {
3641 prev = annot;
3642 annot = annot->next;
3643 xmlFree(prev);
3644 } while (annot != NULL);
3645 }
Daniel Veillardfdc91562002-07-01 21:52:03 +00003646}
3647
3648/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003649 * xmlSchemaFreeNotation:
3650 * @schema: a schema notation structure
3651 *
3652 * Deallocate a Schema Notation structure.
3653 */
3654static void
3655xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3656{
3657 if (nota == NULL)
3658 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003659 xmlFree(nota);
3660}
3661
3662/**
3663 * xmlSchemaFreeAttribute:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003664 * @attr: an attribute declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00003665 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003666 * Deallocates an attribute declaration structure.
Daniel Veillard4255d502002-04-16 15:50:10 +00003667 */
3668static void
3669xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3670{
3671 if (attr == NULL)
3672 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003673 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003674 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003675 if (attr->defVal != NULL)
3676 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003677 xmlFree(attr);
3678}
3679
3680/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003681 * xmlSchemaFreeAttributeUse:
3682 * @use: an attribute use
3683 *
3684 * Deallocates an attribute use structure.
3685 */
3686static void
3687xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3688{
3689 if (use == NULL)
3690 return;
3691 if (use->annot != NULL)
3692 xmlSchemaFreeAnnot(use->annot);
3693 if (use->defVal != NULL)
3694 xmlSchemaFreeValue(use->defVal);
3695 xmlFree(use);
3696}
3697
3698/**
3699 * xmlSchemaFreeAttributeUseProhib:
3700 * @prohib: an attribute use prohibition
3701 *
3702 * Deallocates an attribute use structure.
3703 */
3704static void
3705xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3706{
3707 if (prohib == NULL)
3708 return;
3709 xmlFree(prohib);
3710}
3711
3712/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003713 * xmlSchemaFreeWildcardNsSet:
3714 * set: a schema wildcard namespace
3715 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003716 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00003717 */
3718static void
3719xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3720{
3721 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003722
Daniel Veillard3646d642004-06-02 19:19:14 +00003723 while (set != NULL) {
3724 next = set->next;
3725 xmlFree(set);
3726 set = next;
3727 }
3728}
3729
3730/**
3731 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003732 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00003733 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003734 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00003735 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003736void
Daniel Veillard3646d642004-06-02 19:19:14 +00003737xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3738{
3739 if (wildcard == NULL)
3740 return;
3741 if (wildcard->annot != NULL)
3742 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003743 if (wildcard->nsSet != NULL)
3744 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3745 if (wildcard->negNsSet != NULL)
3746 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00003747 xmlFree(wildcard);
3748}
3749
3750/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003751 * xmlSchemaFreeAttributeGroup:
3752 * @schema: a schema attribute group structure
3753 *
3754 * Deallocate a Schema Attribute Group structure.
3755 */
3756static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003757xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
Daniel Veillard4255d502002-04-16 15:50:10 +00003758{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003759 if (attrGr == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00003760 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003761 if (attrGr->annot != NULL)
3762 xmlSchemaFreeAnnot(attrGr->annot);
3763 if (attrGr->attrUses != NULL)
3764 xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3765 xmlFree(attrGr);
Daniel Veillard3646d642004-06-02 19:19:14 +00003766}
3767
3768/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003769 * xmlSchemaFreeQNameRef:
3770 * @item: a QName reference structure
3771 *
3772 * Deallocatea a QName reference structure.
3773 */
3774static void
3775xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3776{
3777 xmlFree(item);
3778}
3779
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003780/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003781 * xmlSchemaFreeTypeLinkList:
3782 * @alink: a type link
3783 *
3784 * Deallocate a list of types.
3785 */
3786static void
3787xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3788{
3789 xmlSchemaTypeLinkPtr next;
3790
3791 while (link != NULL) {
3792 next = link->next;
3793 xmlFree(link);
3794 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003795 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003796}
3797
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003798static void
3799xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3800{
3801 xmlSchemaIDCStateObjPtr next;
3802 while (sto != NULL) {
3803 next = sto->next;
3804 if (sto->history != NULL)
3805 xmlFree(sto->history);
3806 if (sto->xpathCtxt != NULL)
3807 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3808 xmlFree(sto);
3809 sto = next;
3810 }
3811}
3812
3813/**
3814 * xmlSchemaFreeIDC:
3815 * @idc: a identity-constraint definition
3816 *
3817 * Deallocates an identity-constraint definition.
3818 */
3819static void
3820xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3821{
3822 xmlSchemaIDCSelectPtr cur, prev;
3823
3824 if (idcDef == NULL)
3825 return;
3826 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003827 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003828 /* Selector */
3829 if (idcDef->selector != NULL) {
3830 if (idcDef->selector->xpathComp != NULL)
3831 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3832 xmlFree(idcDef->selector);
3833 }
3834 /* Fields */
3835 if (idcDef->fields != NULL) {
3836 cur = idcDef->fields;
3837 do {
3838 prev = cur;
3839 cur = cur->next;
3840 if (prev->xpathComp != NULL)
3841 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003842 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003843 } while (cur != NULL);
3844 }
3845 xmlFree(idcDef);
3846}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003847
Daniel Veillard01fa6152004-06-29 17:04:39 +00003848/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003849 * xmlSchemaFreeElement:
3850 * @schema: a schema element structure
3851 *
3852 * Deallocate a Schema Element structure.
3853 */
3854static void
3855xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3856{
3857 if (elem == NULL)
3858 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003859 if (elem->annot != NULL)
3860 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003861 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003862 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003863 if (elem->defVal != NULL)
3864 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003865 xmlFree(elem);
3866}
3867
3868/**
3869 * xmlSchemaFreeFacet:
3870 * @facet: a schema facet structure
3871 *
3872 * Deallocate a Schema Facet structure.
3873 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003874void
Daniel Veillard4255d502002-04-16 15:50:10 +00003875xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3876{
3877 if (facet == NULL)
3878 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003879 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003880 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003881 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003882 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003883 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003884 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003885 xmlFree(facet);
3886}
3887
3888/**
3889 * xmlSchemaFreeType:
3890 * @type: a schema type structure
3891 *
3892 * Deallocate a Schema Type structure.
3893 */
3894void
3895xmlSchemaFreeType(xmlSchemaTypePtr type)
3896{
3897 if (type == NULL)
3898 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003899 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003900 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003901 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003902 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003903
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003904 facet = type->facets;
3905 while (facet != NULL) {
3906 next = facet->next;
3907 xmlSchemaFreeFacet(facet);
3908 facet = next;
3909 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003910 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003911 if (type->attrUses != NULL)
3912 xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003913 if (type->memberTypes != NULL)
3914 xmlSchemaFreeTypeLinkList(type->memberTypes);
3915 if (type->facetSet != NULL) {
3916 xmlSchemaFacetLinkPtr next, link;
3917
3918 link = type->facetSet;
3919 do {
3920 next = link->next;
3921 xmlFree(link);
3922 link = next;
3923 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003924 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003925 if (type->contModel != NULL)
3926 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003927 xmlFree(type);
3928}
3929
3930/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003931 * xmlSchemaFreeModelGroupDef:
3932 * @item: a schema model group definition
3933 *
3934 * Deallocates a schema model group definition.
3935 */
3936static void
3937xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3938{
3939 if (item->annot != NULL)
3940 xmlSchemaFreeAnnot(item->annot);
3941 xmlFree(item);
3942}
3943
3944/**
3945 * xmlSchemaFreeModelGroup:
3946 * @item: a schema model group
3947 *
3948 * Deallocates a schema model group structure.
3949 */
3950static void
3951xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3952{
3953 if (item->annot != NULL)
3954 xmlSchemaFreeAnnot(item->annot);
3955 xmlFree(item);
3956}
3957
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003958static void
3959xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
3960{
3961 if ((list == NULL) || (list->nbItems == 0))
3962 return;
3963 {
3964 xmlSchemaTreeItemPtr item;
3965 xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
3966 int i;
3967
3968 for (i = 0; i < list->nbItems; i++) {
3969 item = items[i];
3970 if (item == NULL)
3971 continue;
3972 switch (item->type) {
3973 case XML_SCHEMA_TYPE_SIMPLE:
3974 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003975 xmlSchemaFreeType((xmlSchemaTypePtr) item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003976 break;
3977 case XML_SCHEMA_TYPE_ATTRIBUTE:
3978 xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003979 break;
3980 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
3981 xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
3982 break;
3983 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
3984 xmlSchemaFreeAttributeUseProhib(
3985 (xmlSchemaAttributeUseProhibPtr) item);
3986 break;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003987 case XML_SCHEMA_TYPE_ELEMENT:
3988 xmlSchemaFreeElement((xmlSchemaElementPtr) item);
3989 break;
3990 case XML_SCHEMA_TYPE_PARTICLE:
3991 if (item->annot != NULL)
3992 xmlSchemaFreeAnnot(item->annot);
3993 xmlFree(item);
3994 break;
3995 case XML_SCHEMA_TYPE_SEQUENCE:
3996 case XML_SCHEMA_TYPE_CHOICE:
3997 case XML_SCHEMA_TYPE_ALL:
3998 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
3999 break;
4000 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4001 xmlSchemaFreeAttributeGroup(
4002 (xmlSchemaAttributeGroupPtr) item);
4003 break;
4004 case XML_SCHEMA_TYPE_GROUP:
4005 xmlSchemaFreeModelGroupDef(
4006 (xmlSchemaModelGroupDefPtr) item);
4007 break;
4008 case XML_SCHEMA_TYPE_ANY:
4009 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4010 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4011 break;
4012 case XML_SCHEMA_TYPE_IDC_KEY:
4013 case XML_SCHEMA_TYPE_IDC_UNIQUE:
4014 case XML_SCHEMA_TYPE_IDC_KEYREF:
4015 xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4016 break;
4017 case XML_SCHEMA_TYPE_NOTATION:
4018 xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4019 break;
4020 case XML_SCHEMA_EXTRA_QNAMEREF:
4021 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4022 break;
4023 default: {
4024 /* TODO: This should never be hit. */
4025 xmlSchemaPSimpleInternalErr(NULL,
4026 "Internal error: xmlSchemaComponentListFree, "
4027 "unexpected component type '%s'\n",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004028 (const xmlChar *) WXS_ITEM_TYPE_NAME(item));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004029 }
4030 break;
4031 }
4032 }
4033 list->nbItems = 0;
4034 }
4035}
4036
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004037/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004038 * xmlSchemaFree:
4039 * @schema: a schema structure
4040 *
4041 * Deallocate a Schema structure.
4042 */
4043void
4044xmlSchemaFree(xmlSchemaPtr schema)
4045{
4046 if (schema == NULL)
4047 return;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004048 /* @volatiles is not used anymore :-/ */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004049 if (schema->volatiles != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004050 TODO
4051 /*
4052 * Note that those slots are not responsible for freeing
4053 * schema components anymore; this will now be done by
4054 * the schema buckets.
4055 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004056 if (schema->notaDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004057 xmlHashFree(schema->notaDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004058 if (schema->attrDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004059 xmlHashFree(schema->attrDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004060 if (schema->attrgrpDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004061 xmlHashFree(schema->attrgrpDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004062 if (schema->elemDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004063 xmlHashFree(schema->elemDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004064 if (schema->typeDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004065 xmlHashFree(schema->typeDecl, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004066 if (schema->groupDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004067 xmlHashFree(schema->groupDecl, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004068 if (schema->idcDef != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004069 xmlHashFree(schema->idcDef, NULL);
4070
Daniel Veillard1d913862003-11-21 00:28:39 +00004071 if (schema->schemasImports != NULL)
4072 xmlHashFree(schema->schemasImports,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004073 (xmlHashDeallocator) xmlSchemaBucketFree);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004074 if (schema->includes != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004075 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4076 int i;
4077 for (i = 0; i < list->nbItems; i++) {
4078 xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4079 }
4080 xmlSchemaItemListFree(list);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004081 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004082 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004083 xmlSchemaFreeAnnot(schema->annot);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004084 /* Never free the doc here, since this will be done by the buckets. */
4085
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004086 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004087 xmlFree(schema);
4088}
4089
4090/************************************************************************
4091 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00004092 * Debug functions *
4093 * *
4094 ************************************************************************/
4095
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00004096#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004097
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004098static void
4099xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4100
Daniel Veillard4255d502002-04-16 15:50:10 +00004101/**
4102 * xmlSchemaElementDump:
4103 * @elem: an element
4104 * @output: the file output
4105 *
4106 * Dump the element
4107 */
4108static void
4109xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004110 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004111 const xmlChar * namespace ATTRIBUTE_UNUSED,
4112 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00004113{
4114 if (elem == NULL)
4115 return;
4116
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004117
4118 fprintf(output, "Element");
4119 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4120 fprintf(output, " (global)");
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004121 fprintf(output, ": '%s' ", elem->name);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004122 if (namespace != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004123 fprintf(output, "ns '%s'", namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004124 fprintf(output, "\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004125#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004126 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004127 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004128 if (elem->maxOccurs >= UNBOUNDED)
4129 fprintf(output, "max: unbounded\n");
4130 else if (elem->maxOccurs != 1)
4131 fprintf(output, "max: %d\n", elem->maxOccurs);
4132 else
4133 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00004134 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004135#endif
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004136 /*
4137 * Misc other properties.
4138 */
4139 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4140 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4141 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004142 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004143 fprintf(output, " props: ");
4144 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4145 fprintf(output, "[fixed] ");
4146 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4147 fprintf(output, "[default] ");
4148 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4149 fprintf(output, "[abstract] ");
4150 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4151 fprintf(output, "[nillable] ");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004152 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00004153 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004154 /*
4155 * Default/fixed value.
4156 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004157 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004158 fprintf(output, " value: '%s'\n", elem->value);
4159 /*
4160 * Type.
4161 */
4162 if (elem->namedType != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004163 fprintf(output, " type: '%s' ", elem->namedType);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004164 if (elem->namedTypeNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004165 fprintf(output, "ns '%s'\n", elem->namedTypeNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004166 else
4167 fprintf(output, "\n");
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004168 } else if (elem->subtypes != NULL) {
4169 /*
4170 * Dump local types.
4171 */
4172 xmlSchemaTypeDump(elem->subtypes, output);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004173 }
4174 /*
4175 * Substitution group.
4176 */
4177 if (elem->substGroup != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004178 fprintf(output, " substitutionGroup: '%s' ", elem->substGroup);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004179 if (elem->substGroupNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004180 fprintf(output, "ns '%s'\n", elem->substGroupNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004181 else
4182 fprintf(output, "\n");
4183 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004184}
4185
4186/**
4187 * xmlSchemaAnnotDump:
4188 * @output: the file output
4189 * @annot: a annotation
4190 *
4191 * Dump the annotation
4192 */
4193static void
4194xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4195{
4196 xmlChar *content;
4197
4198 if (annot == NULL)
4199 return;
4200
4201 content = xmlNodeGetContent(annot->content);
4202 if (content != NULL) {
4203 fprintf(output, " Annot: %s\n", content);
4204 xmlFree(content);
4205 } else
4206 fprintf(output, " Annot: empty\n");
4207}
4208
4209/**
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004210 * xmlSchemaContentModelDump:
4211 * @particle: the schema particle
4212 * @output: the file output
4213 * @depth: the depth used for intentation
Daniel Veillard4255d502002-04-16 15:50:10 +00004214 *
4215 * Dump a SchemaType structure
4216 */
4217static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004218xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4219{
4220 xmlChar *str = NULL;
4221 xmlSchemaTreeItemPtr term;
4222 char shift[100];
4223 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004224
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004225 if (particle == NULL)
4226 return;
4227 for (i = 0;((i < depth) && (i < 25));i++)
4228 shift[2 * i] = shift[2 * i + 1] = ' ';
4229 shift[2 * i] = shift[2 * i + 1] = 0;
4230 fprintf(output, shift);
4231 if (particle->children == NULL) {
4232 fprintf(output, "MISSING particle term\n");
4233 return;
4234 }
4235 term = particle->children;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004236 if (term == NULL) {
4237 fprintf(output, "(NULL)");
4238 } else {
4239 switch (term->type) {
4240 case XML_SCHEMA_TYPE_ELEMENT:
4241 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4242 ((xmlSchemaElementPtr)term)->targetNamespace,
4243 ((xmlSchemaElementPtr)term)->name));
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004244 FREE_AND_NULL(str);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004245 break;
4246 case XML_SCHEMA_TYPE_SEQUENCE:
4247 fprintf(output, "SEQUENCE");
4248 break;
4249 case XML_SCHEMA_TYPE_CHOICE:
4250 fprintf(output, "CHOICE");
4251 break;
4252 case XML_SCHEMA_TYPE_ALL:
4253 fprintf(output, "ALL");
4254 break;
4255 case XML_SCHEMA_TYPE_ANY:
4256 fprintf(output, "ANY");
4257 break;
4258 default:
4259 fprintf(output, "UNKNOWN\n");
4260 return;
4261 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004262 }
4263 if (particle->minOccurs != 1)
4264 fprintf(output, " min: %d", particle->minOccurs);
4265 if (particle->maxOccurs >= UNBOUNDED)
4266 fprintf(output, " max: unbounded");
4267 else if (particle->maxOccurs != 1)
4268 fprintf(output, " max: %d", particle->maxOccurs);
4269 fprintf(output, "\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004270 if (term &&
4271 ((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4272 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4273 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4274 (term->children != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004275 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4276 output, depth +1);
4277 }
4278 if (particle->next != NULL)
4279 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4280 output, depth);
4281}
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004282
4283/**
4284 * xmlSchemaAttrUsesDump:
4285 * @uses: attribute uses list
4286 * @output: the file output
4287 *
4288 * Dumps a list of attribute use components.
4289 */
4290static void
4291xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4292{
4293 xmlSchemaAttributeUsePtr use;
4294 xmlSchemaAttributeUseProhibPtr prohib;
4295 xmlSchemaQNameRefPtr ref;
4296 const xmlChar *name, *tns;
4297 xmlChar *str = NULL;
4298 int i;
4299
4300 if ((uses == NULL) || (uses->nbItems == 0))
4301 return;
4302
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004303 fprintf(output, " attributes:\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004304 for (i = 0; i < uses->nbItems; i++) {
4305 use = uses->items[i];
4306 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4307 fprintf(output, " [prohibition] ");
4308 prohib = (xmlSchemaAttributeUseProhibPtr) use;
4309 name = prohib->name;
4310 tns = prohib->targetNamespace;
4311 } else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4312 fprintf(output, " [reference] ");
4313 ref = (xmlSchemaQNameRefPtr) use;
4314 name = ref->name;
4315 tns = ref->targetNamespace;
4316 } else {
4317 fprintf(output, " [use] ");
4318 name = WXS_ATTRUSE_DECL_NAME(use);
4319 tns = WXS_ATTRUSE_DECL_TNS(use);
4320 }
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004321 fprintf(output, "'%s'\n",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004322 (const char *) xmlSchemaFormatQName(&str, tns, name));
4323 FREE_AND_NULL(str);
4324 }
4325}
4326
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004327/**
4328 * xmlSchemaTypeDump:
4329 * @output: the file output
4330 * @type: a type structure
4331 *
4332 * Dump a SchemaType structure
4333 */
4334static void
Daniel Veillard4255d502002-04-16 15:50:10 +00004335xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4336{
4337 if (type == NULL) {
4338 fprintf(output, "Type: NULL\n");
4339 return;
4340 }
4341 fprintf(output, "Type: ");
4342 if (type->name != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004343 fprintf(output, "'%s' ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004344 else
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004345 fprintf(output, "(no name) ");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004346 if (type->targetNamespace != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004347 fprintf(output, "ns '%s' ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004348 switch (type->type) {
4349 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004350 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004351 break;
4352 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004353 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004354 break;
4355 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004356 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004357 break;
4358 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004359 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004360 break;
4361 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004362 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004363 break;
4364 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004365 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004366 break;
4367 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004368 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004369 break;
4370 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004371 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004372 break;
4373 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004374 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004375 break;
4376 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004377 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00004378 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004379 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004380 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004381 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004382 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004383 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004384 break;
4385 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004386 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004387 break;
4388 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004389 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004390 break;
4391 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004392 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004393 break;
4394 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004395 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004396 break;
4397 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004398 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004399 break;
4400 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004401 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004402 break;
4403 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004404 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004405 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00004406 }
4407 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004408 if (type->base != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004409 fprintf(output, " base type: '%s'", type->base);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004410 if (type->baseNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004411 fprintf(output, " ns '%s'\n", type->baseNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004412 else
4413 fprintf(output, "\n");
4414 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004415 if (type->attrUses != NULL)
4416 xmlSchemaAttrUsesDump(type->attrUses, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00004417 if (type->annot != NULL)
4418 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004419#ifdef DUMP_CONTENT_MODEL
4420 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4421 (type->subtypes != NULL)) {
4422 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4423 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004424 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004425#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004426}
4427
4428/**
4429 * xmlSchemaDump:
4430 * @output: the file output
4431 * @schema: a schema structure
4432 *
4433 * Dump a Schema structure.
4434 */
4435void
4436xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4437{
Daniel Veillardce682bc2004-11-05 17:22:25 +00004438 if (output == NULL)
4439 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004440 if (schema == NULL) {
4441 fprintf(output, "Schemas: NULL\n");
4442 return;
4443 }
4444 fprintf(output, "Schemas: ");
4445 if (schema->name != NULL)
4446 fprintf(output, "%s, ", schema->name);
4447 else
4448 fprintf(output, "no name, ");
4449 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00004450 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004451 else
4452 fprintf(output, "no target namespace");
4453 fprintf(output, "\n");
4454 if (schema->annot != NULL)
4455 xmlSchemaAnnotDump(output, schema->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00004456 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
4457 output);
4458 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004459 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00004460}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004461
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004462#ifdef DEBUG_IDC_NODE_TABLE
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004463/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004464 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004465 * @vctxt: the WXS validation context
4466 *
4467 * Displays the current IDC table for debug purposes.
4468 */
4469static void
4470xmlSchemaDebugDumpIDCTable(FILE * output,
4471 const xmlChar *namespaceName,
4472 const xmlChar *localName,
4473 xmlSchemaPSVIIDCBindingPtr bind)
4474{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004475 xmlChar *str = NULL;
4476 const xmlChar *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004477 xmlSchemaPSVIIDCNodePtr tab;
4478 xmlSchemaPSVIIDCKeyPtr key;
4479 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004480
4481 fprintf(output, "IDC: TABLES on %s\n",
4482 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004483 FREE_AND_NULL(str)
4484
4485 if (bind == NULL)
4486 return;
4487 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004488 fprintf(output, "IDC: BINDING %s\n",
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004489 xmlSchemaGetComponentQName(&str,
4490 bind->definition));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004491 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004492 for (i = 0; i < bind->nbNodes; i++) {
4493 tab = bind->nodeTable[i];
4494 fprintf(output, " ( ");
4495 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004496 key = tab->keys[j];
4497 if ((key != NULL) && (key->val != NULL)) {
4498 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004499 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004500 fprintf(output, "\"%s\" ", value);
4501 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004502 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004503 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004504 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004505 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004506 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004507 else
4508 fprintf(output, "(key missing), ");
4509 }
4510 fprintf(output, ")\n");
4511 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004512 if (bind->dupls && bind->dupls->nbItems) {
4513 fprintf(output, "IDC: dupls:\n");
4514 for (i = 0; i < bind->dupls->nbItems; i++) {
4515 tab = bind->dupls->items[i];
4516 fprintf(output, " ( ");
4517 for (j = 0; j < bind->definition->nbFields; j++) {
4518 key = tab->keys[j];
4519 if ((key != NULL) && (key->val != NULL)) {
4520 res = xmlSchemaGetCanonValue(key->val, &value);
4521 if (res >= 0)
4522 fprintf(output, "\"%s\" ", value);
4523 else
4524 fprintf(output, "CANON-VALUE-FAILED ");
4525 if (res == 0)
4526 FREE_AND_NULL(value)
4527 } else if (key != NULL)
4528 fprintf(output, "(no val), ");
4529 else
4530 fprintf(output, "(key missing), ");
4531 }
4532 fprintf(output, ")\n");
4533 }
4534 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004535 bind = bind->next;
4536 } while (bind != NULL);
4537}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00004538#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00004539#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00004540
4541/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004542 * *
4543 * Utilities *
4544 * *
4545 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004546
Daniel Veillardc0826a72004-08-10 14:17:33 +00004547/**
4548 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004549 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00004550 * @name: the name of the attribute
4551 *
4552 * Seeks an attribute with a name of @name in
4553 * no namespace.
4554 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004555 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00004556 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004557static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004558xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00004559{
4560 xmlAttrPtr prop;
4561
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004562 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004563 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004564 prop = node->properties;
4565 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004566 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004567 return(prop);
4568 prop = prop->next;
4569 }
4570 return (NULL);
4571}
4572
4573/**
4574 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004575 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00004576 * @uri: the uri
4577 * @name: the name of the attribute
4578 *
4579 * Seeks an attribute with a local name of @name and
4580 * a namespace URI of @uri.
4581 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004582 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00004583 */
4584static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004585xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00004586{
4587 xmlAttrPtr prop;
4588
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004589 if ((node == NULL) || (name == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004590 return(NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004591 prop = node->properties;
4592 while (prop != NULL) {
4593 if ((prop->ns != NULL) &&
4594 xmlStrEqual(prop->name, BAD_CAST name) &&
4595 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00004596 return(prop);
4597 prop = prop->next;
4598 }
4599 return (NULL);
4600}
4601
4602static const xmlChar *
4603xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4604{
4605 xmlChar *val;
4606 const xmlChar *ret;
4607
4608 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004609 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00004610 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00004611 ret = xmlDictLookup(ctxt->dict, val, -1);
4612 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004613 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004614}
4615
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004616static const xmlChar *
4617xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4618{
4619 return((const xmlChar*) xmlNodeGetContent(node));
4620}
4621
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004622/**
4623 * xmlSchemaGetProp:
4624 * @ctxt: the parser context
4625 * @node: the node
4626 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004627 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004628 * Read a attribute value and internalize the string
4629 *
4630 * Returns the string or NULL if not present.
4631 */
4632static const xmlChar *
4633xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4634 const char *name)
4635{
4636 xmlChar *val;
4637 const xmlChar *ret;
4638
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004639 val = xmlGetNoNsProp(node, BAD_CAST name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004640 if (val == NULL)
4641 return(NULL);
4642 ret = xmlDictLookup(ctxt->dict, val, -1);
4643 xmlFree(val);
4644 return(ret);
4645}
4646
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004647/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00004648 * *
4649 * Parsing functions *
4650 * *
4651 ************************************************************************/
4652
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004653#define WXS_FIND_GLOBAL_ITEM(slot) \
4654 if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4655 ret = xmlHashLookup(schema->slot, name); \
4656 if (ret != NULL) goto exit; \
4657 } \
4658 if (xmlHashSize(schema->schemasImports) > 1) { \
4659 xmlSchemaImportPtr import; \
4660 if (nsName == NULL) \
4661 import = xmlHashLookup(schema->schemasImports, \
4662 XML_SCHEMAS_NO_NAMESPACE); \
4663 else \
4664 import = xmlHashLookup(schema->schemasImports, nsName); \
4665 if (import == NULL) \
4666 goto exit; \
4667 ret = xmlHashLookup(import->schema->slot, name); \
4668 }
4669
Daniel Veillard4255d502002-04-16 15:50:10 +00004670/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004671 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004672 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004673 * @name: the element name
4674 * @ns: the element namespace
4675 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004676 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004677 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004678 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004679 */
4680static xmlSchemaElementPtr
4681xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004682 const xmlChar * nsName)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004683{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004684 xmlSchemaElementPtr ret = NULL;
4685
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004686 if ((name == NULL) || (schema == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004687 return(NULL);
4688 if (schema != NULL) {
4689 WXS_FIND_GLOBAL_ITEM(elemDecl)
4690 }
4691exit:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004692#ifdef DEBUG
4693 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004694 if (nsName == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004695 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004696 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004697 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004698 nsName);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004699 }
4700#endif
4701 return (ret);
4702}
4703
4704/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004705 * xmlSchemaGetType:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004706 * @schema: the main schema
4707 * @name: the type's name
4708 * nsName: the type's namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004709 *
4710 * Lookup a type in the schemas or the predefined types
4711 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004712 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00004713 */
4714static xmlSchemaTypePtr
4715xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004716 const xmlChar * nsName)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004717{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004718 xmlSchemaTypePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004719
4720 if (name == NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004721 return (NULL);
4722 /* First try the built-in types. */
4723 if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4724 ret = xmlSchemaGetPredefinedType(name, nsName);
4725 if (ret != NULL)
4726 goto exit;
4727 /*
4728 * Note that we try the parsed schemas as well here
4729 * since one might have parsed the S4S, which contain more
4730 * than the built-in types.
4731 * TODO: Can we optimize this?
4732 */
4733 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004734 if (schema != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004735 WXS_FIND_GLOBAL_ITEM(typeDecl)
4736 }
4737exit:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004738
Daniel Veillard4255d502002-04-16 15:50:10 +00004739#ifdef DEBUG
4740 if (ret == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004741 if (nsName == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004742 fprintf(stderr, "Unable to lookup type %s", name);
4743 else
4744 fprintf(stderr, "Unable to lookup type %s:%s", name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004745 nsName);
Daniel Veillard4255d502002-04-16 15:50:10 +00004746 }
4747#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004748 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004749}
4750
Daniel Veillard3646d642004-06-02 19:19:14 +00004751/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004752 * xmlSchemaGetAttributeDecl:
4753 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004754 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004755 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004756 *
4757 * Lookup a an attribute in the schema or imported schemas
4758 *
4759 * Returns the attribute declaration or NULL if not found.
4760 */
4761static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004762xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004763 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004764{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004765 xmlSchemaAttributePtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004766
4767 if ((name == NULL) || (schema == NULL))
4768 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004769 if (schema != NULL) {
4770 WXS_FIND_GLOBAL_ITEM(attrDecl)
Daniel Veillard3646d642004-06-02 19:19:14 +00004771 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004772exit:
Daniel Veillard3646d642004-06-02 19:19:14 +00004773#ifdef DEBUG
4774 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004775 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004776 fprintf(stderr, "Unable to lookup attribute %s", name);
4777 else
4778 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004779 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004780 }
4781#endif
4782 return (ret);
4783}
4784
4785/**
4786 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004787 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004788 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004789 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004790 *
4791 * Lookup a an attribute group in the schema or imported schemas
4792 *
4793 * Returns the attribute group definition or NULL if not found.
4794 */
4795static xmlSchemaAttributeGroupPtr
4796xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004797 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004798{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004799 xmlSchemaAttributeGroupPtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004800
4801 if ((name == NULL) || (schema == NULL))
4802 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004803 if (schema != NULL) {
4804 WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4805 }
4806exit:
4807 /* TODO:
4808 if ((ret != NULL) && (ret->redef != NULL)) {
4809 * Return the last redefinition. *
4810 ret = ret->redef;
Daniel Veillard3646d642004-06-02 19:19:14 +00004811 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004812 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004813#ifdef DEBUG
4814 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004815 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004816 fprintf(stderr, "Unable to lookup attribute group %s", name);
4817 else
4818 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004819 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004820 }
4821#endif
4822 return (ret);
4823}
4824
4825/**
4826 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004827 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004828 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004829 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004830 *
4831 * Lookup a group in the schema or imported schemas
4832 *
4833 * Returns the group definition or NULL if not found.
4834 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004835static xmlSchemaModelGroupDefPtr
Daniel Veillard3646d642004-06-02 19:19:14 +00004836xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004837 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004838{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004839 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004840
4841 if ((name == NULL) || (schema == NULL))
4842 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004843 if (schema != NULL) {
4844 WXS_FIND_GLOBAL_ITEM(groupDecl)
Daniel Veillard3646d642004-06-02 19:19:14 +00004845 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004846exit:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004847
Daniel Veillard3646d642004-06-02 19:19:14 +00004848#ifdef DEBUG
4849 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004850 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004851 fprintf(stderr, "Unable to lookup group %s", name);
4852 else
4853 fprintf(stderr, "Unable to lookup group %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004854 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004855 }
4856#endif
4857 return (ret);
4858}
4859
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004860static xmlSchemaNotationPtr
4861xmlSchemaGetNotation(xmlSchemaPtr schema,
4862 const xmlChar *name,
4863 const xmlChar *nsName)
4864{
4865 xmlSchemaNotationPtr ret = NULL;
4866
4867 if ((name == NULL) || (schema == NULL))
4868 return (NULL);
4869 if (schema != NULL) {
4870 WXS_FIND_GLOBAL_ITEM(notaDecl)
4871 }
4872exit:
4873 return (ret);
4874}
4875
4876static xmlSchemaIDCPtr
4877xmlSchemaGetIDC(xmlSchemaPtr schema,
4878 const xmlChar *name,
4879 const xmlChar *nsName)
4880{
4881 xmlSchemaIDCPtr ret = NULL;
4882
4883 if ((name == NULL) || (schema == NULL))
4884 return (NULL);
4885 if (schema != NULL) {
4886 WXS_FIND_GLOBAL_ITEM(idcDef)
4887 }
4888exit:
4889 return (ret);
4890}
4891
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004892/**
4893 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004894 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004895 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004896 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004897 *
4898 * Lookup a group in the schema or imported schemas
4899 *
4900 * Returns the group definition or NULL if not found.
4901 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004902static xmlSchemaBasicItemPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004903xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4904 xmlSchemaTypeType itemType,
4905 const xmlChar *name,
4906 const xmlChar *targetNs)
4907{
4908 switch (itemType) {
4909 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004910 return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004911 name, targetNs));
4912 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004913 return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004914 name, targetNs));
4915 default:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004916 TODO
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004917 return (NULL);
4918 }
4919}
4920
Daniel Veillard4255d502002-04-16 15:50:10 +00004921/************************************************************************
4922 * *
4923 * Parsing functions *
4924 * *
4925 ************************************************************************/
4926
4927#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004928 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00004929
4930/**
4931 * xmlSchemaIsBlank:
4932 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004933 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00004934 *
4935 * Check if a string is ignorable
4936 *
4937 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4938 */
4939static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004940xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004941{
Daniel Veillard4255d502002-04-16 15:50:10 +00004942 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004943 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004944 if (len < 0) {
4945 while (*str != 0) {
4946 if (!(IS_BLANK_CH(*str)))
4947 return (0);
4948 str++;
4949 }
4950 } else while ((*str != 0) && (len != 0)) {
4951 if (!(IS_BLANK_CH(*str)))
4952 return (0);
4953 str++;
4954 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00004955 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004956
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004957 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004958}
4959
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004960#define WXS_COMP_NAME(c, t) ((t) (c))->name
4961#define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
4962/*
4963* xmlSchemaFindRedefCompInGraph:
4964* ATTENTION TODO: This uses pointer comp. for strings.
4965*/
4966static xmlSchemaBasicItemPtr
4967xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
4968 xmlSchemaTypeType type,
4969 const xmlChar *name,
4970 const xmlChar *nsName)
4971{
4972 xmlSchemaBasicItemPtr ret;
4973 int i;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004974
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004975 if ((bucket == NULL) || (name == NULL))
4976 return(NULL);
4977 if ((bucket->globals == NULL) ||
4978 (bucket->globals->nbItems == 0))
4979 goto subschemas;
4980 /*
4981 * Search in global components.
4982 */
4983 for (i = 0; i < bucket->globals->nbItems; i++) {
4984 ret = bucket->globals->items[i];
4985 if (ret->type == type) {
4986 switch (type) {
4987 case XML_SCHEMA_TYPE_COMPLEX:
4988 case XML_SCHEMA_TYPE_SIMPLE:
4989 if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
4990 (WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
4991 nsName))
4992 {
4993 return(ret);
4994 }
4995 break;
4996 case XML_SCHEMA_TYPE_GROUP:
4997 if ((WXS_COMP_NAME(ret,
4998 xmlSchemaModelGroupDefPtr) == name) &&
4999 (WXS_COMP_TNS(ret,
5000 xmlSchemaModelGroupDefPtr) == nsName))
5001 {
5002 return(ret);
5003 }
5004 break;
5005 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5006 if ((WXS_COMP_NAME(ret,
5007 xmlSchemaAttributeGroupPtr) == name) &&
5008 (WXS_COMP_TNS(ret,
5009 xmlSchemaAttributeGroupPtr) == nsName))
5010 {
5011 return(ret);
5012 }
5013 default:
5014 /* Should not be hit. */
5015 return(NULL);
5016 }
5017 }
5018 }
5019subschemas:
5020 /*
5021 * Process imported/included schemas.
5022 */
5023 if (bucket->relations != NULL) {
5024 xmlSchemaSchemaRelationPtr rel = bucket->relations;
5025
5026 /*
5027 * TODO: Marking the bucket will not avoid multiple searches
5028 * in the same schema, but avoids at least circularity.
5029 */
5030 bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5031 do {
5032 if ((rel->bucket != NULL) &&
5033 ((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5034 ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5035 type, name, nsName);
5036 if (ret != NULL)
5037 return(ret);
5038 }
5039 rel = rel->next;
5040 } while (rel != NULL);
5041 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5042 }
5043 return(NULL);
5044}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005045
5046/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005047 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005048 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005049 * @schema: the schema being built
5050 * @name: the item name
5051 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005052 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00005053 * *WARNING* this interface is highly subject to change
5054 *
5055 * Returns the new struture or NULL in case of error
5056 */
5057static xmlSchemaNotationPtr
5058xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005059 const xmlChar *name, const xmlChar *nsName,
5060 xmlNodePtr node ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00005061{
5062 xmlSchemaNotationPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005063
5064 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5065 return (NULL);
5066
Daniel Veillard4255d502002-04-16 15:50:10 +00005067 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5068 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005069 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005070 return (NULL);
5071 }
5072 memset(ret, 0, sizeof(xmlSchemaNotation));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005073 ret->type = XML_SCHEMA_TYPE_NOTATION;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005074 ret->name = name;
5075 ret->targetNamespace = nsName;
5076 /* TODO: do we need the node to be set?
5077 * ret->node = node;*/
5078 WXS_ADD_GLOBAL(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005079 return (ret);
5080}
5081
Daniel Veillard4255d502002-04-16 15:50:10 +00005082/**
5083 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005084 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005085 * @schema: the schema being built
5086 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005087 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005088 *
5089 * Add an XML schema Attrribute declaration
5090 * *WARNING* this interface is highly subject to change
5091 *
5092 * Returns the new struture or NULL in case of error
5093 */
5094static xmlSchemaAttributePtr
5095xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005096 const xmlChar * name, const xmlChar * nsName,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005097 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005098{
5099 xmlSchemaAttributePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005100
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005101 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005102 return (NULL);
5103
5104 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5105 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005106 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005107 return (NULL);
5108 }
5109 memset(ret, 0, sizeof(xmlSchemaAttribute));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005110 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5111 ret->node = node;
5112 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005113 ret->targetNamespace = nsName;
5114
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005115 if (topLevel)
5116 WXS_ADD_GLOBAL(ctxt, ret);
5117 else
5118 WXS_ADD_LOCAL(ctxt, ret);
5119 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005120 return (ret);
5121}
5122
5123/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005124 * xmlSchemaAddAttributeUse:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005125 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005126 * @schema: the schema being built
5127 * @name: the item name
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005128 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005129 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005130 * Add an XML schema Attrribute declaration
5131 * *WARNING* this interface is highly subject to change
5132 *
5133 * Returns the new struture or NULL in case of error
5134 */
5135static xmlSchemaAttributeUsePtr
5136xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5137 xmlNodePtr node)
5138{
5139 xmlSchemaAttributeUsePtr ret = NULL;
5140
5141 if (pctxt == NULL)
5142 return (NULL);
5143
5144 ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5145 if (ret == NULL) {
5146 xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5147 return (NULL);
5148 }
5149 memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5150 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5151 ret->node = node;
5152
5153 WXS_ADD_LOCAL(pctxt, ret);
5154 return (ret);
5155}
5156
5157/*
5158* xmlSchemaAddRedef:
5159*
5160* Adds a redefinition information. This is used at a later stage to:
5161* resolve references to the redefined components and to check constraints.
5162*/
5163static xmlSchemaRedefPtr
5164xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5165 xmlSchemaBucketPtr targetBucket,
5166 void *item,
5167 const xmlChar *refName,
5168 const xmlChar *refTargetNs)
5169{
5170 xmlSchemaRedefPtr ret;
5171
5172 ret = (xmlSchemaRedefPtr)
5173 xmlMalloc(sizeof(xmlSchemaRedef));
5174 if (ret == NULL) {
5175 xmlSchemaPErrMemory(pctxt,
5176 "allocating redefinition info", NULL);
5177 return (NULL);
5178 }
5179 memset(ret, 0, sizeof(xmlSchemaRedef));
5180 ret->item = item;
5181 ret->targetBucket = targetBucket;
5182 ret->refName = refName;
5183 ret->refTargetNs = refTargetNs;
5184 if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5185 WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5186 else
5187 WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5188 WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5189
5190 return (ret);
5191}
5192
5193/**
5194 * xmlSchemaAddAttributeGroupDefinition:
5195 * @ctxt: a schema parser context
5196 * @schema: the schema being built
5197 * @name: the item name
5198 * @nsName: the target namespace
5199 * @node: the corresponding node
5200 *
5201 * Add an XML schema Attrribute Group definition.
Daniel Veillard4255d502002-04-16 15:50:10 +00005202 *
5203 * Returns the new struture or NULL in case of error
5204 */
5205static xmlSchemaAttributeGroupPtr
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005206xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5207 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5208 const xmlChar *name,
5209 const xmlChar *nsName,
5210 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005211{
5212 xmlSchemaAttributeGroupPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005213
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005214 if ((pctxt == NULL) || (name == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005215 return (NULL);
5216
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005217 ret = (xmlSchemaAttributeGroupPtr)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005218 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00005219 if (ret == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005220 xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005221 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005222 }
5223 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005224 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005225 ret->name = name;
5226 ret->targetNamespace = nsName;
5227 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005228
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005229 /* TODO: Remove the flag. */
5230 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5231 if (pctxt->isRedefine) {
5232 pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5233 ret, name, nsName);
5234 if (pctxt->redef == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005235 xmlFree(ret);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005236 return(NULL);
5237 }
5238 pctxt->redefCounter = 0;
5239 }
5240 WXS_ADD_GLOBAL(pctxt, ret);
5241 WXS_ADD_PENDING(pctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005242 return (ret);
5243}
5244
5245/**
5246 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005247 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005248 * @schema: the schema being built
5249 * @name: the type name
5250 * @namespace: the type namespace
5251 *
5252 * Add an XML schema Element declaration
5253 * *WARNING* this interface is highly subject to change
5254 *
5255 * Returns the new struture or NULL in case of error
5256 */
5257static xmlSchemaElementPtr
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005258xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005259 const xmlChar * name, const xmlChar * nsName,
William M. Brack2f2a6632004-08-20 23:09:47 +00005260 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005261{
5262 xmlSchemaElementPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005263
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005264 if ((ctxt == NULL) || (name == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005265 return (NULL);
5266
Daniel Veillard4255d502002-04-16 15:50:10 +00005267 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5268 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005269 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005270 return (NULL);
5271 }
5272 memset(ret, 0, sizeof(xmlSchemaElement));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005273 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5274 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005275 ret->targetNamespace = nsName;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005276 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005277
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005278 if (topLevel)
5279 WXS_ADD_GLOBAL(ctxt, ret);
5280 else
5281 WXS_ADD_LOCAL(ctxt, ret);
5282 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005283 return (ret);
5284}
5285
5286/**
5287 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00005288 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005289 * @schema: the schema being built
5290 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005291 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005292 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005293 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00005294 * *WARNING* this interface is highly subject to change
5295 *
5296 * Returns the new struture or NULL in case of error
5297 */
5298static xmlSchemaTypePtr
5299xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005300 xmlSchemaTypeType type,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00005301 const xmlChar * name, const xmlChar * nsName,
5302 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005303{
5304 xmlSchemaTypePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005305
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005306 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005307 return (NULL);
5308
5309 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5310 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005311 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005312 return (NULL);
5313 }
5314 memset(ret, 0, sizeof(xmlSchemaType));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005315 ret->type = type;
5316 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005317 ret->targetNamespace = nsName;
5318 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005319 if (topLevel) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005320 if (ctxt->isRedefine) {
5321 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5322 ret, name, nsName);
5323 if (ctxt->redef == NULL) {
5324 xmlFree(ret);
5325 return(NULL);
5326 }
5327 ctxt->redefCounter = 0;
5328 }
5329 WXS_ADD_GLOBAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005330 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005331 WXS_ADD_LOCAL(ctxt, ret);
5332 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005333 return (ret);
5334}
5335
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005336static xmlSchemaQNameRefPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005337xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005338 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005339 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005340 const xmlChar *refNs)
5341{
5342 xmlSchemaQNameRefPtr ret;
5343
5344 ret = (xmlSchemaQNameRefPtr)
5345 xmlMalloc(sizeof(xmlSchemaQNameRef));
5346 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005347 xmlSchemaPErrMemory(pctxt,
5348 "allocating QName reference item", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005349 return (NULL);
5350 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005351 ret->node = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005352 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5353 ret->name = refName;
5354 ret->targetNamespace = refNs;
5355 ret->item = NULL;
5356 ret->itemType = refType;
5357 /*
5358 * Store the reference item in the schema.
5359 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005360 WXS_ADD_LOCAL(pctxt, ret);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005361 return (ret);
5362}
5363
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005364static xmlSchemaAttributeUseProhibPtr
5365xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5366{
5367 xmlSchemaAttributeUseProhibPtr ret;
5368
5369 ret = (xmlSchemaAttributeUseProhibPtr)
5370 xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5371 if (ret == NULL) {
5372 xmlSchemaPErrMemory(pctxt,
5373 "allocating attribute use prohibition", NULL);
5374 return (NULL);
5375 }
5376 memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5377 ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5378 WXS_ADD_LOCAL(pctxt, ret);
5379 return (ret);
5380}
5381
5382
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005383/**
5384 * xmlSchemaAddModelGroup:
5385 * @ctxt: a schema parser context
5386 * @schema: the schema being built
5387 * @type: the "compositor" type of the model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005388 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005389 *
5390 * Adds a schema model group
5391 * *WARNING* this interface is highly subject to change
5392 *
5393 * Returns the new struture or NULL in case of error
5394 */
5395static xmlSchemaModelGroupPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005396xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5397 xmlSchemaPtr schema,
5398 xmlSchemaTypeType type,
5399 xmlNodePtr node)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005400{
5401 xmlSchemaModelGroupPtr ret = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005402
5403 if ((ctxt == NULL) || (schema == NULL))
5404 return (NULL);
5405
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005406 ret = (xmlSchemaModelGroupPtr)
5407 xmlMalloc(sizeof(xmlSchemaModelGroup));
5408 if (ret == NULL) {
5409 xmlSchemaPErrMemory(ctxt, "allocating model group component",
5410 NULL);
5411 return (NULL);
5412 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005413 memset(ret, 0, sizeof(xmlSchemaModelGroup));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005414 ret->type = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005415 ret->node = node;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005416 WXS_ADD_LOCAL(ctxt, ret);
5417 if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5418 (type == XML_SCHEMA_TYPE_CHOICE))
5419 WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005420 return (ret);
5421}
5422
5423
5424/**
5425 * xmlSchemaAddParticle:
5426 * @ctxt: a schema parser context
5427 * @schema: the schema being built
5428 * @node: the corresponding node in the schema doc
5429 * @min: the minOccurs
5430 * @max: the maxOccurs
5431 *
5432 * Adds an XML schema particle component.
5433 * *WARNING* this interface is highly subject to change
5434 *
5435 * Returns the new struture or NULL in case of error
5436 */
5437static xmlSchemaParticlePtr
5438xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5439 xmlNodePtr node, int min, int max)
5440{
5441 xmlSchemaParticlePtr ret = NULL;
5442 if ((ctxt == NULL) || (schema == NULL))
5443 return (NULL);
5444
5445#ifdef DEBUG
5446 fprintf(stderr, "Adding particle component\n");
5447#endif
5448 ret = (xmlSchemaParticlePtr)
5449 xmlMalloc(sizeof(xmlSchemaParticle));
5450 if (ret == NULL) {
5451 xmlSchemaPErrMemory(ctxt, "allocating particle component",
5452 NULL);
5453 return (NULL);
5454 }
5455 ret->type = XML_SCHEMA_TYPE_PARTICLE;
5456 ret->annot = NULL;
5457 ret->node = node;
5458 ret->minOccurs = min;
5459 ret->maxOccurs = max;
5460 ret->next = NULL;
5461 ret->children = NULL;
5462
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005463 WXS_ADD_LOCAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005464 /*
5465 * Note that addition to pending components will be done locally
5466 * to the specific parsing function, since the most particles
5467 * need not to be fixed up (i.e. the reference to be resolved).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005468 * REMOVED: WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005469 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005470 return (ret);
5471}
5472
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005473/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005474 * xmlSchemaAddModelGroupDefinition:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005475 * @ctxt: a schema validation context
5476 * @schema: the schema being built
5477 * @name: the group name
5478 *
5479 * Add an XML schema Group definition
5480 *
5481 * Returns the new struture or NULL in case of error
5482 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005483static xmlSchemaModelGroupDefPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005484xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5485 xmlSchemaPtr schema,
5486 const xmlChar *name,
5487 const xmlChar *nsName,
5488 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005489{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005490 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005491
5492 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5493 return (NULL);
5494
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005495 ret = (xmlSchemaModelGroupDefPtr)
5496 xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005497 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005498 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005499 return (NULL);
5500 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005501 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005502 ret->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005503 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005504 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005505 ret->targetNamespace = nsName;
5506
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005507 if (ctxt->isRedefine) {
5508 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5509 ret, name, nsName);
5510 if (ctxt->redef == NULL) {
5511 xmlFree(ret);
5512 return(NULL);
5513 }
5514 ctxt->redefCounter = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005515 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005516 WXS_ADD_GLOBAL(ctxt, ret);
5517 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005518 return (ret);
5519}
5520
Daniel Veillard3646d642004-06-02 19:19:14 +00005521/**
5522 * xmlSchemaNewWildcardNs:
5523 * @ctxt: a schema validation context
5524 *
5525 * Creates a new wildcard namespace constraint.
5526 *
5527 * Returns the new struture or NULL in case of error
5528 */
5529static xmlSchemaWildcardNsPtr
5530xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5531{
5532 xmlSchemaWildcardNsPtr ret;
5533
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005534 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005535 xmlMalloc(sizeof(xmlSchemaWildcardNs));
5536 if (ret == NULL) {
5537 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005538 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00005539 }
5540 ret->value = NULL;
5541 ret->next = NULL;
5542 return (ret);
5543}
5544
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005545static xmlSchemaIDCPtr
5546xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5547 const xmlChar *name, const xmlChar *nsName,
5548 int category, xmlNodePtr node)
5549{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005550 xmlSchemaIDCPtr ret = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005551
5552 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5553 return (NULL);
5554
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005555 ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5556 if (ret == NULL) {
5557 xmlSchemaPErrMemory(ctxt,
5558 "allocating an identity-constraint definition", NULL);
5559 return (NULL);
5560 }
5561 memset(ret, 0, sizeof(xmlSchemaIDC));
5562 /* The target namespace of the parent element declaration. */
5563 ret->targetNamespace = nsName;
5564 ret->name = name;
5565 ret->type = category;
5566 ret->node = node;
5567
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005568 WXS_ADD_GLOBAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005569 /*
5570 * Only keyrefs need to be fixup up.
5571 */
5572 if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005573 WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005574 return (ret);
5575}
5576
Daniel Veillard3646d642004-06-02 19:19:14 +00005577/**
5578 * xmlSchemaAddWildcard:
5579 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005580 * @schema: a schema
5581 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005582 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005583 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00005584 *
5585 * Returns the new struture or NULL in case of error
5586 */
5587static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005588xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5589 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00005590{
5591 xmlSchemaWildcardPtr ret = NULL;
5592
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005593 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00005594 return (NULL);
5595
5596 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5597 if (ret == NULL) {
5598 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5599 return (NULL);
5600 }
5601 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005602 ret->type = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005603 ret->node = node;
5604 WXS_ADD_LOCAL(ctxt, ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00005605 return (ret);
5606}
5607
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005608static void
5609xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5610{
5611 if (group == NULL)
5612 return;
5613 if (group->members != NULL)
5614 xmlSchemaItemListFree(group->members);
5615 xmlFree(group);
5616}
5617
5618static xmlSchemaSubstGroupPtr
5619xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5620 xmlSchemaElementPtr head)
5621{
5622 xmlSchemaSubstGroupPtr ret;
5623
5624 /* Init subst group hash. */
5625 if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5626 WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5627 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5628 return(NULL);
5629 }
5630 /* Create a new substitution group. */
5631 ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5632 if (ret == NULL) {
5633 xmlSchemaPErrMemory(NULL,
5634 "allocating a substitution group container", NULL);
5635 return(NULL);
5636 }
5637 memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5638 ret->head = head;
5639 /* Create list of members. */
5640 ret->members = xmlSchemaItemListCreate();
5641 if (ret->members == NULL) {
5642 xmlSchemaSubstGroupFree(ret);
5643 return(NULL);
5644 }
5645 /* Add subst group to hash. */
5646 if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5647 head->name, head->targetNamespace, ret) != 0) {
5648 PERROR_INT("xmlSchemaSubstGroupAdd",
5649 "failed to add a new substitution container");
5650 xmlSchemaSubstGroupFree(ret);
5651 return(NULL);
5652 }
5653 return(ret);
5654}
5655
5656static xmlSchemaSubstGroupPtr
5657xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5658 xmlSchemaElementPtr head)
5659{
5660 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5661 return(NULL);
5662 return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5663 head->name, head->targetNamespace));
5664
5665}
5666
5667/**
5668 * xmlSchemaAddElementSubstitutionMember:
5669 * @pctxt: a schema parser context
5670 * @head: the head of the substitution group
5671 * @member: the new member of the substitution group
5672 *
5673 * Allocate a new annotation structure.
5674 *
5675 * Returns the newly allocated structure or NULL in case or error
5676 */
5677static int
5678xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5679 xmlSchemaElementPtr head,
5680 xmlSchemaElementPtr member)
5681{
5682 xmlSchemaSubstGroupPtr substGroup = NULL;
5683
5684 if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5685 return (-1);
5686
5687 substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5688 if (substGroup == NULL)
5689 substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5690 if (substGroup == NULL)
5691 return(-1);
5692 if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5693 return(-1);
5694 return(0);
5695}
5696
Daniel Veillard4255d502002-04-16 15:50:10 +00005697/************************************************************************
5698 * *
5699 * Utilities for parsing *
5700 * *
5701 ************************************************************************/
5702
Daniel Veillard4255d502002-04-16 15:50:10 +00005703/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005704 * xmlSchemaPValAttrNodeQNameValue:
5705 * @ctxt: a schema parser context
5706 * @schema: the schema context
5707 * @ownerDes: the designation of the parent element
5708 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005709 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00005710 * @local: the resulting local part if found, the attribute value otherwise
5711 * @uri: the resulting namespace URI if found
5712 *
5713 * Extracts the local name and the URI of a QName value and validates it.
5714 * This one is intended to be used on attribute values that
5715 * should resolve to schema components.
5716 *
5717 * Returns 0, in case the QName is valid, a positive error code
5718 * if not valid and -1 if an internal error occurs.
5719 */
5720static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005721xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005722 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005723 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005724 xmlAttrPtr attr,
5725 const xmlChar *value,
5726 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005727 const xmlChar **local)
5728{
5729 const xmlChar *pref;
5730 xmlNsPtr ns;
5731 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005732
Daniel Veillardc0826a72004-08-10 14:17:33 +00005733 *uri = NULL;
5734 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005735 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005736 if (ret > 0) {
5737 xmlSchemaPSimpleTypeErr(ctxt,
5738 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5739 ownerItem, (xmlNodePtr) attr,
5740 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5741 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005742 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005743 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005744 } else if (ret < 0)
5745 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005746
5747 if (!strchr((char *) value, ':')) {
Daniel Veillard24505b02005-07-28 23:49:35 +00005748 ns = xmlSearchNs(attr->doc, attr->parent, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005749 if (ns)
5750 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5751 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005752 /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5753 * parser context. */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005754 /*
5755 * This one takes care of included schemas with no
5756 * target namespace.
5757 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005758 *uri = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005759 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005760 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005761 return (0);
5762 }
5763 /*
5764 * At this point xmlSplitQName3 has to return a local name.
5765 */
5766 *local = xmlSplitQName3(value, &len);
5767 *local = xmlDictLookup(ctxt->dict, *local, -1);
5768 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005769 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5770 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005771 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005772 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005773 ownerItem, (xmlNodePtr) attr,
5774 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5775 "The value '%s' of simple type 'xs:QName' has no "
5776 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005777 return (ctxt->err);
5778 } else {
5779 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005780 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005781 return (0);
5782}
5783
5784/**
5785 * xmlSchemaPValAttrNodeQName:
5786 * @ctxt: a schema parser context
5787 * @schema: the schema context
5788 * @ownerDes: the designation of the owner element
5789 * @ownerItem: the owner as a schema object
5790 * @attr: the attribute node
5791 * @local: the resulting local part if found, the attribute value otherwise
5792 * @uri: the resulting namespace URI if found
5793 *
5794 * Extracts and validates the QName of an attribute value.
5795 * This one is intended to be used on attribute values that
5796 * should resolve to schema components.
5797 *
5798 * Returns 0, in case the QName is valid, a positive error code
5799 * if not valid and -1 if an internal error occurs.
5800 */
5801static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005802xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005803 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005804 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005805 xmlAttrPtr attr,
5806 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005807 const xmlChar **local)
5808{
5809 const xmlChar *value;
5810
5811 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005812 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005813 ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005814}
5815
5816/**
5817 * xmlSchemaPValAttrQName:
5818 * @ctxt: a schema parser context
5819 * @schema: the schema context
5820 * @ownerDes: the designation of the parent element
5821 * @ownerItem: the owner as a schema object
5822 * @ownerElem: the parent node of the attribute
5823 * @name: the name of the attribute
5824 * @local: the resulting local part if found, the attribute value otherwise
5825 * @uri: the resulting namespace URI if found
5826 *
5827 * Extracts and validates the QName of an attribute value.
5828 *
5829 * Returns 0, in case the QName is valid, a positive error code
5830 * if not valid and -1 if an internal error occurs.
5831 */
5832static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005833xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5834 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005835 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005836 xmlNodePtr ownerElem,
5837 const char *name,
5838 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005839 const xmlChar **local)
5840{
5841 xmlAttrPtr attr;
5842
5843 attr = xmlSchemaGetPropNode(ownerElem, name);
5844 if (attr == NULL) {
5845 *local = NULL;
5846 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005847 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005848 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005849 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005850 ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005851}
5852
5853/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005854 * xmlSchemaPValAttrID:
5855 * @ctxt: a schema parser context
5856 * @schema: the schema context
5857 * @ownerDes: the designation of the parent element
5858 * @ownerItem: the owner as a schema object
5859 * @ownerElem: the parent node of the attribute
5860 * @name: the name of the attribute
5861 *
5862 * Extracts and validates the ID of an attribute value.
5863 *
5864 * Returns 0, in case the ID is valid, a positive error code
5865 * if not valid and -1 if an internal error occurs.
5866 */
5867static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005868xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005869{
5870 int ret;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005871 const xmlChar *value;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005872
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005873 if (attr == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005874 return(0);
5875 value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5876 ret = xmlValidateNCName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005877 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005878 /*
5879 * NOTE: the IDness might have already be declared in the DTD
5880 */
5881 if (attr->atype != XML_ATTRIBUTE_ID) {
5882 xmlIDPtr res;
5883 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005884
5885 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005886 * TODO: Use xmlSchemaStrip here; it's not exported at this
5887 * moment.
5888 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005889 strip = xmlSchemaCollapseString(value);
5890 if (strip != NULL) {
5891 xmlFree((xmlChar *) value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005892 value = strip;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005893 }
5894 res = xmlAddID(NULL, attr->doc, value, attr);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005895 if (res == NULL) {
5896 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005897 xmlSchemaPSimpleTypeErr(ctxt,
5898 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005899 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005900 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5901 NULL, NULL, "Duplicate value '%s' of simple "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005902 "type 'xs:ID'", value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005903 } else
5904 attr->atype = XML_ATTRIBUTE_ID;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005905 }
5906 } else if (ret > 0) {
5907 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005908 xmlSchemaPSimpleTypeErr(ctxt,
5909 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005910 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005911 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5912 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5913 "not a valid 'xs:NCName'",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005914 value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005915 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005916 if (value != NULL)
5917 xmlFree((xmlChar *)value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005918
5919 return (ret);
5920}
5921
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005922static int
5923xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5924 xmlNodePtr ownerElem,
5925 const xmlChar *name)
5926{
5927 xmlAttrPtr attr;
5928
5929 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5930 if (attr == NULL)
5931 return(0);
5932 return(xmlSchemaPValAttrNodeID(ctxt, attr));
5933
5934}
5935
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005936/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005937 * xmlGetMaxOccurs:
5938 * @ctxt: a schema validation context
5939 * @node: a subtree containing XML Schema informations
5940 *
5941 * Get the maxOccurs property
5942 *
5943 * Returns the default if not found, or the value
5944 */
5945static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005946xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5947 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005948{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005949 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005950 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005951 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005952
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005953 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5954 if (attr == NULL)
5955 return (def);
5956 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005957
5958 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005959 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005960 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005961 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5962 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005963 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005964 val, NULL, NULL, NULL);
5965 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005966 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005967 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005968 }
5969
5970 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005971 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005972 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005973 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005974 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005975 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5976 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005977 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005978 val, NULL, NULL, NULL);
5979 return (def);
5980 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005981 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005982 ret = ret * 10 + (*cur - '0');
5983 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005984 }
William M. Brack76e95df2003-10-18 16:20:14 +00005985 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005986 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005987 /*
5988 * TODO: Restrict the maximal value to Integer.
5989 */
5990 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005991 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005992 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5993 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005994 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005995 val, NULL, NULL, NULL);
5996 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005997 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005998 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005999}
6000
6001/**
6002 * xmlGetMinOccurs:
6003 * @ctxt: a schema validation context
6004 * @node: a subtree containing XML Schema informations
6005 *
6006 * Get the minOccurs property
6007 *
6008 * Returns the default if not found, or the value
6009 */
6010static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006011xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006012 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006013{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006014 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00006015 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006016 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006017
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006018 attr = xmlSchemaGetPropNode(node, "minOccurs");
6019 if (attr == NULL)
6020 return (def);
6021 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00006022 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00006023 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006024 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006025 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006026 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006027 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6028 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006029 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006030 val, NULL, NULL, NULL);
6031 return (def);
6032 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006033 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006034 ret = ret * 10 + (*cur - '0');
6035 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00006036 }
William M. Brack76e95df2003-10-18 16:20:14 +00006037 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006038 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006039 /*
6040 * TODO: Restrict the maximal value to Integer.
6041 */
6042 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006043 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006044 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6045 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006046 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006047 val, NULL, NULL, NULL);
6048 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006049 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006050 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006051}
6052
6053/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006054 * xmlSchemaPGetBoolNodeValue:
6055 * @ctxt: a schema validation context
6056 * @ownerDes: owner designation
6057 * @ownerItem: the owner as a schema item
6058 * @node: the node holding the value
6059 *
6060 * Converts a boolean string value into 1 or 0.
6061 *
6062 * Returns 0 or 1.
6063 */
6064static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006065xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006066 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006067 xmlNodePtr node)
6068{
6069 xmlChar *value = NULL;
6070 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006071
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006072 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006073 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006074 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006075 * An instance of a datatype that is defined as ·boolean·
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006076 * can have the following legal literals {true, false, 1, 0}.
6077 */
6078 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6079 res = 1;
6080 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6081 res = 0;
6082 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6083 res = 1;
6084 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006085 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006086 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006087 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006088 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006089 ownerItem, node,
6090 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6091 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006092 NULL, NULL, NULL);
6093 }
6094 if (value != NULL)
6095 xmlFree(value);
6096 return (res);
6097}
6098
6099/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006100 * xmlGetBooleanProp:
6101 * @ctxt: a schema validation context
6102 * @node: a subtree containing XML Schema informations
6103 * @name: the attribute name
6104 * @def: the default value
6105 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006106 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00006107 *
6108 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006109 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00006110 */
6111static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006112xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006113 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006114 const char *name, int def)
6115{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006116 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00006117
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006118 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006119 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006120 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006121 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006122 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006123 * An instance of a datatype that is defined as ·boolean·
Daniel Veillardc0826a72004-08-10 14:17:33 +00006124 * can have the following legal literals {true, false, 1, 0}.
6125 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006126 if (xmlStrEqual(val, BAD_CAST "true"))
6127 def = 1;
6128 else if (xmlStrEqual(val, BAD_CAST "false"))
6129 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006130 else if (xmlStrEqual(val, BAD_CAST "1"))
6131 def = 1;
6132 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006133 def = 0;
6134 else {
6135 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006136 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006137 NULL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006138 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006139 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6140 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006141 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006142 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006143}
6144
6145/************************************************************************
6146 * *
6147 * Shema extraction from an Infoset *
6148 * *
6149 ************************************************************************/
6150static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6151 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006152 xmlNodePtr node,
6153 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006154static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6155 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00006156 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006157 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00006158 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006159static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6160 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00006161 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006162 xmlNodePtr node,
6163 xmlSchemaTypeType parentType);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006164static xmlSchemaBasicItemPtr
6165xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6166 xmlSchemaPtr schema,
6167 xmlNodePtr node,
6168 xmlSchemaItemListPtr uses,
6169 int parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00006170static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6171 xmlSchemaPtr schema,
6172 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00006173static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006174xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6175 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006176
6177/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006178 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006179 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00006180 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00006181 * @ownerDes: the designation of the parent element
6182 * @ownerItem: the schema object owner if existent
6183 * @attr: the schema attribute node being validated
6184 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006185 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00006186 *
6187 * Validates a value against the given built-in type.
6188 * This one is intended to be used internally for validation
6189 * of schema attribute values during parsing of the schema.
6190 *
6191 * Returns 0 if the value is valid, a positive error code
6192 * number otherwise and -1 in case of an internal or API error.
6193 */
6194static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006195xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006196 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006197 xmlAttrPtr attr,
6198 const xmlChar *value,
6199 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00006200{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006201
6202 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006203
6204 /*
6205 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6206 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006207 */
6208 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00006209 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006210 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6211 PERROR_INT("xmlSchemaPValAttrNodeValue",
6212 "the given type is not a built-in type");
6213 return (-1);
6214 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006215 switch (type->builtInType) {
6216 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006217 case XML_SCHEMAS_QNAME:
6218 case XML_SCHEMAS_ANYURI:
6219 case XML_SCHEMAS_TOKEN:
6220 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006221 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6222 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006223 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006224 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006225 PERROR_INT("xmlSchemaPValAttrNodeValue",
6226 "validation using the given type is not supported");
Daniel Veillard01fa6152004-06-29 17:04:39 +00006227 return (-1);
6228 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006229 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006230 /*
6231 * TODO: Should we use the S4S error codes instead?
6232 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006233 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006234 PERROR_INT("xmlSchemaPValAttrNodeValue",
6235 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006236 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006237 } else if (ret > 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006238 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006239 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6240 else
6241 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6242 xmlSchemaPSimpleTypeErr(pctxt,
6243 ret, ownerItem, (xmlNodePtr) attr,
6244 type, NULL, value, NULL, NULL, NULL);
6245 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006246 return (ret);
6247}
6248
6249/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006250 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006251 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006252 * @ctxt: a schema parser context
6253 * @ownerDes: the designation of the parent element
6254 * @ownerItem: the schema object owner if existent
6255 * @attr: the schema attribute node being validated
6256 * @type: the built-in type to be validated against
6257 * @value: the resulting value if any
6258 *
6259 * Extracts and validates a value against the given built-in type.
6260 * This one is intended to be used internally for validation
6261 * of schema attribute values during parsing of the schema.
6262 *
6263 * Returns 0 if the value is valid, a positive error code
6264 * number otherwise and -1 in case of an internal or API error.
6265 */
6266static int
6267xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006268 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006269 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006270 xmlSchemaTypePtr type,
6271 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006272{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006273 const xmlChar *val;
6274
6275 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006276 return (-1);
6277
Daniel Veillardc0826a72004-08-10 14:17:33 +00006278 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6279 if (value != NULL)
6280 *value = val;
6281
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006282 return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006283 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00006284}
6285
6286/**
6287 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006288 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006289 * @ctxt: a schema parser context
6290 * @node: the element node of the attribute
6291 * @ownerDes: the designation of the parent element
6292 * @ownerItem: the schema object owner if existent
6293 * @ownerElem: the owner element node
6294 * @name: the name of the schema attribute node
6295 * @type: the built-in type to be validated against
6296 * @value: the resulting value if any
6297 *
6298 * Extracts and validates a value against the given built-in type.
6299 * This one is intended to be used internally for validation
6300 * of schema attribute values during parsing of the schema.
6301 *
6302 * Returns 0 if the value is valid, a positive error code
6303 * number otherwise and -1 in case of an internal or API error.
6304 */
6305static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006306xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6307 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006308 xmlNodePtr ownerElem,
6309 const char *name,
6310 xmlSchemaTypePtr type,
6311 const xmlChar **value)
6312{
6313 xmlAttrPtr attr;
6314
6315 if ((ctxt == NULL) || (type == NULL)) {
6316 if (value != NULL)
6317 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006318 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006319 }
6320 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6321 if (value != NULL)
6322 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006323 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006324 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006325 "Internal error: xmlSchemaPValAttr, the given "
6326 "type '%s' is not a built-in type.\n",
6327 type->name, NULL);
6328 return (-1);
6329 }
6330 attr = xmlSchemaGetPropNode(ownerElem, name);
6331 if (attr == NULL) {
6332 if (value != NULL)
6333 *value = NULL;
6334 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006335 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006336 return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006337 type, value));
6338}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006339
6340static int
6341xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006342 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006343 xmlNodePtr node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006344 xmlAttrPtr attr,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006345 const xmlChar *namespaceName)
6346{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006347 /* TODO: Pointer comparison instead? */
6348 if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006349 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006350 if (xmlStrEqual(xmlSchemaNs, namespaceName))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006351 return (0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006352 /*
6353 * Check if the referenced namespace was <import>ed.
6354 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006355 if (WXS_BUCKET(pctxt)->relations != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006356 xmlSchemaSchemaRelationPtr rel;
6357
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006358 rel = WXS_BUCKET(pctxt)->relations;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006359 do {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006360 if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006361 xmlStrEqual(namespaceName, rel->importNamespace))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006362 return (0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006363 rel = rel->next;
6364 } while (rel != NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006365 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006366 /*
6367 * No matching <import>ed namespace found.
6368 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006369 {
6370 xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6371
6372 if (namespaceName == NULL)
6373 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6374 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6375 "References from this schema to components in no "
6376 "namespace are not allowed, since not indicated by an "
6377 "import statement", NULL, NULL);
6378 else
6379 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6380 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6381 "References from this schema to components in the "
6382 "namespace '%s' are not allowed, since not indicated by an "
6383 "import statement", namespaceName, NULL);
6384 }
6385 return (XML_SCHEMAP_SRC_RESOLVE);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006386}
6387
Daniel Veillardc0826a72004-08-10 14:17:33 +00006388/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006389 * xmlSchemaParseLocalAttributes:
Daniel Veillard4255d502002-04-16 15:50:10 +00006390 * @ctxt: a schema validation context
6391 * @schema: the schema being built
6392 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006393 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00006394 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006395 * Parses attribute uses and attribute declarations and
6396 * attribute group references.
Daniel Veillard4255d502002-04-16 15:50:10 +00006397 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006398static int
6399xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6400 xmlNodePtr *child, xmlSchemaItemListPtr *list,
6401 int parentType, int *hasRefs)
Daniel Veillard4255d502002-04-16 15:50:10 +00006402{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006403 void *item;
Daniel Veillard4255d502002-04-16 15:50:10 +00006404
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006405 while ((IS_SCHEMA((*child), "attribute")) ||
6406 (IS_SCHEMA((*child), "attributeGroup"))) {
6407 if (IS_SCHEMA((*child), "attribute")) {
6408 item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6409 *list, parentType);
6410 } else {
6411 item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6412 if ((item != NULL) && (hasRefs != NULL))
6413 *hasRefs = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006414 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006415 if (item != NULL) {
6416 if (*list == NULL) {
6417 /* TODO: Customize grow factor. */
6418 *list = xmlSchemaItemListCreate();
6419 if (*list == NULL)
6420 return(-1);
6421 }
6422 if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6423 return(-1);
6424 }
6425 *child = (*child)->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006426 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006427 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006428}
6429
6430/**
6431 * xmlSchemaParseAnnotation:
6432 * @ctxt: a schema validation context
6433 * @schema: the schema being built
6434 * @node: a subtree containing XML Schema informations
6435 *
6436 * parse a XML schema Attrribute declaration
6437 * *WARNING* this interface is highly subject to change
6438 *
William M. Bracke7091952004-05-11 15:09:58 +00006439 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006440 * 1 in case of success.
6441 */
6442static xmlSchemaAnnotPtr
6443xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006444 xmlNodePtr node, int needed)
Daniel Veillard4255d502002-04-16 15:50:10 +00006445{
6446 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006447 xmlNodePtr child = NULL;
6448 xmlAttrPtr attr;
6449 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00006450
Daniel Veillardc0826a72004-08-10 14:17:33 +00006451 /*
6452 * INFO: S4S completed.
6453 */
6454 /*
6455 * id = ID
6456 * {any attributes with non-schema namespace . . .}>
6457 * Content: (appinfo | documentation)*
6458 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006459 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6460 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006461 if (needed)
6462 ret = xmlSchemaNewAnnot(ctxt, node);
6463 else
6464 ret = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006465 attr = node->properties;
6466 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006467 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006468 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006469 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006470 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006471
6472 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006473 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006474 }
6475 attr = attr->next;
6476 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006477 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006478 /*
6479 * And now for the children...
6480 */
6481 child = node->children;
6482 while (child != NULL) {
6483 if (IS_SCHEMA(child, "appinfo")) {
6484 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006485 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006486 * source = anyURI
6487 * {any attributes with non-schema namespace . . .}>
6488 * Content: ({any})*
6489 */
6490 attr = child->properties;
6491 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006492 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006493 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006494 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006495 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006496
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006497 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006498 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006499 }
6500 attr = attr->next;
6501 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006502 xmlSchemaPValAttr(ctxt, NULL, child, "source",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006503 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006504 child = child->next;
6505 } else if (IS_SCHEMA(child, "documentation")) {
6506 /* TODO: make available the content of "documentation". */
6507 /*
6508 * source = anyURI
6509 * {any attributes with non-schema namespace . . .}>
6510 * Content: ({any})*
6511 */
6512 attr = child->properties;
6513 while (attr != NULL) {
6514 if (attr->ns == NULL) {
6515 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006516 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006517 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006518 }
6519 } else {
6520 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6521 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
6522 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006523
6524 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006525 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006526 }
6527 }
6528 attr = attr->next;
6529 }
6530 /*
6531 * Attribute "xml:lang".
6532 */
6533 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6534 if (attr != NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006535 xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006536 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006537 child = child->next;
6538 } else {
6539 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006540 xmlSchemaPContentErr(ctxt,
6541 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006542 NULL, node, child, NULL, "(appinfo | documentation)*");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006543 barked = 1;
6544 child = child->next;
6545 }
6546 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006547
Daniel Veillard4255d502002-04-16 15:50:10 +00006548 return (ret);
6549}
6550
6551/**
6552 * xmlSchemaParseFacet:
6553 * @ctxt: a schema validation context
6554 * @schema: the schema being built
6555 * @node: a subtree containing XML Schema informations
6556 *
6557 * parse a XML schema Facet declaration
6558 * *WARNING* this interface is highly subject to change
6559 *
6560 * Returns the new type structure or NULL in case of error
6561 */
6562static xmlSchemaFacetPtr
6563xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006564 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006565{
6566 xmlSchemaFacetPtr facet;
6567 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006568 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00006569
6570 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6571 return (NULL);
6572
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006573 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006574 if (facet == NULL) {
6575 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6576 return (NULL);
6577 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006578 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006579 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00006580 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006581 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6582 "Facet %s has no value\n", node->name, NULL);
6583 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00006584 return (NULL);
6585 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006586 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006587 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006588 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006589 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006590 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006591 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006592 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006593 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006594 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006595 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006596 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006597 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006598 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006599 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006600 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006601 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006602 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006603 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006604 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006605 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006606 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006607 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6608 } else if (IS_SCHEMA(node, "minLength")) {
6609 facet->type = XML_SCHEMA_FACET_MINLENGTH;
6610 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006611 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6612 "Unknown facet type %s\n", node->name, NULL);
6613 xmlSchemaFreeFacet(facet);
6614 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006615 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006616 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006617 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006618 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6619 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6620 const xmlChar *fixed;
6621
6622 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6623 if (fixed != NULL) {
6624 if (xmlStrEqual(fixed, BAD_CAST "true"))
6625 facet->fixed = 1;
6626 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006627 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006628 child = node->children;
6629
6630 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006631 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006632 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006633 }
6634 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006635 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6636 "Facet %s has unexpected child content\n",
6637 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006638 }
6639 return (facet);
6640}
6641
6642/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006643 * xmlSchemaParseWildcardNs:
6644 * @ctxt: a schema parser context
6645 * @wildc: the wildcard, already created
6646 * @node: a subtree containing XML Schema informations
6647 *
6648 * Parses the attribute "processContents" and "namespace"
6649 * of a xsd:anyAttribute and xsd:any.
6650 * *WARNING* this interface is highly subject to change
6651 *
6652 * Returns 0 if everything goes fine, a positive error code
6653 * if something is not valid and -1 if an internal error occurs.
6654 */
6655static int
6656xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006657 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006658 xmlSchemaWildcardPtr wildc,
6659 xmlNodePtr node)
6660{
6661 const xmlChar *pc, *ns, *dictnsItem;
6662 int ret = 0;
6663 xmlChar *nsItem;
6664 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6665 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006666
Daniel Veillardc0826a72004-08-10 14:17:33 +00006667 pc = xmlSchemaGetProp(ctxt, node, "processContents");
6668 if ((pc == NULL)
6669 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6670 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6671 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6672 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6673 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6674 wildc->processContents = XML_SCHEMAS_ANY_LAX;
6675 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006676 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006677 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006678 NULL, node,
6679 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006680 NULL, NULL, NULL);
6681 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006682 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006683 }
6684 /*
6685 * Build the namespace constraints.
6686 */
6687 attr = xmlSchemaGetPropNode(node, "namespace");
6688 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006689 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00006690 wildc->any = 1;
6691 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6692 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006693 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006694 return (-1);
6695 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006696 wildc->negNsSet->value = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006697 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006698 const xmlChar *end, *cur;
6699
6700 cur = ns;
6701 do {
6702 while (IS_BLANK_CH(*cur))
6703 cur++;
6704 end = cur;
6705 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6706 end++;
6707 if (end == cur)
6708 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006709 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006710 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6711 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006712 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006713 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006714 NULL, (xmlNodePtr) attr,
6715 NULL,
6716 "((##any | ##other) | List of (xs:anyURI | "
6717 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006718 nsItem, NULL, NULL, NULL);
6719 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6720 } else {
6721 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006722 dictnsItem = ctxt->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006723 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6724 dictnsItem = NULL;
6725 } else {
6726 /*
6727 * Validate the item (anyURI).
6728 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006729 xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006730 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6731 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6732 }
6733 /*
6734 * Avoid dublicate namespaces.
6735 */
6736 tmp = wildc->nsSet;
6737 while (tmp != NULL) {
6738 if (dictnsItem == tmp->value)
6739 break;
6740 tmp = tmp->next;
6741 }
6742 if (tmp == NULL) {
6743 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6744 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006745 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006746 return (-1);
6747 }
6748 tmp->value = dictnsItem;
6749 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006750 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006751 wildc->nsSet = tmp;
6752 else
6753 lastNs->next = tmp;
6754 lastNs = tmp;
6755 }
6756
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006757 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006758 xmlFree(nsItem);
6759 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006760 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006761 }
6762 return (ret);
6763}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006764
6765static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006766xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6767 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006768 xmlNodePtr node,
6769 int minOccurs,
6770 int maxOccurs) {
6771
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006772 if ((maxOccurs == 0) && ( minOccurs == 0))
6773 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006774 if (maxOccurs != UNBOUNDED) {
6775 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006776 * TODO: Maybe we should better not create the particle,
6777 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006778 * content model.
6779 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006780 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006781 * 3.9.6 Schema Component Constraint: Particle Correct
6782 *
6783 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006784 if (maxOccurs < 1) {
6785 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006786 * 2.2 {max occurs} must be greater than or equal to 1.
6787 */
6788 xmlSchemaPCustomAttrErr(ctxt,
6789 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006790 NULL, NULL,
6791 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006792 "The value must be greater than or equal to 1");
6793 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6794 } else if (minOccurs > maxOccurs) {
6795 /*
6796 * 2.1 {min occurs} must not be greater than {max occurs}.
6797 */
6798 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006799 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006800 NULL, NULL,
6801 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006802 "The value must not be greater than the value of 'maxOccurs'");
6803 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6804 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006805 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006806 return (0);
6807}
6808
Daniel Veillardc0826a72004-08-10 14:17:33 +00006809/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006810 * xmlSchemaParseAny:
6811 * @ctxt: a schema validation context
6812 * @schema: the schema being built
6813 * @node: a subtree containing XML Schema informations
6814 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006815 * Parsea a XML schema <any> element. A particle and wildcard
6816 * will be created (except if minOccurs==maxOccurs==0, in this case
6817 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006818 * *WARNING* this interface is highly subject to change
6819 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006820 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006821 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006822static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006823xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6824 xmlNodePtr node)
6825{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006826 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006827 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006828 xmlSchemaWildcardPtr wild;
6829 int min, max;
6830 xmlAttrPtr attr;
6831 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006832
6833 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6834 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006835 /*
6836 * Check for illegal attributes.
6837 */
6838 attr = node->properties;
6839 while (attr != NULL) {
6840 if (attr->ns == NULL) {
6841 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6842 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6843 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6844 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6845 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006846 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006847 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006848 }
6849 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006850 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006851 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006852 }
6853 attr = attr->next;
6854 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006855 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006856 /*
6857 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006858 */
6859 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6860 "(xs:nonNegativeInteger | unbounded)");
6861 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6862 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006863 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6864 /*
6865 * Create & parse the wildcard.
6866 */
6867 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6868 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006869 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006870 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006871 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006872 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006873 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006874 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006875 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006876 annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006877 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006878 }
6879 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006880 xmlSchemaPContentErr(ctxt,
6881 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006882 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006883 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006884 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006885 /*
6886 * No component if minOccurs==maxOccurs==0.
6887 */
6888 if ((min == 0) && (max == 0)) {
6889 /* Don't free the wildcard, since it's already on the list. */
6890 return (NULL);
6891 }
6892 /*
6893 * Create the particle.
6894 */
6895 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6896 if (particle == NULL)
6897 return (NULL);
6898 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006899 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006900
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006901 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006902}
6903
6904/**
6905 * xmlSchemaParseNotation:
6906 * @ctxt: a schema validation context
6907 * @schema: the schema being built
6908 * @node: a subtree containing XML Schema informations
6909 *
6910 * parse a XML schema Notation declaration
6911 *
6912 * Returns the new structure or NULL in case of error
6913 */
6914static xmlSchemaNotationPtr
6915xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006916 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006917{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006918 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006919 xmlSchemaNotationPtr ret;
6920 xmlNodePtr child = NULL;
6921
6922 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6923 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006924 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006925 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006926 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6927 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006928 return (NULL);
6929 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006930 ret = xmlSchemaAddNotation(ctxt, schema, name,
6931 ctxt->targetNamespace, node);
6932 if (ret == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00006933 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006934 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006935
6936 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006937 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006938 child = child->next;
6939 }
6940
Daniel Veillard4255d502002-04-16 15:50:10 +00006941 child = node->children;
6942 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006943 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006944 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006945 }
6946 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006947 xmlSchemaPContentErr(ctxt,
6948 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006949 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006950 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006951 }
6952
6953 return (ret);
6954}
6955
6956/**
6957 * xmlSchemaParseAnyAttribute:
6958 * @ctxt: a schema validation context
6959 * @schema: the schema being built
6960 * @node: a subtree containing XML Schema informations
6961 *
6962 * parse a XML schema AnyAttrribute declaration
6963 * *WARNING* this interface is highly subject to change
6964 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006965 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006966 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006967static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006968xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6969 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006970{
Daniel Veillard3646d642004-06-02 19:19:14 +00006971 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006972 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006973 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006974
6975 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6976 return (NULL);
6977
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006978 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6979 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006980 if (ret == NULL) {
6981 return (NULL);
6982 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006983 /*
6984 * Check for illegal attributes.
6985 */
6986 attr = node->properties;
6987 while (attr != NULL) {
6988 if (attr->ns == NULL) {
6989 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6990 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6991 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006992 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006993 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006994 }
6995 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006996 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006997 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006998 }
6999 attr = attr->next;
7000 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007001 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007002 /*
7003 * Parse the namespace list.
7004 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007005 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007006 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007007 /*
7008 * And now for the children...
7009 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007010 child = node->children;
7011 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007012 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007013 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007014 }
7015 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007016 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007017 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007018 NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007019 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007020 }
7021
7022 return (ret);
7023}
7024
7025
7026/**
7027 * xmlSchemaParseAttribute:
7028 * @ctxt: a schema validation context
7029 * @schema: the schema being built
7030 * @node: a subtree containing XML Schema informations
7031 *
7032 * parse a XML schema Attrribute declaration
7033 * *WARNING* this interface is highly subject to change
7034 *
William M. Bracke7091952004-05-11 15:09:58 +00007035 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007036 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007037static xmlSchemaBasicItemPtr
7038xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7039 xmlSchemaPtr schema,
7040 xmlNodePtr node,
7041 xmlSchemaItemListPtr uses,
7042 int parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00007043{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007044 const xmlChar *attrValue, *name = NULL, *ns = NULL;
7045 xmlSchemaAttributeUsePtr use = NULL;
7046 xmlNodePtr child = NULL;
7047 xmlAttrPtr attr;
7048 const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7049 int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7050 int nberrors, hasForm = 0, defValueType = 0;
7051
7052#define WXS_ATTR_DEF_VAL_DEFAULT 1
7053#define WXS_ATTR_DEF_VAL_FIXED 2
7054
7055 /*
7056 * 3.2.3 Constraints on XML Representations of Attribute Declarations
7057 */
7058
7059 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7060 return (NULL);
7061 attr = xmlSchemaGetPropNode(node, "ref");
7062 if (attr != NULL) {
7063 if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7064 NULL, attr, &tmpNs, &tmpName) != 0) {
7065 return (NULL);
7066 }
7067 if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7068 return(NULL);
7069 isRef = 1;
7070 }
7071 nberrors = pctxt->nberrors;
7072 /*
7073 * Check for illegal attributes.
7074 */
7075 attr = node->properties;
7076 while (attr != NULL) {
7077 if (attr->ns == NULL) {
7078 if (isRef) {
7079 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7080 xmlSchemaPValAttrNodeID(pctxt, attr);
7081 goto attr_next;
7082 } else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7083 goto attr_next;
7084 }
7085 } else {
7086 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7087 goto attr_next;
7088 } else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7089 xmlSchemaPValAttrNodeID(pctxt, attr);
7090 goto attr_next;
7091 } else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7092 xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7093 attr, &tmpNs, &tmpName);
7094 goto attr_next;
7095 } else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7096 /*
7097 * Evaluate the target namespace
7098 */
7099 hasForm = 1;
7100 attrValue = xmlSchemaGetNodeContent(pctxt,
7101 (xmlNodePtr) attr);
7102 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7103 ns = pctxt->targetNamespace;
7104 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7105 {
7106 xmlSchemaPSimpleTypeErr(pctxt,
7107 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7108 NULL, (xmlNodePtr) attr,
7109 NULL, "(qualified | unqualified)",
7110 attrValue, NULL, NULL, NULL);
7111 }
7112 goto attr_next;
7113 }
7114 }
7115 if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7116
7117 attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7118 /* TODO: Maybe we need to normalize the value beforehand. */
7119 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7120 occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7121 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7122 occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7123 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7124 occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7125 else {
7126 xmlSchemaPSimpleTypeErr(pctxt,
7127 XML_SCHEMAP_INVALID_ATTR_USE,
7128 NULL, (xmlNodePtr) attr,
7129 NULL, "(optional | prohibited | required)",
7130 attrValue, NULL, NULL, NULL);
7131 }
7132 goto attr_next;
7133 } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7134 /*
7135 * 3.2.3 : 1
7136 * default and fixed must not both be present.
7137 */
7138 if (defValue) {
7139 xmlSchemaPMutualExclAttrErr(pctxt,
7140 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7141 NULL, attr, "default", "fixed");
7142 } else {
7143 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7144 defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7145 }
7146 goto attr_next;
7147 } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7148 /*
7149 * 3.2.3 : 1
7150 * default and fixed must not both be present.
7151 */
7152 if (defValue) {
7153 xmlSchemaPMutualExclAttrErr(pctxt,
7154 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7155 NULL, attr, "default", "fixed");
7156 } else {
7157 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7158 defValueType = WXS_ATTR_DEF_VAL_FIXED;
7159 }
7160 goto attr_next;
7161 }
7162 } else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7163 goto attr_next;
7164
7165 xmlSchemaPIllegalAttrErr(pctxt,
7166 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7167
7168attr_next:
7169 attr = attr->next;
7170 }
7171 /*
7172 * 3.2.3 : 2
7173 * If default and use are both present, use must have
7174 * the actual value optional.
7175 */
7176 if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7177 (occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7178 xmlSchemaPSimpleTypeErr(pctxt,
7179 XML_SCHEMAP_SRC_ATTRIBUTE_2,
7180 NULL, node, NULL,
7181 "(optional | prohibited | required)", NULL,
7182 "The value of the attribute 'use' must be 'optional' "
7183 "if the attribute 'default' is present",
7184 NULL, NULL);
7185 }
7186 /*
7187 * We want correct attributes.
7188 */
7189 if (nberrors != pctxt->nberrors)
7190 return(NULL);
7191 if (! isRef) {
7192 xmlSchemaAttributePtr attrDecl;
7193
7194 /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7195 if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7196 ns = pctxt->targetNamespace;
7197 /*
7198 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7199 * TODO: Move this to the component layer.
7200 */
7201 if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7202 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7203 XML_SCHEMAP_NO_XSI,
7204 node, NULL,
7205 "The target namespace must not match '%s'",
7206 xmlSchemaInstanceNs, NULL);
7207 }
7208 attr = xmlSchemaGetPropNode(node, "name");
7209 if (attr == NULL) {
7210 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7211 NULL, node, "name", NULL);
7212 return (NULL);
7213 }
7214 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7215 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7216 return (NULL);
7217 }
7218 /*
7219 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7220 * TODO: Move this to the component layer.
7221 */
7222 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7223 xmlSchemaPSimpleTypeErr(pctxt,
7224 XML_SCHEMAP_NO_XMLNS,
7225 NULL, (xmlNodePtr) attr,
7226 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7227 "The value of the attribute must not match 'xmlns'",
7228 NULL, NULL);
7229 return (NULL);
7230 }
7231 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7232 goto check_children;
7233 /*
7234 * Create the attribute use component.
7235 */
7236 use = xmlSchemaAddAttributeUse(pctxt, node);
7237 if (use == NULL)
7238 return(NULL);
7239 use->occurs = occurs;
7240 /*
7241 * Create the attribute declaration.
7242 */
7243 attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7244 if (attrDecl == NULL)
7245 return (NULL);
7246 if (tmpName != NULL) {
7247 attrDecl->typeName = tmpName;
7248 attrDecl->typeNs = tmpNs;
7249 }
7250 use->attrDecl = attrDecl;
7251 /*
7252 * Value constraint.
7253 */
7254 if (defValue != NULL) {
7255 attrDecl->defValue = defValue;
7256 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7257 attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7258 }
7259 } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7260 xmlSchemaQNameRefPtr ref;
7261
7262 /*
7263 * Create the attribute use component.
7264 */
7265 use = xmlSchemaAddAttributeUse(pctxt, node);
7266 if (use == NULL)
7267 return(NULL);
7268 /*
7269 * We need to resolve the reference at later stage.
7270 */
7271 WXS_ADD_PENDING(pctxt, use);
7272 use->occurs = occurs;
7273 /*
7274 * Create a QName reference to the attribute declaration.
7275 */
7276 ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7277 tmpName, tmpNs);
7278 if (ref == NULL)
7279 return(NULL);
7280 /*
7281 * Assign the reference. This will be substituted for the
7282 * referenced attribute declaration when the QName is resolved.
7283 */
7284 use->attrDecl = WXS_ATTR_CAST ref;
7285 /*
7286 * Value constraint.
7287 */
7288 if (defValue != NULL)
7289 use->defValue = defValue;
7290 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7291 use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7292 }
7293
7294check_children:
7295 /*
7296 * And now for the children...
7297 */
7298 child = node->children;
7299 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7300 xmlSchemaAttributeUseProhibPtr prohib;
7301
7302 if (IS_SCHEMA(child, "annotation")) {
7303 xmlSchemaParseAnnotation(pctxt, schema, child, 0);
7304 child = child->next;
7305 }
7306 if (child != NULL) {
7307 xmlSchemaPContentErr(pctxt,
7308 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7309 NULL, node, child, NULL,
7310 "(annotation?)");
7311 }
7312 /*
7313 * Check for pointlessness of attribute prohibitions.
7314 */
7315 if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7316 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7317 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7318 node, NULL,
7319 "Skipping attribute use prohibition, since it is "
7320 "pointless inside an <attributeGroup>",
7321 NULL, NULL, NULL);
7322 return(NULL);
7323 } else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7324 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7325 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7326 node, NULL,
7327 "Skipping attribute use prohibition, since it is "
7328 "pointless when extending a type",
7329 NULL, NULL, NULL);
7330 return(NULL);
7331 }
7332 if (! isRef) {
7333 tmpName = name;
7334 tmpNs = ns;
7335 }
7336 /*
7337 * Check for duplicate attribute prohibitions.
7338 */
7339 if (uses) {
7340 int i;
7341
7342 for (i = 0; i < uses->nbItems; i++) {
7343 use = uses->items[i];
7344 if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7345 (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7346 (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7347 {
7348 xmlChar *str = NULL;
7349
7350 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7351 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7352 node, NULL,
7353 "Skipping duplicate attribute use prohibition '%s'",
7354 xmlSchemaFormatQName(&str, tmpNs, tmpName),
7355 NULL, NULL);
7356 FREE_AND_NULL(str)
7357 return(NULL);
7358 }
7359 }
7360 }
7361 /*
7362 * Create the attribute prohibition helper component.
7363 */
7364 prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7365 if (prohib == NULL)
7366 return(NULL);
7367 prohib->node = node;
7368 prohib->name = tmpName;
7369 prohib->targetNamespace = tmpNs;
7370 if (isRef) {
7371 /*
7372 * We need at least to resolve to the attribute declaration.
7373 */
7374 WXS_ADD_PENDING(pctxt, prohib);
7375 }
7376 return(WXS_BASIC_CAST prohib);
7377 } else {
7378 if (IS_SCHEMA(child, "annotation")) {
7379 /*
7380 * TODO: Should this go into the attr decl?
7381 */
7382 use->annot = xmlSchemaParseAnnotation(pctxt, schema, child, 1);
7383 child = child->next;
7384 }
7385 if (isRef) {
7386 if (child != NULL) {
7387 if (IS_SCHEMA(child, "simpleType"))
7388 /*
7389 * 3.2.3 : 3.2
7390 * If ref is present, then all of <simpleType>,
7391 * form and type must be absent.
7392 */
7393 xmlSchemaPContentErr(pctxt,
7394 XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7395 NULL, node, child, NULL,
7396 "(annotation?)");
7397 else
7398 xmlSchemaPContentErr(pctxt,
7399 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7400 NULL, node, child, NULL,
7401 "(annotation?)");
7402 }
7403 } else {
7404 if (IS_SCHEMA(child, "simpleType")) {
7405 if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7406 /*
7407 * 3.2.3 : 4
7408 * type and <simpleType> must not both be present.
7409 */
7410 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7411 NULL, node, child,
7412 "The attribute 'type' and the <simpleType> child "
7413 "are mutually exclusive", NULL);
7414 } else
7415 WXS_ATTRUSE_TYPEDEF(use) =
7416 xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7417 child = child->next;
7418 }
7419 if (child != NULL)
7420 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7421 NULL, node, child, NULL,
7422 "(annotation?, simpleType?)");
7423 }
7424 }
7425 return (WXS_BASIC_CAST use);
7426}
7427
7428
7429static xmlSchemaAttributePtr
7430xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7431 xmlSchemaPtr schema,
7432 xmlNodePtr node)
7433{
7434 const xmlChar *attrValue;
Daniel Veillard4255d502002-04-16 15:50:10 +00007435 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007436 xmlNodePtr child = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007437 xmlAttrPtr attr;
William M. Bracke7091952004-05-11 15:09:58 +00007438
7439 /*
7440 * Note that the w3c spec assumes the schema to be validated with schema
7441 * for schemas beforehand.
7442 *
7443 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00007444 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007445 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7446 return (NULL);
7447 /*
7448 * 3.2.3 : 3.1
7449 * One of ref or name must be present, but not both
7450 */
7451 attr = xmlSchemaGetPropNode(node, "name");
7452 if (attr == NULL) {
7453 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7454 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007455 return (NULL);
7456 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007457 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7458 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7459 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007460 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007461 /*
7462 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7463 * TODO: Move this to the component layer.
7464 */
7465 if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7466 xmlSchemaPSimpleTypeErr(pctxt,
7467 XML_SCHEMAP_NO_XMLNS,
7468 NULL, (xmlNodePtr) attr,
7469 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7470 "The value of the attribute must not match 'xmlns'",
7471 NULL, NULL);
7472 return (NULL);
7473 }
7474 /*
7475 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7476 * TODO: Move this to the component layer.
7477 * Or better leave it here and add it to the component layer
7478 * if we have a schema construction API.
7479 */
7480 if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7481 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7482 XML_SCHEMAP_NO_XSI, node, NULL,
7483 "The target namespace must not match '%s'",
7484 xmlSchemaInstanceNs, NULL);
7485 }
7486
7487 ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7488 pctxt->targetNamespace, node, 1);
7489 if (ret == NULL)
7490 return (NULL);
7491 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7492
7493 /*
7494 * Check for illegal attributes.
7495 */
7496 attr = node->properties;
7497 while (attr != NULL) {
7498 if (attr->ns == NULL) {
7499 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7500 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7501 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7502 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7503 (!xmlStrEqual(attr->name, BAD_CAST "type")))
7504 {
7505 xmlSchemaPIllegalAttrErr(pctxt,
7506 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7507 }
7508 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7509 xmlSchemaPIllegalAttrErr(pctxt,
7510 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7511 }
7512 attr = attr->next;
7513 }
7514 xmlSchemaPValAttrQName(pctxt, schema, NULL,
7515 node, "type", &ret->typeNs, &ret->typeName);
7516
7517 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00007518 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007519 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00007520 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007521 ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007522 if (ret->defValue != NULL)
7523 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007524 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007525 * Attribute "default".
7526 */
7527 attr = xmlSchemaGetPropNode(node, "default");
7528 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007529 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007530 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007531 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007532 */
7533 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007534 xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7535 WXS_BASIC_CAST ret, attr, "default", "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007536 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007537 ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007538 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007539 /*
7540 * And now for the children...
7541 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007542 child = node->children;
7543 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007544 ret->annot = xmlSchemaParseAnnotation(pctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007545 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007546 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007547 if (IS_SCHEMA(child, "simpleType")) {
7548 if (ret->typeName != NULL) {
7549 /*
7550 * 3.2.3 : 4
7551 * type and <simpleType> must not both be present.
7552 */
7553 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7554 NULL, node, child,
7555 "The attribute 'type' and the <simpleType> child "
7556 "are mutually exclusive", NULL);
7557 } else
7558 ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7559 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007560 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007561 if (child != NULL)
7562 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7563 NULL, node, child, NULL,
7564 "(annotation?, simpleType?)");
7565
Daniel Veillard4255d502002-04-16 15:50:10 +00007566 return (ret);
7567}
7568
7569/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007570 * xmlSchemaParseAttributeGroupRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00007571 * @ctxt: a schema validation context
7572 * @schema: the schema being built
7573 * @node: a subtree containing XML Schema informations
7574 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007575 * Parse an attribute group definition reference.
7576 * Note that a reference to an attribute group does not
7577 * correspond to any component at all.
Daniel Veillard4255d502002-04-16 15:50:10 +00007578 * *WARNING* this interface is highly subject to change
7579 *
7580 * Returns the attribute group or NULL in case of error.
7581 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007582static xmlSchemaQNameRefPtr
7583xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7584 xmlSchemaPtr schema,
7585 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007586{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007587 xmlSchemaQNameRefPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00007588 xmlNodePtr child = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007589 xmlAttrPtr attr;
7590 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007591
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007592 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00007593 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007594
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007595 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007596 if (attr == NULL) {
7597 xmlSchemaPMissingAttrErr(pctxt,
7598 XML_SCHEMAP_S4S_ATTR_MISSING,
7599 NULL, node, "ref", NULL);
7600 return (NULL);
7601 }
7602 xmlSchemaPValAttrNodeQName(pctxt, schema,
7603 NULL, attr, &refNs, &ref);
7604 if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7605 return(NULL);
7606
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007607 /*
7608 * Check for illegal attributes.
7609 */
7610 attr = node->properties;
7611 while (attr != NULL) {
7612 if (attr->ns == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007613 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007614 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007615 {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007616 xmlSchemaPIllegalAttrErr(pctxt,
7617 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007618 }
7619 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007620 xmlSchemaPIllegalAttrErr(pctxt,
7621 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007622 }
7623 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007624 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00007625 /* Attribute ID */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007626 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7627
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007628 /*
7629 * And now for the children...
7630 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007631 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00007632 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007633 /*
7634 * TODO: We do not have a place to store the annotation, do we?
7635 */
7636 xmlSchemaParseAnnotation(pctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007637 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007638 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007639 if (child != NULL) {
7640 xmlSchemaPContentErr(pctxt,
7641 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7642 NULL, node, child, NULL,
7643 "(annotation?)");
7644 }
7645
7646 /*
7647 * Handle attribute group redefinitions.
7648 */
7649 if (pctxt->isRedefine && pctxt->redef &&
7650 (pctxt->redef->item->type ==
7651 XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7652 (ref == pctxt->redef->refName) &&
7653 (refNs == pctxt->redef->refTargetNs))
7654 {
7655 /*
7656 * SPEC src-redefine:
7657 * (7.1) "If it has an <attributeGroup> among its contents
7658 * the ·actual value· of whose ref [attribute] is the same
7659 * as the ·actual value· of its own name attribute plus
7660 * target namespace, then it must have exactly one such group."
7661 */
7662 if (pctxt->redefCounter != 0) {
7663 xmlChar *str = NULL;
7664
7665 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7666 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7667 "The redefining attribute group definition "
7668 "'%s' must not contain more than one "
7669 "reference to the redefined definition",
7670 xmlSchemaFormatQName(&str, refNs, ref), NULL);
7671 FREE_AND_NULL(str);
7672 return(NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007673 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007674 pctxt->redefCounter++;
7675 /*
7676 * URGENT TODO: How to ensure that the reference will not be
7677 * handled by the normal component resolution mechanism?
7678 */
7679 ret = xmlSchemaNewQNameRef(pctxt,
7680 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7681 if (ret == NULL)
7682 return(NULL);
7683 ret->node = node;
7684 pctxt->redef->reference = WXS_BASIC_CAST ret;
7685 } else {
7686 /*
7687 * Create a QName-reference helper component. We will substitute this
7688 * component for the attribute uses of the referenced attribute group
7689 * definition.
7690 */
7691 ret = xmlSchemaNewQNameRef(pctxt,
7692 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7693 if (ret == NULL)
7694 return(NULL);
7695 ret->node = node;
7696 /* Add to pending items, to be able to resolve the reference. */
7697 WXS_ADD_PENDING(pctxt, ret);
7698 }
7699 return (ret);
7700}
7701
7702/**
7703 * xmlSchemaParseAttributeGroupDefinition:
7704 * @pctxt: a schema validation context
7705 * @schema: the schema being built
7706 * @node: a subtree containing XML Schema informations
7707 *
7708 * parse a XML schema Attribute Group declaration
7709 * *WARNING* this interface is highly subject to change
7710 *
7711 * Returns the attribute group definition or NULL in case of error.
7712 */
7713static xmlSchemaAttributeGroupPtr
7714xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7715 xmlSchemaPtr schema,
7716 xmlNodePtr node)
7717{
7718 const xmlChar *name;
7719 xmlSchemaAttributeGroupPtr ret;
7720 xmlNodePtr child = NULL;
7721 xmlAttrPtr attr;
7722 int hasRefs = 0;
7723
7724 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7725 return (NULL);
7726
7727 attr = xmlSchemaGetPropNode(node, "name");
7728 if (attr == NULL) {
7729 xmlSchemaPMissingAttrErr(pctxt,
7730 XML_SCHEMAP_S4S_ATTR_MISSING,
7731 NULL, node, "name", NULL);
7732 return (NULL);
7733 }
7734 /*
7735 * The name is crucial, exit if invalid.
7736 */
7737 if (xmlSchemaPValAttrNode(pctxt,
7738 NULL, attr,
7739 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7740 return (NULL);
7741 }
7742 ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7743 name, pctxt->targetNamespace, node);
7744 if (ret == NULL)
7745 return (NULL);
7746 /*
7747 * Check for illegal attributes.
7748 */
7749 attr = node->properties;
7750 while (attr != NULL) {
7751 if (attr->ns == NULL) {
7752 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7753 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7754 {
7755 xmlSchemaPIllegalAttrErr(pctxt,
7756 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7757 }
7758 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7759 xmlSchemaPIllegalAttrErr(pctxt,
7760 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7761 }
7762 attr = attr->next;
7763 }
7764 /* Attribute ID */
7765 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7766 /*
7767 * And now for the children...
7768 */
7769 child = node->children;
7770 if (IS_SCHEMA(child, "annotation")) {
7771 ret->annot = xmlSchemaParseAnnotation(pctxt, schema, child, 1);
7772 child = child->next;
7773 }
7774 /*
7775 * Parse contained attribute decls/refs.
7776 */
7777 if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7778 (xmlSchemaItemListPtr *) &(ret->attrUses),
7779 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7780 return(NULL);
7781 if (hasRefs)
7782 ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7783 /*
7784 * Parse the attribute wildcard.
7785 */
7786 if (IS_SCHEMA(child, "anyAttribute")) {
7787 ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7788 schema, child);
7789 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007790 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007791 if (child != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007792 xmlSchemaPContentErr(pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007793 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007794 NULL, node, child, NULL,
7795 "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007796 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007797 return (ret);
7798}
7799
7800/**
William M. Brack2f2a6632004-08-20 23:09:47 +00007801 * xmlSchemaPValAttrFormDefault:
7802 * @value: the value
7803 * @flags: the flags to be modified
7804 * @flagQualified: the specific flag for "qualified"
7805 *
7806 * Returns 0 if the value is valid, 1 otherwise.
7807 */
7808static int
7809xmlSchemaPValAttrFormDefault(const xmlChar *value,
7810 int *flags,
7811 int flagQualified)
7812{
7813 if (xmlStrEqual(value, BAD_CAST "qualified")) {
7814 if ((*flags & flagQualified) == 0)
7815 *flags |= flagQualified;
7816 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007817 return (1);
7818
William M. Brack2f2a6632004-08-20 23:09:47 +00007819 return (0);
7820}
7821
7822/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00007823 * xmlSchemaPValAttrBlockFinal:
7824 * @value: the value
7825 * @flags: the flags to be modified
7826 * @flagAll: the specific flag for "#all"
7827 * @flagExtension: the specific flag for "extension"
7828 * @flagRestriction: the specific flag for "restriction"
7829 * @flagSubstitution: the specific flag for "substitution"
7830 * @flagList: the specific flag for "list"
7831 * @flagUnion: the specific flag for "union"
7832 *
7833 * Validates the value of the attribute "final" and "block". The value
7834 * is converted into the specified flag values and returned in @flags.
7835 *
7836 * Returns 0 if the value is valid, 1 otherwise.
7837 */
7838
7839static int
7840xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007841 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007842 int flagAll,
7843 int flagExtension,
7844 int flagRestriction,
7845 int flagSubstitution,
7846 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007847 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007848{
7849 int ret = 0;
7850
7851 /*
7852 * TODO: This does not check for dublicate entries.
7853 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007854 if ((flags == NULL) || (value == NULL))
7855 return (-1);
7856 if (value[0] == 0)
7857 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007858 if (xmlStrEqual(value, BAD_CAST "#all")) {
7859 if (flagAll != -1)
7860 *flags |= flagAll;
7861 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007862 if (flagExtension != -1)
7863 *flags |= flagExtension;
7864 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007865 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007866 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007867 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007868 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007869 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007870 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007871 *flags |= flagUnion;
7872 }
7873 } else {
7874 const xmlChar *end, *cur = value;
7875 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007876
Daniel Veillardc0826a72004-08-10 14:17:33 +00007877 do {
7878 while (IS_BLANK_CH(*cur))
7879 cur++;
7880 end = cur;
7881 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7882 end++;
7883 if (end == cur)
7884 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007885 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007886 if (xmlStrEqual(item, BAD_CAST "extension")) {
7887 if (flagExtension != -1) {
7888 if ((*flags & flagExtension) == 0)
7889 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007890 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007891 ret = 1;
7892 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7893 if (flagRestriction != -1) {
7894 if ((*flags & flagRestriction) == 0)
7895 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007896 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007897 ret = 1;
7898 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7899 if (flagSubstitution != -1) {
7900 if ((*flags & flagSubstitution) == 0)
7901 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007902 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007903 ret = 1;
7904 } else if (xmlStrEqual(item, BAD_CAST "list")) {
7905 if (flagList != -1) {
7906 if ((*flags & flagList) == 0)
7907 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007908 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007909 ret = 1;
7910 } else if (xmlStrEqual(item, BAD_CAST "union")) {
7911 if (flagUnion != -1) {
7912 if ((*flags & flagUnion) == 0)
7913 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007914 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007915 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007916 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007917 ret = 1;
7918 if (item != NULL)
7919 xmlFree(item);
7920 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007921 } while ((ret == 0) && (*cur != 0));
7922 }
7923
Daniel Veillardc0826a72004-08-10 14:17:33 +00007924 return (ret);
7925}
7926
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007927static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007928xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007929 xmlSchemaIDCPtr idc,
7930 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007931 xmlAttrPtr attr,
7932 int isField)
7933{
7934 xmlNodePtr node;
7935
7936 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007937 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007938 * Schema Component Constraint: Selector Value OK
7939 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007940 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007941 * in [XPath].
7942 */
7943 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007944 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007945 XML_SCHEMAP_INTERNAL,
7946 "Internal error: xmlSchemaCheckCSelectorXPath, "
7947 "the selector is not specified.\n", NULL, NULL);
7948 return (-1);
7949 }
7950 if (attr == NULL)
7951 node = idc->node;
7952 else
7953 node = (xmlNodePtr) attr;
7954 if (selector->xpath == NULL) {
7955 xmlSchemaPCustomErr(ctxt,
7956 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007957 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007958 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007959 "The XPath expression of the selector is not valid", NULL);
7960 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
7961 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007962 const xmlChar **nsArray = NULL;
7963 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007964 /*
7965 * Compile the XPath expression.
7966 */
7967 /*
7968 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007969 * TODO: Call xmlPatterncompile with different options for selector/
7970 * field.
7971 */
7972 nsList = xmlGetNsList(attr->doc, attr->parent);
7973 /*
7974 * Build an array of prefixes and namespaces.
7975 */
7976 if (nsList != NULL) {
7977 int i, count = 0;
7978 xmlNsPtr ns;
7979
7980 for (i = 0; nsList[i] != NULL; i++)
7981 count++;
7982
7983 nsArray = (const xmlChar **) xmlMalloc(
7984 (count * 2 + 1) * sizeof(const xmlChar *));
7985 if (nsArray == NULL) {
7986 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
7987 NULL);
Kasimier T. Buchcik940ab0c2005-10-19 17:00:53 +00007988 xmlFree(nsList);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007989 return (-1);
7990 }
7991 for (i = 0; i < count; i++) {
7992 ns = nsList[i];
7993 nsArray[2 * i] = nsList[i]->href;
7994 nsArray[2 * i + 1] = nsList[i]->prefix;
7995 }
7996 nsArray[count * 2] = NULL;
7997 xmlFree(nsList);
7998 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007999 /*
8000 * TODO: Differentiate between "selector" and "field".
8001 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008002 if (isField)
8003 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008004 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008005 else
8006 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008007 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008008 if (nsArray != NULL)
8009 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008010
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00008011 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008012 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00008013 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008014 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008015 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008016 "The XPath expression '%s' could not be "
8017 "compiled", selector->xpath);
8018 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008019 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008020 }
8021 return (0);
8022}
8023
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008024#define ADD_ANNOTATION(annot) \
8025 xmlSchemaAnnotPtr cur = item->annot; \
8026 if (item->annot == NULL) { \
8027 item->annot = annot; \
8028 return (annot); \
8029 } \
8030 cur = item->annot; \
8031 if (cur->next != NULL) { \
8032 cur = cur->next; \
8033 } \
8034 cur->next = annot;
8035
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008036/**
8037 * xmlSchemaAssignAnnotation:
8038 * @item: the schema component
8039 * @annot: the annotation
8040 *
8041 * Adds the annotation to the given schema component.
8042 *
8043 * Returns the given annotaion.
8044 */
8045static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008046xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8047 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008048{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008049 if ((annItem == NULL) || (annot == NULL))
8050 return (NULL);
8051 switch (annItem->type) {
8052 case XML_SCHEMA_TYPE_ELEMENT: {
8053 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8054 ADD_ANNOTATION(annot)
8055 }
8056 break;
8057 case XML_SCHEMA_TYPE_ATTRIBUTE: {
8058 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8059 ADD_ANNOTATION(annot)
8060 }
8061 break;
8062 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8063 case XML_SCHEMA_TYPE_ANY: {
8064 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8065 ADD_ANNOTATION(annot)
8066 }
8067 break;
8068 case XML_SCHEMA_TYPE_PARTICLE:
8069 case XML_SCHEMA_TYPE_IDC_KEY:
8070 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008071 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008072 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8073 ADD_ANNOTATION(annot)
8074 }
8075 break;
8076 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8077 xmlSchemaAttributeGroupPtr item =
8078 (xmlSchemaAttributeGroupPtr) annItem;
8079 ADD_ANNOTATION(annot)
8080 }
8081 break;
8082 case XML_SCHEMA_TYPE_NOTATION: {
8083 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8084 ADD_ANNOTATION(annot)
8085 }
8086 break;
8087 case XML_SCHEMA_FACET_MININCLUSIVE:
8088 case XML_SCHEMA_FACET_MINEXCLUSIVE:
8089 case XML_SCHEMA_FACET_MAXINCLUSIVE:
8090 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8091 case XML_SCHEMA_FACET_TOTALDIGITS:
8092 case XML_SCHEMA_FACET_FRACTIONDIGITS:
8093 case XML_SCHEMA_FACET_PATTERN:
8094 case XML_SCHEMA_FACET_ENUMERATION:
8095 case XML_SCHEMA_FACET_WHITESPACE:
8096 case XML_SCHEMA_FACET_LENGTH:
8097 case XML_SCHEMA_FACET_MAXLENGTH:
8098 case XML_SCHEMA_FACET_MINLENGTH: {
8099 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8100 ADD_ANNOTATION(annot)
8101 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008102 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008103 case XML_SCHEMA_TYPE_SIMPLE:
8104 case XML_SCHEMA_TYPE_COMPLEX: {
8105 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8106 ADD_ANNOTATION(annot)
8107 }
8108 break;
8109 case XML_SCHEMA_TYPE_GROUP: {
8110 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8111 ADD_ANNOTATION(annot)
8112 }
8113 break;
8114 case XML_SCHEMA_TYPE_SEQUENCE:
8115 case XML_SCHEMA_TYPE_CHOICE:
8116 case XML_SCHEMA_TYPE_ALL: {
8117 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8118 ADD_ANNOTATION(annot)
8119 }
8120 break;
8121 default:
8122 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008123 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008124 NULL, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008125 "Internal error: xmlSchemaAddAnnotation, "
8126 "The item is not a annotated schema component", NULL);
8127 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008128 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008129 return (annot);
8130}
8131
8132/**
8133 * xmlSchemaParseIDCSelectorAndField:
8134 * @ctxt: a schema validation context
8135 * @schema: the schema being built
8136 * @node: a subtree containing XML Schema informations
8137 *
8138 * Parses a XML Schema identity-contraint definition's
8139 * <selector> and <field> elements.
8140 *
8141 * Returns the parsed identity-constraint definition.
8142 */
8143static xmlSchemaIDCSelectPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008144xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008145 xmlSchemaPtr schema,
8146 xmlSchemaIDCPtr idc,
8147 xmlNodePtr node,
8148 int isField)
8149{
8150 xmlSchemaIDCSelectPtr item;
8151 xmlNodePtr child = NULL;
8152 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008153
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008154 /*
8155 * Check for illegal attributes.
8156 */
8157 attr = node->properties;
8158 while (attr != NULL) {
8159 if (attr->ns == NULL) {
8160 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8161 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008162 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008163 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008164 }
8165 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008166 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008167 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008168 }
8169 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008170 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008171 /*
8172 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008173 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008174 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8175 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008176 xmlSchemaPErrMemory(ctxt,
8177 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008178 NULL);
8179 return (NULL);
8180 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008181 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008182 /*
8183 * Attribute "xpath" (mandatory).
8184 */
8185 attr = xmlSchemaGetPropNode(node, "xpath");
8186 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008187 xmlSchemaPMissingAttrErr(ctxt,
8188 XML_SCHEMAP_S4S_ATTR_MISSING,
8189 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008190 "name", NULL);
8191 } else {
8192 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8193 /*
8194 * URGENT TODO: "field"s have an other syntax than "selector"s.
8195 */
8196
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008197 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8198 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008199 xmlSchemaPErr(ctxt,
8200 (xmlNodePtr) attr,
8201 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008202 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008203 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008204 NULL, NULL);
8205 }
8206
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008207 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008208 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008209 /*
8210 * And now for the children...
8211 */
8212 child = node->children;
8213 if (IS_SCHEMA(child, "annotation")) {
8214 /*
8215 * Add the annotation to the parent IDC.
8216 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008217 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008218 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008219 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008220 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008221 if (child != NULL) {
8222 xmlSchemaPContentErr(ctxt,
8223 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008224 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008225 NULL, "(annotation?)");
8226 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008227
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008228 return (item);
8229}
8230
8231/**
8232 * xmlSchemaParseIDC:
8233 * @ctxt: a schema validation context
8234 * @schema: the schema being built
8235 * @node: a subtree containing XML Schema informations
8236 *
8237 * Parses a XML Schema identity-contraint definition.
8238 *
8239 * Returns the parsed identity-constraint definition.
8240 */
8241static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008242xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008243 xmlSchemaPtr schema,
8244 xmlNodePtr node,
8245 xmlSchemaTypeType idcCategory,
8246 const xmlChar *targetNamespace)
8247{
8248 xmlSchemaIDCPtr item = NULL;
8249 xmlNodePtr child = NULL;
8250 xmlAttrPtr attr;
8251 const xmlChar *name = NULL;
8252 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008253
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008254 /*
8255 * Check for illegal attributes.
8256 */
8257 attr = node->properties;
8258 while (attr != NULL) {
8259 if (attr->ns == NULL) {
8260 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8261 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8262 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8263 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008264 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008265 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008266 }
8267 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008268 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008269 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008270 }
8271 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008272 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008273 /*
8274 * Attribute "name" (mandatory).
8275 */
8276 attr = xmlSchemaGetPropNode(node, "name");
8277 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008278 xmlSchemaPMissingAttrErr(ctxt,
8279 XML_SCHEMAP_S4S_ATTR_MISSING,
8280 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008281 "name", NULL);
8282 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008283 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008284 NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008285 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8286 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008287 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008288 /* Create the component. */
8289 item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8290 idcCategory, node);
8291 if (item == NULL)
8292 return(NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008293
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008294 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008295 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8296 /*
8297 * Attribute "refer" (mandatory).
8298 */
8299 attr = xmlSchemaGetPropNode(node, "refer");
8300 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008301 xmlSchemaPMissingAttrErr(ctxt,
8302 XML_SCHEMAP_S4S_ATTR_MISSING,
8303 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008304 "refer", NULL);
8305 } else {
8306 /*
8307 * Create a reference item.
8308 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008309 item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008310 NULL, NULL);
8311 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008312 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008313 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008314 NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008315 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008316 &(item->ref->name));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008317 xmlSchemaCheckReference(ctxt, schema, node, attr,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008318 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008319 }
8320 }
8321 /*
8322 * And now for the children...
8323 */
8324 child = node->children;
8325 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008326 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008327 child = child->next;
8328 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00008329 if (child == NULL) {
8330 xmlSchemaPContentErr(ctxt,
8331 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008332 NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00008333 "A child element is missing",
8334 "(annotation?, (selector, field+))");
8335 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008336 /*
8337 * Child element <selector>.
8338 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008339 if (IS_SCHEMA(child, "selector")) {
8340 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008341 item, child, 0);
8342 child = child->next;
8343 /*
8344 * Child elements <field>.
8345 */
8346 if (IS_SCHEMA(child, "field")) {
8347 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008348 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008349 item, child, 1);
8350 if (field != NULL) {
8351 field->index = item->nbFields;
8352 item->nbFields++;
8353 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008354 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008355 else
8356 item->fields = field;
8357 lastField = field;
8358 }
8359 child = child->next;
8360 } while (IS_SCHEMA(child, "field"));
8361 } else {
8362 xmlSchemaPContentErr(ctxt,
8363 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008364 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008365 NULL, "(annotation?, (selector, field+))");
8366 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008367 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008368 if (child != NULL) {
8369 xmlSchemaPContentErr(ctxt,
8370 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008371 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008372 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008373 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008374
8375 return (item);
8376}
8377
Daniel Veillardc0826a72004-08-10 14:17:33 +00008378/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008379 * xmlSchemaParseElement:
8380 * @ctxt: a schema validation context
8381 * @schema: the schema being built
8382 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008383 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00008384 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008385 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00008386 * *WARNING* this interface is highly subject to change
8387 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008388 * Returns the element declaration or a particle; NULL in case
8389 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00008390 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008391static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00008392xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008393 xmlNodePtr node, int *isElemRef, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008394{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008395 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008396 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008397 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008398 xmlNodePtr child = NULL;
8399 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008400 int min, max, isRef = 0;
8401 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00008402
8403 /* 3.3.3 Constraints on XML Representations of Element Declarations */
8404 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008405
Daniel Veillard4255d502002-04-16 15:50:10 +00008406 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008407 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008408
8409 if (isElemRef != NULL)
8410 *isElemRef = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008411 /*
8412 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008413 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008414 * robust.
8415 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008416 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008417 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008418 if ((topLevel) || (attr == NULL)) {
8419 if (nameAttr == NULL) {
8420 xmlSchemaPMissingAttrErr(ctxt,
8421 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008422 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008423 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008424 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008425 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00008426 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008427
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008428 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008429 child = node->children;
8430 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008431 annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008432 child = child->next;
8433 }
8434 /*
8435 * Skip particle part if a global declaration.
8436 */
8437 if (topLevel)
8438 goto declaration_part;
8439 /*
8440 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008441 */
8442 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8443 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8444 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008445 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8446 if (particle == NULL)
8447 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008448
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008449 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8450
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008451 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008452 const xmlChar *refNs = NULL, *ref = NULL;
8453 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008454 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008455 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00008456 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008457 if (isElemRef != NULL)
8458 *isElemRef = 1;
8459
Daniel Veillardc0826a72004-08-10 14:17:33 +00008460 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008461 NULL, attr, &refNs, &ref);
8462 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008463 /*
8464 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00008465 */
8466 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008467 xmlSchemaPMutualExclAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008468 XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008469 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008470 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008471 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008472 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008473 attr = node->properties;
8474 while (attr != NULL) {
8475 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008476 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8477 xmlStrEqual(attr->name, BAD_CAST "name") ||
8478 xmlStrEqual(attr->name, BAD_CAST "id") ||
8479 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8480 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8481 {
8482 attr = attr->next;
8483 continue;
8484 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008485 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008486 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008487 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008488 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008489 "Only the attributes 'minOccurs', 'maxOccurs' and "
8490 "'id' are allowed in addition to 'ref'");
8491 break;
8492 }
8493 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8494 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008495 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008496 }
8497 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008498 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008499 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008500 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008501 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008502 if (child != NULL) {
8503 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008504 NULL, node, child, NULL, "(annotation?)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008505 }
8506 if ((min == 0) && (max == 0))
8507 goto return_null;
8508 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008509 * Create the reference item and attach it to the particle.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008510 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008511 refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008512 ref, refNs);
8513 if (refer == NULL)
8514 goto return_null;
8515 particle->children = (xmlSchemaTreeItemPtr) refer;
8516 particle->annot = annot;
8517 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008518 * Add the particle to pending components, since the reference
8519 * need to be resolved.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008520 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008521 WXS_ADD_PENDING(ctxt, particle);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008522 return ((xmlSchemaBasicItemPtr) particle);
8523 }
8524 /*
8525 * The declaration part ===============================================
8526 */
8527declaration_part:
8528 {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008529 const xmlChar *ns = NULL, *fixed, *name, *attrValue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008530 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8531
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008532 if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008533 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008534 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008535 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008536 * Evaluate the target namespace.
8537 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008538 if (topLevel) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008539 ns = ctxt->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008540 } else {
8541 attr = xmlSchemaGetPropNode(node, "form");
8542 if (attr != NULL) {
8543 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8544 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008545 ns = ctxt->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008546 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008547 xmlSchemaPSimpleTypeErr(ctxt,
8548 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8549 NULL, (xmlNodePtr) attr,
8550 NULL, "(qualified | unqualified)",
8551 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008552 }
8553 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008554 ns = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008555 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008556 decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008557 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008558 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00008559 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008560 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008561 * Check for illegal attributes.
8562 */
William M. Bracke7091952004-05-11 15:09:58 +00008563 attr = node->properties;
8564 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008565 if (attr->ns == NULL) {
8566 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8567 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008568 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008569 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008570 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008571 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008572 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8573 {
8574 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008575 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008576 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008577 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008578 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008579 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008580 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008581 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008582 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8583 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008584 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8585
8586 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008587 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008588 }
8589 }
8590 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008591
Daniel Veillardc0826a72004-08-10 14:17:33 +00008592 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008593 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Bracke7091952004-05-11 15:09:58 +00008594 }
8595 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008596 }
William M. Bracke7091952004-05-11 15:09:58 +00008597 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008598 * Extract/validate attributes.
8599 */
8600 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008601 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008602 * Process top attributes of global element declarations here.
8603 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008604 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8605 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008606 xmlSchemaPValAttrQName(ctxt, schema,
8607 NULL, node, "substitutionGroup",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008608 &(decl->substGroupNs), &(decl->substGroup));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008609 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008610 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008611 /*
8612 * Attribute "final".
8613 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008614 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008615 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008616 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8617 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8618 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8619 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008620 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008621 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8622 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00008623 -1,
8624 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8625 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008626 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008627 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008628 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008629 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008630 attrValue, NULL, NULL, NULL);
8631 }
8632 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008633 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008634 /*
8635 * Attribute "block".
8636 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008637 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008638 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00008639 /*
8640 * Apply default "block" values.
8641 */
8642 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8643 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8644 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8645 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8646 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8647 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008648 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008649 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8650 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00008651 -1,
8652 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008653 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008654 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8655 xmlSchemaPSimpleTypeErr(ctxt,
8656 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008657 NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00008658 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008659 "restriction | substitution))", attrValue,
8660 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008661 }
8662 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008663 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008664 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008665
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008666 attr = xmlSchemaGetPropNode(node, "type");
8667 if (attr != NULL) {
8668 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008669 NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008670 &(decl->namedTypeNs), &(decl->namedType));
8671 xmlSchemaCheckReference(ctxt, schema, node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008672 attr, decl->namedTypeNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008673 }
8674 decl->value = xmlSchemaGetProp(ctxt, node, "default");
8675 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008676 if (attr != NULL) {
8677 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008678 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008679 /*
8680 * 3.3.3 : 1
8681 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008682 */
8683 xmlSchemaPMutualExclAttrErr(ctxt,
8684 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008685 NULL, attr, "default", "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008686 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008687 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8688 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008689 }
William M. Bracke7091952004-05-11 15:09:58 +00008690 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008691 /*
8692 * And now for the children...
8693 */
William M. Bracke7091952004-05-11 15:09:58 +00008694 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008695 /*
8696 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00008697 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008698 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00008699 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008700 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008701 xmlSchemaPContentErr(ctxt,
8702 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008703 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008704 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008705 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008706 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008707 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00008708 child = child->next;
8709 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008710 /*
8711 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00008712 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008713 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00008714 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008715 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008716 xmlSchemaPContentErr(ctxt,
8717 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008718 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008719 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008720 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008721 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008722 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00008723 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008724 }
William M. Bracke7091952004-05-11 15:09:58 +00008725 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00008726 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008727 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008728 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008729 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008730 } else if (IS_SCHEMA(child, "key")) {
8731 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008732 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008733 } else if (IS_SCHEMA(child, "keyref")) {
8734 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008735 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008736 }
8737 if (lastIDC != NULL)
8738 lastIDC->next = curIDC;
8739 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008740 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008741 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008742 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00008743 }
8744 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008745 xmlSchemaPContentErr(ctxt,
8746 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008747 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008748 NULL, "(annotation?, ((simpleType | complexType)?, "
8749 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008750 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008751 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008752 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008753 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008754 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00008755 * different layer.
8756 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008757 FREE_AND_NULL(des)
8758 if (topLevel)
8759 return ((xmlSchemaBasicItemPtr) decl);
8760 else {
8761 particle->children = (xmlSchemaTreeItemPtr) decl;
8762 return ((xmlSchemaBasicItemPtr) particle);
8763 }
8764
8765return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008766 FREE_AND_NULL(des);
8767 if (annot != NULL) {
8768 if (particle != NULL)
8769 particle->annot = NULL;
8770 if (decl != NULL)
8771 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008772 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008773 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008774 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008775}
8776
8777/**
8778 * xmlSchemaParseUnion:
8779 * @ctxt: a schema validation context
8780 * @schema: the schema being built
8781 * @node: a subtree containing XML Schema informations
8782 *
8783 * parse a XML schema Union definition
8784 * *WARNING* this interface is highly subject to change
8785 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008786 * Returns -1 in case of internal error, 0 in case of success and a positive
8787 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00008788 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008789static int
Daniel Veillard4255d502002-04-16 15:50:10 +00008790xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008791 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008792{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008793 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008794 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008795 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008796 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008797
8798 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008799 return (-1);
8800 /* Not a component, don't create it. */
8801 type = ctxt->ctxtType;
8802 /*
8803 * Mark the simple type as being of variety "union".
8804 */
8805 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008806 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008807 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8808 * then the ·simple ur-type definition·."
8809 */
8810 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008811 /*
8812 * Check for illegal attributes.
8813 */
8814 attr = node->properties;
8815 while (attr != NULL) {
8816 if (attr->ns == NULL) {
8817 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8818 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008819 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008820 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008821 }
8822 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008823 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008824 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008825 }
8826 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008827 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008828 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008829 /*
8830 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008831 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00008832 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008833 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008834 if (attr != NULL) {
8835 const xmlChar *end;
8836 xmlChar *tmp;
8837 const xmlChar *localName, *nsName;
8838 xmlSchemaTypeLinkPtr link, lastLink = NULL;
8839 xmlSchemaQNameRefPtr ref;
8840
8841 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008842 type->base = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008843 do {
8844 while (IS_BLANK_CH(*cur))
8845 cur++;
8846 end = cur;
8847 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8848 end++;
8849 if (end == cur)
8850 break;
8851 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008852 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008853 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008854 /*
8855 * Create the member type link.
8856 */
8857 link = (xmlSchemaTypeLinkPtr)
8858 xmlMalloc(sizeof(xmlSchemaTypeLink));
8859 if (link == NULL) {
8860 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8861 "allocating a type link", NULL);
8862 return (-1);
8863 }
8864 link->type = NULL;
8865 link->next = NULL;
8866 if (lastLink == NULL)
8867 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008868 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008869 lastLink->next = link;
8870 lastLink = link;
8871 /*
8872 * Create a reference item.
8873 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008874 ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008875 localName, nsName);
8876 if (ref == NULL) {
8877 FREE_AND_NULL(tmp)
8878 return (-1);
8879 }
8880 /*
8881 * Assign the reference to the link, it will be resolved
8882 * later during fixup of the union simple type.
8883 */
8884 link->type = (xmlSchemaTypePtr) ref;
8885 }
8886 FREE_AND_NULL(tmp)
8887 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008888 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008889
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008890 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008891 /*
8892 * And now for the children...
8893 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008894 child = node->children;
8895 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008896 /*
8897 * Add the annotation to the simple type ancestor.
8898 */
8899 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008900 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008901 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008902 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008903 if (IS_SCHEMA(child, "simpleType")) {
8904 xmlSchemaTypePtr subtype, last = NULL;
8905
8906 /*
8907 * Anchor the member types in the "subtypes" field of the
8908 * simple type.
8909 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008910 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008911 subtype = (xmlSchemaTypePtr)
8912 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8913 if (subtype != NULL) {
8914 if (last == NULL) {
8915 type->subtypes = subtype;
8916 last = subtype;
8917 } else {
8918 last->next = subtype;
8919 last = subtype;
8920 }
8921 last->next = NULL;
8922 }
8923 child = child->next;
8924 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008925 }
8926 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008927 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008928 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008929 NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008930 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008931 if ((attr == NULL) && (type->subtypes == NULL)) {
8932 /*
8933 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008934 * Either the memberTypes [attribute] of the <union> element must
8935 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008936 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008937 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008938 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008939 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008940 "Either the attribute 'memberTypes' or "
8941 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008942 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008943 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00008944}
8945
8946/**
8947 * xmlSchemaParseList:
8948 * @ctxt: a schema validation context
8949 * @schema: the schema being built
8950 * @node: a subtree containing XML Schema informations
8951 *
8952 * parse a XML schema List definition
8953 * *WARNING* this interface is highly subject to change
8954 *
William M. Bracke7091952004-05-11 15:09:58 +00008955 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008956 * 1 in case of success.
8957 */
8958static xmlSchemaTypePtr
8959xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008960 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008961{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008962 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008963 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008964 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008965
8966 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8967 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008968 /* Not a component, don't create it. */
8969 type = ctxt->ctxtType;
8970 /*
8971 * Mark the type as being of variety "list".
8972 */
8973 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008974 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008975 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8976 * then the ·simple ur-type definition·."
8977 */
8978 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008979 /*
8980 * Check for illegal attributes.
8981 */
8982 attr = node->properties;
8983 while (attr != NULL) {
8984 if (attr->ns == NULL) {
8985 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8986 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008987 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008988 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008989 }
8990 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008991 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008992 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008993 }
8994 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008995 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008996
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008997 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008998
William M. Brack2f2a6632004-08-20 23:09:47 +00008999 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009000 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9001 * fields for holding the reference to the itemType.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009002 *
9003 * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9004 * the "ref" fields.
William M. Brack2f2a6632004-08-20 23:09:47 +00009005 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009006 xmlSchemaPValAttrQName(ctxt, schema, NULL,
9007 node, "itemType", &(type->baseNs), &(type->base));
William M. Brack2f2a6632004-08-20 23:09:47 +00009008 /*
9009 * And now for the children...
9010 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009011 child = node->children;
9012 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009013 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009014 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009015 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009016 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009017 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009018 /*
9019 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009020 * Either the itemType [attribute] or the <simpleType> [child] of
9021 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009022 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009023 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009024 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009025 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009026 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00009027 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009028 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009029 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009030 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009031 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009032 child = child->next;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009033 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009034 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009035 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009036 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009037 "Either the attribute 'itemType' or the <simpleType> child "
9038 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009039 }
9040 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009041 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009042 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009043 NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00009044 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009045 if ((type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009046 (type->subtypes == NULL) &&
9047 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009048 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009049 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009050 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009051 "Either the attribute 'itemType' or the <simpleType> child "
9052 "must be present", NULL);
9053 }
9054 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009055}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009056
Daniel Veillard4255d502002-04-16 15:50:10 +00009057/**
9058 * xmlSchemaParseSimpleType:
9059 * @ctxt: a schema validation context
9060 * @schema: the schema being built
9061 * @node: a subtree containing XML Schema informations
9062 *
9063 * parse a XML schema Simple Type definition
9064 * *WARNING* this interface is highly subject to change
9065 *
William M. Bracke7091952004-05-11 15:09:58 +00009066 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00009067 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00009068 */
9069static xmlSchemaTypePtr
9070xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00009071 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00009072{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009073 xmlSchemaTypePtr type, oldCtxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009074 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009075 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009076 xmlAttrPtr attr;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009077 int hasRestriction = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009078
9079 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9080 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009081
Daniel Veillardc0826a72004-08-10 14:17:33 +00009082 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009083 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009084 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009085 xmlSchemaPMissingAttrErr(ctxt,
9086 XML_SCHEMAP_S4S_ATTR_MISSING,
9087 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009088 "name", NULL);
9089 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009090 } else {
9091 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009092 NULL, attr,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009093 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9094 return (NULL);
9095 /*
9096 * Skip built-in types.
9097 */
9098 if (ctxt->isS4S) {
9099 xmlSchemaTypePtr biType;
9100
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009101 if (ctxt->isRedefine) {
9102 /*
9103 * REDEFINE: Disallow redefinition of built-in-types.
9104 * TODO: It seems that the spec does not say anything
9105 * about this case.
9106 */
9107 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009108 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009109 "Redefinition of built-in simple types is not "
9110 "supported", NULL);
9111 return(NULL);
9112 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009113 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9114 if (biType != NULL)
9115 return (biType);
9116 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009117 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009118 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009119 /*
9120 * TargetNamespace:
9121 * SPEC "The ·actual value· of the targetNamespace [attribute]
9122 * of the <schema> ancestor element information item if present,
9123 * otherwise ·absent·.
9124 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009125 if (topLevel == 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009126#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009127 char buf[40];
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009128#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +00009129 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00009130 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009131 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009132#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009133 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009134 type = xmlSchemaAddType(ctxt, schema,
9135 XML_SCHEMA_TYPE_SIMPLE,
9136 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009137 ctxt->targetNamespace, node, 0);
9138#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009139 type = xmlSchemaAddType(ctxt, schema,
9140 XML_SCHEMA_TYPE_SIMPLE,
9141 NULL, ctxt->targetNamespace, node, 0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009142#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +00009143 if (type == NULL)
9144 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009145 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009146 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009147 /*
9148 * Check for illegal attributes.
9149 */
9150 attr = node->properties;
9151 while (attr != NULL) {
9152 if (attr->ns == NULL) {
9153 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009154 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009155 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009156 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009157 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009158 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009159 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009160 }
9161 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009162 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009163 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009164 /*
9165 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009166 *
9167 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009168 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009169 type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9170 attrValue, ctxt->targetNamespace, node, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009171 if (type == NULL)
9172 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009173 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009174 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009175 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9176 /*
9177 * Check for illegal attributes.
9178 */
9179 attr = node->properties;
9180 while (attr != NULL) {
9181 if (attr->ns == NULL) {
9182 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9183 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009184 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009185 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009186 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009187 }
9188 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009189 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009190 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009191 }
9192 attr = attr->next;
9193 }
9194 /*
9195 * Attribute "final".
9196 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009197 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009198 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009199 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9200 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9201 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9202 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9203 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9204 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009205 } else {
9206 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009207 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9208 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009209 XML_SCHEMAS_TYPE_FINAL_LIST,
9210 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9211
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009212 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009213 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009214 WXS_BASIC_CAST type, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009215 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00009216 attrValue, NULL, NULL, NULL);
9217 }
9218 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009219 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009220 type->targetNamespace = ctxt->targetNamespace;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009221 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009222 /*
9223 * And now for the children...
9224 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009225 oldCtxtType = ctxt->ctxtType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009226
Daniel Veillardc0826a72004-08-10 14:17:33 +00009227 ctxt->ctxtType = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009228
Daniel Veillard4255d502002-04-16 15:50:10 +00009229 child = node->children;
9230 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009231 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009232 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009233 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009234 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009235 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009236 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009237 "(annotation?, (restriction | list | union))");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009238 } else if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009239 xmlSchemaParseRestriction(ctxt, schema, child,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009240 XML_SCHEMA_TYPE_SIMPLE);
9241 hasRestriction = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009242 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009243 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009244 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009245 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009246 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009247 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009248 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009249 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009250 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009251 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009252 NULL, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009253 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00009254 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009255 /*
9256 * REDEFINE: SPEC src-redefine (5)
9257 * "Within the [children], each <simpleType> must have a
9258 * <restriction> among its [children] ... the ·actual value· of whose
9259 * base [attribute] must be the same as the ·actual value· of its own
9260 * name attribute plus target namespace;"
9261 */
9262 if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9263 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009264 NULL, node, "This is a redefinition, thus the "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009265 "<simpleType> must have a <restriction> child", NULL);
9266 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009267
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009268 ctxt->ctxtType = oldCtxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009269 return (type);
9270}
9271
Daniel Veillard4255d502002-04-16 15:50:10 +00009272/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009273 * xmlSchemaParseModelGroupDefRef:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009274 * @ctxt: the parser context
9275 * @schema: the schema being built
9276 * @node: the node
Daniel Veillard4255d502002-04-16 15:50:10 +00009277 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009278 * Parses a reference to a model group definition.
Daniel Veillard4255d502002-04-16 15:50:10 +00009279 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009280 * We will return a particle component with a qname-component or
9281 * NULL in case of an error.
Daniel Veillard4255d502002-04-16 15:50:10 +00009282 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009283static xmlSchemaTreeItemPtr
9284xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9285 xmlSchemaPtr schema,
9286 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00009287{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009288 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009289 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009290 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009291 const xmlChar *ref = NULL, *refNs = NULL;
9292 int min, max;
9293
9294 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009295 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009296
9297 attr = xmlSchemaGetPropNode(node, "ref");
9298 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009299 xmlSchemaPMissingAttrErr(ctxt,
9300 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009301 NULL, node, "ref", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009302 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009303 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009304 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009305 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009306 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009307 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009308 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009309 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009310 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009311 /*
9312 * Check for illegal attributes.
9313 */
9314 attr = node->properties;
9315 while (attr != NULL) {
9316 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009317 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009318 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9319 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9320 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009321 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009322 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009323 }
9324 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009325 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009326 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009327 }
9328 attr = attr->next;
9329 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009330 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009331 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
9332 if (item == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009333 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009334 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009335 * Create a qname-reference and set as the term; it will be substituted
9336 * for the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009337 */
9338 item->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009339 xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009340 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9341 /*
9342 * And now for the children...
9343 */
9344 child = node->children;
9345 /* TODO: Is annotation even allowed for a model group reference? */
9346 if (IS_SCHEMA(child, "annotation")) {
9347 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009348 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009349 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009350 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009351 child = child->next;
9352 }
9353 if (child != NULL) {
9354 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009355 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009356 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009357 "(annotation?)");
9358 }
9359 /*
9360 * Corresponds to no component at all if minOccurs==maxOccurs==0.
9361 */
9362 if ((min == 0) && (max == 0))
9363 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009364
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009365 return ((xmlSchemaTreeItemPtr) item);
9366}
9367
9368/**
9369 * xmlSchemaParseModelGroupDefinition:
9370 * @ctxt: a schema validation context
9371 * @schema: the schema being built
9372 * @node: a subtree containing XML Schema informations
9373 *
9374 * Parses a XML schema model group definition.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009375 *
9376 * Note that the contraint src-redefine (6.2) can't be applied until
9377 * references have been resolved. So we will do this at the
9378 * component fixup level.
9379 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009380 * *WARNING* this interface is highly subject to change
9381 *
9382 * Returns -1 in case of error, 0 if the declaration is improper and
9383 * 1 in case of success.
9384 */
9385static xmlSchemaModelGroupDefPtr
9386xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9387 xmlSchemaPtr schema,
9388 xmlNodePtr node)
9389{
9390 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009391 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009392 xmlAttrPtr attr;
9393 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00009394
9395 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009396 return (NULL);
9397
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009398 attr = xmlSchemaGetPropNode(node, "name");
9399 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009400 xmlSchemaPMissingAttrErr(ctxt,
9401 XML_SCHEMAP_S4S_ATTR_MISSING,
9402 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009403 "name", NULL);
9404 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009405 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009406 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9407 return (NULL);
9408 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009409 item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9410 ctxt->targetNamespace, node);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009411 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009412 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009413 /*
9414 * Check for illegal attributes.
9415 */
9416 attr = node->properties;
9417 while (attr != NULL) {
9418 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009419 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009420 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009421 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009422 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009423 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009424 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009425 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009426 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009427 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009428 attr = attr->next;
9429 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009430 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009431 /*
9432 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009433 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009434 child = node->children;
9435 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009436 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009437 child = child->next;
9438 }
9439 if (IS_SCHEMA(child, "all")) {
9440 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9441 XML_SCHEMA_TYPE_ALL, 0);
9442 child = child->next;
9443 } else if (IS_SCHEMA(child, "choice")) {
9444 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9445 XML_SCHEMA_TYPE_CHOICE, 0);
9446 child = child->next;
9447 } else if (IS_SCHEMA(child, "sequence")) {
9448 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9449 XML_SCHEMA_TYPE_SEQUENCE, 0);
9450 child = child->next;
9451 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009452
9453
9454
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009455 if (child != NULL) {
9456 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009457 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009458 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009459 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009460 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009461 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009462}
9463
9464/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009465 * xmlSchemaCleanupDoc:
9466 * @ctxt: a schema validation context
9467 * @node: the root of the document.
9468 *
9469 * removes unwanted nodes in a schemas document tree
9470 */
9471static void
9472xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9473{
9474 xmlNodePtr delete, cur;
9475
9476 if ((ctxt == NULL) || (root == NULL)) return;
9477
9478 /*
9479 * Remove all the blank text nodes
9480 */
9481 delete = NULL;
9482 cur = root;
9483 while (cur != NULL) {
9484 if (delete != NULL) {
9485 xmlUnlinkNode(delete);
9486 xmlFreeNode(delete);
9487 delete = NULL;
9488 }
9489 if (cur->type == XML_TEXT_NODE) {
9490 if (IS_BLANK_NODE(cur)) {
9491 if (xmlNodeGetSpacePreserve(cur) != 1) {
9492 delete = cur;
9493 }
9494 }
9495 } else if ((cur->type != XML_ELEMENT_NODE) &&
9496 (cur->type != XML_CDATA_SECTION_NODE)) {
9497 delete = cur;
9498 goto skip_children;
9499 }
9500
9501 /*
9502 * Skip to next node
9503 */
9504 if (cur->children != NULL) {
9505 if ((cur->children->type != XML_ENTITY_DECL) &&
9506 (cur->children->type != XML_ENTITY_REF_NODE) &&
9507 (cur->children->type != XML_ENTITY_NODE)) {
9508 cur = cur->children;
9509 continue;
9510 }
9511 }
9512 skip_children:
9513 if (cur->next != NULL) {
9514 cur = cur->next;
9515 continue;
9516 }
9517
9518 do {
9519 cur = cur->parent;
9520 if (cur == NULL)
9521 break;
9522 if (cur == root) {
9523 cur = NULL;
9524 break;
9525 }
9526 if (cur->next != NULL) {
9527 cur = cur->next;
9528 break;
9529 }
9530 } while (cur != NULL);
9531 }
9532 if (delete != NULL) {
9533 xmlUnlinkNode(delete);
9534 xmlFreeNode(delete);
9535 delete = NULL;
9536 }
9537}
9538
William M. Brack2f2a6632004-08-20 23:09:47 +00009539
William M. Brack2f2a6632004-08-20 23:09:47 +00009540static void
9541xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9542{
9543 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9544 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9545
9546 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9547 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9548
9549 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9550 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9551 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9552 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9553 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9554 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9555 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9556 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9557
9558 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9559 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9560 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9561 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9562 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9563 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9564}
9565
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009566static int
9567xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009568 xmlSchemaPtr schema,
9569 xmlNodePtr node)
9570{
9571 xmlAttrPtr attr;
9572 const xmlChar *val;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009573 int res = 0, oldErrs = ctxt->nberrors;
William M. Brack2f2a6632004-08-20 23:09:47 +00009574
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009575 /*
9576 * Those flags should be moved to the parser context flags,
9577 * since they are not visible at the component level. I.e.
9578 * they are used if processing schema *documents* only.
9579 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009580 res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009581 HFAILURE;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009582
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009583 /*
9584 * Since the version is of type xs:token, we won't bother to
9585 * check it.
9586 */
9587 /* REMOVED:
9588 attr = xmlSchemaGetPropNode(node, "version");
9589 if (attr != NULL) {
9590 res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9591 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9592 HFAILURE;
9593 }
9594 */
9595 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9596 if (attr != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009597 res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009598 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9599 HFAILURE;
9600 if (res != 0) {
9601 ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9602 goto exit;
9603 }
9604 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009605 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009606 if (attr != NULL) {
9607 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009608 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9609 XML_SCHEMAS_QUALIF_ELEM);
9610 HFAILURE;
9611 if (res != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009612 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009613 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009614 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009615 "(qualified | unqualified)", val, NULL, NULL, NULL);
9616 }
9617 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009618 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009619 if (attr != NULL) {
9620 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009621 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9622 XML_SCHEMAS_QUALIF_ATTR);
9623 HFAILURE;
9624 if (res != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009625 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009626 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009627 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009628 "(qualified | unqualified)", val, NULL, NULL, NULL);
9629 }
9630 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009631 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009632 if (attr != NULL) {
9633 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009634 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
William M. Brack2f2a6632004-08-20 23:09:47 +00009635 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9636 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9637 -1,
9638 XML_SCHEMAS_FINAL_DEFAULT_LIST,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009639 XML_SCHEMAS_FINAL_DEFAULT_UNION);
9640 HFAILURE;
9641 if (res != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009642 xmlSchemaPSimpleTypeErr(ctxt,
9643 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009644 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009645 "(#all | List of (extension | restriction | list | union))",
9646 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009647 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009648 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009649 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009650 if (attr != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009651 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9652 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
William M. Brack2f2a6632004-08-20 23:09:47 +00009653 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9654 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009655 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9656 HFAILURE;
9657 if (res != 0) {
9658 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009659 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009660 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009661 "(#all | List of (extension | restriction | substitution))",
9662 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009663 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009664 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009665
9666exit:
9667 if (oldErrs != ctxt->nberrors)
9668 res = ctxt->err;
9669 return(res);
9670exit_failure:
9671 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009672}
9673
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009674/**
9675 * xmlSchemaParseSchemaTopLevel:
9676 * @ctxt: a schema validation context
9677 * @schema: the schemas
9678 * @nodes: the list of top level nodes
9679 *
9680 * Returns the internal XML Schema structure built from the resource or
9681 * NULL in case of error
9682 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009683static int
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009684xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9685 xmlSchemaPtr schema, xmlNodePtr nodes)
9686{
9687 xmlNodePtr child;
9688 xmlSchemaAnnotPtr annot;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009689 int res = 0, oldErrs, tmpOldErrs;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009690
9691 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009692 return(-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009693
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009694 oldErrs = ctxt->nberrors;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009695 child = nodes;
9696 while ((IS_SCHEMA(child, "include")) ||
9697 (IS_SCHEMA(child, "import")) ||
9698 (IS_SCHEMA(child, "redefine")) ||
9699 (IS_SCHEMA(child, "annotation"))) {
9700 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009701 annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009702 if (schema->annot == NULL)
9703 schema->annot = annot;
9704 else
9705 xmlSchemaFreeAnnot(annot);
9706 } else if (IS_SCHEMA(child, "import")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009707 tmpOldErrs = ctxt->nberrors;
9708 res = xmlSchemaParseImport(ctxt, schema, child);
9709 HFAILURE;
9710 HSTOP(ctxt);
9711 if (tmpOldErrs != ctxt->nberrors)
9712 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009713 } else if (IS_SCHEMA(child, "include")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009714 tmpOldErrs = ctxt->nberrors;
9715 res = xmlSchemaParseInclude(ctxt, schema, child);
9716 HFAILURE;
9717 HSTOP(ctxt);
9718 if (tmpOldErrs != ctxt->nberrors)
9719 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009720 } else if (IS_SCHEMA(child, "redefine")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009721 tmpOldErrs = ctxt->nberrors;
9722 res = xmlSchemaParseRedefine(ctxt, schema, child);
9723 HFAILURE;
9724 HSTOP(ctxt);
9725 if (tmpOldErrs != ctxt->nberrors)
9726 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009727 }
9728 child = child->next;
9729 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009730 /*
9731 * URGENT TODO: Change the functions to return int results.
9732 * We need especially to catch internal errors.
9733 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009734 while (child != NULL) {
9735 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009736 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009737 child = child->next;
9738 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009739 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009740 child = child->next;
9741 } else if (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009742 xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009743 child = child->next;
9744 } else if (IS_SCHEMA(child, "attribute")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009745 xmlSchemaParseGlobalAttribute(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009746 child = child->next;
9747 } else if (IS_SCHEMA(child, "attributeGroup")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009748 xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009749 child = child->next;
9750 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009751 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009752 child = child->next;
9753 } else if (IS_SCHEMA(child, "notation")) {
9754 xmlSchemaParseNotation(ctxt, schema, child);
9755 child = child->next;
9756 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009757 xmlSchemaPContentErr(ctxt,
9758 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009759 NULL, child->parent, child,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009760 NULL, "((include | import | redefine | annotation)*, "
9761 "(((simpleType | complexType | group | attributeGroup) "
9762 "| element | attribute | notation), annotation*)*)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009763 child = child->next;
9764 }
9765 while (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009766 /*
9767 * TODO: We should add all annotations.
9768 */
9769 annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009770 if (schema->annot == NULL)
9771 schema->annot = annot;
9772 else
9773 xmlSchemaFreeAnnot(annot);
9774 child = child->next;
9775 }
9776 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009777exit:
Daniel Veillard01fa6152004-06-29 17:04:39 +00009778 ctxt->ctxtType = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009779 if (oldErrs != ctxt->nberrors)
9780 res = ctxt->err;
9781 return(res);
9782exit_failure:
9783 return(-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009784}
9785
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009786static xmlSchemaSchemaRelationPtr
9787xmlSchemaSchemaRelationCreate(void)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009788{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009789 xmlSchemaSchemaRelationPtr ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009790
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009791 ret = (xmlSchemaSchemaRelationPtr)
9792 xmlMalloc(sizeof(xmlSchemaSchemaRelation));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009793 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009794 xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009795 return(NULL);
9796 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009797 memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009798 return(ret);
9799}
9800
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009801#if 0
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009802static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009803xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009804{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009805 xmlFree(rel);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009806}
9807#endif
9808
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009809static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009810xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9811{
9812 xmlSchemaRedefPtr prev;
9813
9814 while (redef != NULL) {
9815 prev = redef;
9816 redef = redef->next;
9817 xmlFree(prev);
9818 }
9819}
9820
9821static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009822xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9823{
9824 /*
9825 * After the construction context has been freed, there will be
9826 * no schema graph available any more. Only the schema buckets
9827 * will stay alive, which are put into the "schemasImports" and
9828 * "includes" slots of the xmlSchema.
9829 */
9830 if (con->buckets != NULL)
9831 xmlSchemaItemListFree(con->buckets);
9832 if (con->pending != NULL)
9833 xmlSchemaItemListFree(con->pending);
9834 if (con->substGroups != NULL)
9835 xmlHashFree(con->substGroups,
9836 (xmlHashDeallocator) xmlSchemaSubstGroupFree);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009837 if (con->redefs != NULL)
9838 xmlSchemaRedefListFree(con->redefs);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009839 if (con->dict != NULL)
9840 xmlDictFree(con->dict);
9841 xmlFree(con);
9842}
9843
9844static xmlSchemaConstructionCtxtPtr
9845xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9846{
9847 xmlSchemaConstructionCtxtPtr ret;
9848
9849 ret = (xmlSchemaConstructionCtxtPtr)
9850 xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9851 if (ret == NULL) {
9852 xmlSchemaPErrMemory(NULL,
9853 "allocating schema construction context", NULL);
9854 return (NULL);
9855 }
9856 memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9857
9858 ret->buckets = xmlSchemaItemListCreate();
9859 if (ret->buckets == NULL) {
9860 xmlSchemaPErrMemory(NULL,
9861 "allocating list of schema buckets", NULL);
9862 xmlFree(ret);
9863 return (NULL);
9864 }
9865 ret->pending = xmlSchemaItemListCreate();
9866 if (ret->pending == NULL) {
9867 xmlSchemaPErrMemory(NULL,
9868 "allocating list of pending global components", NULL);
9869 xmlSchemaConstructionCtxtFree(ret);
9870 return (NULL);
9871 }
9872 ret->dict = dict;
9873 xmlDictReference(dict);
9874 return(ret);
9875}
9876
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009877static xmlSchemaParserCtxtPtr
9878xmlSchemaParserCtxtCreate(void)
9879{
9880 xmlSchemaParserCtxtPtr ret;
9881
9882 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9883 if (ret == NULL) {
9884 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9885 NULL);
9886 return (NULL);
9887 }
9888 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9889 ret->type = XML_SCHEMA_CTXT_PARSER;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009890 ret->attrProhibs = xmlSchemaItemListCreate();
9891 if (ret->attrProhibs == NULL) {
9892 xmlFree(ret);
9893 return(NULL);
9894 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009895 return(ret);
9896}
9897
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009898/**
9899 * xmlSchemaNewParserCtxtUseDict:
9900 * @URL: the location of the schema
9901 * @dict: the dictionary to be used
9902 *
9903 * Create an XML Schemas parse context for that file/resource expected
9904 * to contain an XML Schemas file.
9905 *
9906 * Returns the parser context or NULL in case of error
9907 */
9908static xmlSchemaParserCtxtPtr
9909xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9910{
9911 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009912
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009913 ret = xmlSchemaParserCtxtCreate();
9914 if (ret == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009915 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009916 ret->dict = dict;
9917 xmlDictReference(dict);
9918 if (URL != NULL)
9919 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009920 return (ret);
9921}
9922
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009923static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009924xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
9925{
9926 if (vctxt->pctxt == NULL) {
9927 if (vctxt->schema != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009928 vctxt->pctxt =
9929 xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009930 else
9931 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
9932 if (vctxt->pctxt == NULL) {
9933 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
9934 "failed to create a temp. parser context");
9935 return (-1);
9936 }
9937 /* TODO: Pass user data. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009938 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
9939 vctxt->warning, vctxt->userData);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009940 }
9941 return (0);
9942}
9943
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009944/**
9945 * xmlSchemaGetSchemaBucket:
9946 * @pctxt: the schema parser context
9947 * @schemaLocation: the URI of the schema document
9948 *
9949 * Returns a schema bucket if it was already parsed.
9950 *
9951 * Returns a schema bucket if it was already parsed from
9952 * @schemaLocation, NULL otherwise.
9953 */
9954static xmlSchemaBucketPtr
9955xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
9956 const xmlChar *schemaLocation)
9957{
9958 xmlSchemaBucketPtr cur;
9959 xmlSchemaItemListPtr list;
9960
9961 list = pctxt->constructor->buckets;
9962 if (list->nbItems == 0)
9963 return(NULL);
9964 else {
9965 int i;
9966 for (i = 0; i < list->nbItems; i++) {
9967 cur = (xmlSchemaBucketPtr) list->items[i];
9968 /* Pointer comparison! */
9969 if (cur->schemaLocation == schemaLocation)
9970 return(cur);
9971 }
9972 }
9973 return(NULL);
9974}
9975
9976static xmlSchemaBucketPtr
9977xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
9978 const xmlChar *schemaLocation,
9979 const xmlChar *targetNamespace)
9980{
9981 xmlSchemaBucketPtr cur;
9982 xmlSchemaItemListPtr list;
9983
9984 list = pctxt->constructor->buckets;
9985 if (list->nbItems == 0)
9986 return(NULL);
9987 else {
9988 int i;
9989 for (i = 0; i < list->nbItems; i++) {
9990 cur = (xmlSchemaBucketPtr) list->items[i];
9991 /* Pointer comparison! */
9992 if ((cur->origTargetNamespace == NULL) &&
9993 (cur->schemaLocation == schemaLocation) &&
9994 (cur->targetNamespace == targetNamespace))
9995 return(cur);
9996 }
9997 }
9998 return(NULL);
9999}
10000
10001
10002#define IS_BAD_SCHEMA_DOC(b) \
10003 (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10004
10005static xmlSchemaBucketPtr
10006xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10007 const xmlChar *targetNamespace,
10008 int imported)
10009{
10010 xmlSchemaBucketPtr cur;
10011 xmlSchemaItemListPtr list;
10012
10013 list = pctxt->constructor->buckets;
10014 if (list->nbItems == 0)
10015 return(NULL);
10016 else {
10017 int i;
10018 for (i = 0; i < list->nbItems; i++) {
10019 cur = (xmlSchemaBucketPtr) list->items[i];
10020 if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10021 (cur->origTargetNamespace == targetNamespace) &&
10022 ((imported && cur->imported) ||
10023 ((!imported) && (!cur->imported))))
10024 return(cur);
10025 }
10026 }
10027 return(NULL);
10028}
10029
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010030static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010031xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10032 xmlSchemaPtr schema,
10033 xmlSchemaBucketPtr bucket)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010034{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010035 int oldFlags;
10036 xmlDocPtr oldDoc;
10037 xmlNodePtr node;
10038 int ret, oldErrs;
10039 xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10040
10041 /*
10042 * Save old values; reset the *main* schema.
10043 * URGENT TODO: This is not good; move the per-document information
10044 * to the parser.
10045 */
10046 oldFlags = schema->flags;
10047 oldDoc = schema->doc;
10048 if (schema->flags != 0)
10049 xmlSchemaClearSchemaDefaults(schema);
10050 schema->doc = bucket->doc;
10051 /* !! REMOVED: schema->targetNamespace = bucket->targetNamespace; */
10052 pctxt->schema = schema;
10053 /*
10054 * Keep the current target namespace on the parser *not* on the
10055 * main schema.
10056 */
10057 pctxt->targetNamespace = bucket->targetNamespace;
10058 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010059
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010060 if ((bucket->targetNamespace != NULL) &&
10061 xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010062 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010063 * We are parsing the schema for schemas!
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010064 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010065 pctxt->isS4S = 1;
10066 }
10067 /* Mark it as parsed, even if parsing fails. */
10068 bucket->parsed++;
10069 /* Compile the schema doc. */
10070 node = xmlDocGetRootElement(bucket->doc);
10071 ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10072 if (ret != 0)
10073 goto exit;
10074 /* An empty schema; just get out. */
10075 if (node->children == NULL)
10076 goto exit;
10077 oldErrs = pctxt->nberrors;
10078 ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10079 if (ret != 0)
10080 goto exit;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010081 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010082 * TODO: Not nice, but I'm not 100% sure we will get always an error
10083 * as a result of the obove functions; so better rely on pctxt->err
10084 * as well.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010085 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010086 if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10087 ret = pctxt->err;
10088 goto exit;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010089 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010090
10091exit:
10092 WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10093 /* Restore schema values. */
10094 schema->doc = oldDoc;
10095 schema->flags = oldFlags;
10096 return(ret);
10097}
10098
10099static int
10100xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10101 xmlSchemaPtr schema,
10102 xmlSchemaBucketPtr bucket)
10103{
10104 xmlSchemaParserCtxtPtr newpctxt;
10105 int res = 0;
10106
10107 if (bucket == NULL)
10108 return(0);
10109 if (bucket->parsed) {
10110 PERROR_INT("xmlSchemaParseNewDoc",
10111 "reparsing a schema doc");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010112 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010113 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010114 if (bucket->doc == NULL) {
10115 PERROR_INT("xmlSchemaParseNewDoc",
10116 "parsing a schema doc, but there's no doc");
10117 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000010118 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010119 if (pctxt->constructor == NULL) {
10120 PERROR_INT("xmlSchemaParseNewDoc",
10121 "no constructor");
10122 return(-1);
10123 }
10124 /* Create and init the temporary parser context. */
10125 newpctxt = xmlSchemaNewParserCtxtUseDict(
10126 (const char *) bucket->schemaLocation, pctxt->dict);
10127 if (newpctxt == NULL)
10128 return(-1);
10129 newpctxt->constructor = pctxt->constructor;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010130 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010131 * TODO: Can we avoid that the parser knows about the main schema?
10132 * It would be better if he knows about the current schema bucket
10133 * only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010134 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010135 newpctxt->schema = schema;
10136 xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10137 pctxt->userData);
10138 newpctxt->counter = pctxt->counter;
10139
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010140
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010141 res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10142
10143 /* Channel back errors and cleanup the temporary parser context. */
10144 if (res != 0)
10145 pctxt->err = res;
10146 pctxt->nberrors += newpctxt->nberrors;
10147 pctxt->counter = newpctxt->counter;
10148 newpctxt->constructor = NULL;
10149 /* Free the parser context. */
10150 xmlSchemaFreeParserCtxt(newpctxt);
10151 return(res);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010152}
William M. Brack2f2a6632004-08-20 23:09:47 +000010153
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010154static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010155xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10156 xmlSchemaSchemaRelationPtr rel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010157{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010158 xmlSchemaSchemaRelationPtr cur = bucket->relations;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010159
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010160 if (cur == NULL) {
10161 bucket->relations = rel;
10162 return;
10163 }
10164 while (cur->next != NULL)
10165 cur = cur->next;
10166 cur->next = rel;
10167}
10168
10169
10170static const xmlChar *
10171xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10172 xmlNodePtr ctxtNode)
10173{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010174 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010175 * Build an absolue location URI.
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010176 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010177 if (location != NULL) {
10178 if (ctxtNode == NULL)
10179 return(location);
10180 else {
10181 xmlChar *base, *URI;
10182 const xmlChar *ret = NULL;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010183
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010184 base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10185 if (base == NULL) {
10186 URI = xmlBuildURI(location, ctxtNode->doc->URL);
10187 } else {
10188 URI = xmlBuildURI(location, base);
10189 xmlFree(base);
10190 }
10191 if (URI != NULL) {
10192 ret = xmlDictLookup(dict, URI, -1);
10193 xmlFree(URI);
10194 return(ret);
10195 }
10196 }
10197 }
10198 return(NULL);
10199}
10200
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010201
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010202
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010203/**
10204 * xmlSchemaAddSchemaDoc:
10205 * @pctxt: a schema validation context
10206 * @schema: the schema being built
10207 * @node: a subtree containing XML Schema informations
10208 *
10209 * Parse an included (and to-be-redefined) XML schema document.
10210 *
10211 * Returns 0 on success, a positive error code on errors and
10212 * -1 in case of an internal or API error.
10213 */
10214
10215static int
10216xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10217 int type, /* import or include or redefine */
10218 const xmlChar *schemaLocation,
10219 xmlDocPtr schemaDoc,
10220 const char *schemaBuffer,
10221 int schemaBufferLen,
10222 xmlNodePtr invokingNode,
10223 const xmlChar *sourceTargetNamespace,
10224 const xmlChar *importNamespace,
10225 xmlSchemaBucketPtr *bucket)
10226{
10227 const xmlChar *targetNamespace = NULL;
10228 xmlSchemaSchemaRelationPtr relation = NULL;
10229 xmlDocPtr doc = NULL;
10230 int res = 0, err = 0, located = 0, preserveDoc = 0;
10231 xmlSchemaBucketPtr bkt = NULL;
10232
10233 if (bucket != NULL)
10234 *bucket = NULL;
10235
10236 switch (type) {
10237 case XML_SCHEMA_SCHEMA_IMPORT:
10238 case XML_SCHEMA_SCHEMA_MAIN:
10239 err = XML_SCHEMAP_SRC_IMPORT;
10240 break;
10241 case XML_SCHEMA_SCHEMA_INCLUDE:
10242 err = XML_SCHEMAP_SRC_INCLUDE;
10243 break;
10244 case XML_SCHEMA_SCHEMA_REDEFINE:
10245 err = XML_SCHEMAP_SRC_REDEFINE;
10246 break;
10247 }
10248
10249
10250 /* Special handling for the main schema:
10251 * skip the location and relation logic and just parse the doc.
10252 * We need just a bucket to be returned in this case.
10253 */
10254 if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10255 goto doc_load;
10256
10257 /* Note that we expect the location to be an absulute URI. */
10258 if (schemaLocation != NULL) {
10259 bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10260 if ((bkt != NULL) &&
10261 (pctxt->constructor->bucket == bkt)) {
10262 /* Report self-imports/inclusions/redefinitions. */
10263
10264 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10265 invokingNode, NULL,
10266 "The schema must not import/include/redefine itself",
10267 NULL, NULL);
10268 goto exit;
10269 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010270 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010271 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010272 * Create a relation for the graph of schemas.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010273 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010274 relation = xmlSchemaSchemaRelationCreate();
10275 if (relation == NULL)
10276 return(-1);
10277 xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10278 relation);
10279 relation->type = type;
10280
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010281 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010282 * Save the namespace import information.
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010283 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010284 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010285 relation->importNamespace = importNamespace;
10286 if (schemaLocation == NULL) {
10287 /*
10288 * No location; this is just an import of the namespace.
10289 * Note that we don't assign a bucket to the relation
10290 * in this case.
10291 */
10292 goto exit;
10293 }
10294 targetNamespace = importNamespace;
10295 }
10296
10297 /* Did we already fetch the doc? */
10298 if (bkt != NULL) {
10299 /* TODO: The following nasty cases will produce an error. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010300 if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010301 /* We included/redefined and then try to import a schema. */
10302 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10303 invokingNode, NULL,
10304 "The schema document '%s' cannot be imported, since "
10305 "it was already included or redefined",
10306 schemaLocation, NULL);
10307 goto exit;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010308 } else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010309 /* We imported and then try to include/redefine a schema. */
10310 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10311 invokingNode, NULL,
10312 "The schema document '%s' cannot be included or "
10313 "redefined, since it was already imported",
10314 schemaLocation, NULL);
10315 goto exit;
10316 }
10317 }
10318
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010319 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010320 /*
10321 * Given that the schemaLocation [attribute] is only a hint, it is open
10322 * to applications to ignore all but the first <import> for a given
10323 * namespace, regardless of the ·actual value· of schemaLocation, but
10324 * such a strategy risks missing useful information when new
10325 * schemaLocations are offered.
10326 *
10327 * We will use the first <import> that comes with a location.
10328 * Further <import>s *with* a location, will result in an error.
10329 * TODO: Better would be to just report a warning here, but
10330 * we'll try it this way until someone complains.
10331 *
10332 * Schema Document Location Strategy:
10333 * 3 Based on the namespace name, identify an existing schema document,
10334 * either as a resource which is an XML document or a <schema> element
10335 * information item, in some local schema repository;
10336 * 5 Attempt to resolve the namespace name to locate such a resource.
10337 *
10338 * NOTE: (3) and (5) are not supported.
10339 */
10340 if (bkt != NULL) {
10341 relation->bucket = bkt;
10342 goto exit;
10343 }
10344 bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10345 importNamespace, 1);
10346
10347 if (bkt != NULL) {
10348 relation->bucket = bkt;
10349 if (bkt->schemaLocation == NULL) {
10350 /* First given location of the schema; load the doc. */
10351 bkt->schemaLocation = schemaLocation;
10352 } else {
10353 if (!xmlStrEqual(schemaLocation,
10354 bkt->schemaLocation)) {
10355 /*
10356 * Additional location given; just skip it.
10357 * URGENT TODO: We should report a warning here.
10358 * res = XML_SCHEMAP_SRC_IMPORT;
10359 */
10360 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10361 XML_SCHEMAP_WARN_SKIP_SCHEMA,
10362 invokingNode, NULL,
10363 "Skipping import of schema located at '%s' for the "
10364 "namespace '%s', since this namespace was already "
10365 "imported with the schema located at '%s'",
10366 schemaLocation, importNamespace, bkt->schemaLocation);
10367 }
10368 goto exit;
10369 }
10370 }
10371 /*
10372 * No bucket + first location: load the doc and create a
10373 * bucket.
10374 */
10375 } else {
10376 /* <include> and <redefine> */
10377 if (bkt != NULL) {
10378
10379 if ((bkt->origTargetNamespace == NULL) &&
10380 (bkt->targetNamespace != sourceTargetNamespace)) {
10381 xmlSchemaBucketPtr chamel;
10382
10383 /*
10384 * Chameleon include/redefine: skip loading only if it was
10385 * aleady build for the targetNamespace of the including
10386 * schema.
10387 */
10388 /*
10389 * URGENT TODO: If the schema is a chameleon-include then copy
10390 * the components into the including schema and modify the
10391 * targetNamespace of those components, do nothing otherwise.
10392 * NOTE: This is currently worked-around by compiling the
10393 * chameleon for every destinct including targetNamespace; thus
10394 * not performant at the moment.
10395 * TODO: Check when the namespace in wildcards for chameleons
10396 * needs to be converted: before we built wildcard intersections
10397 * or after.
10398 * Answer: after!
10399 */
10400 chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10401 schemaLocation, sourceTargetNamespace);
10402 if (chamel != NULL) {
10403 /* A fitting chameleon was already parsed; NOP. */
10404 relation->bucket = chamel;
10405 goto exit;
10406 }
10407 /*
10408 * We need to parse the chameleon again for a different
10409 * targetNamespace.
10410 * CHAMELEON TODO: Optimize this by only parsing the
10411 * chameleon once, and then copying the components to
10412 * the new targetNamespace.
10413 */
10414 bkt = NULL;
10415 } else {
10416 relation->bucket = bkt;
10417 goto exit;
10418 }
10419 }
10420 }
10421 if ((bkt != NULL) && (bkt->doc != NULL)) {
10422 PERROR_INT("xmlSchemaAddSchemaDoc",
10423 "trying to load a schema doc, but a doc is already "
10424 "assigned to the schema bucket");
10425 goto exit_failure;
10426 }
10427
10428doc_load:
10429 /*
10430 * Load the document.
10431 */
10432 if (schemaDoc != NULL) {
10433 doc = schemaDoc;
10434 /* Don' free this one, since it was provided by the caller. */
10435 preserveDoc = 1;
10436 /* TODO: Does the context or the doc hold the location? */
10437 if (schemaDoc->URL != NULL)
10438 schemaLocation = xmlDictLookup(pctxt->dict,
10439 schemaDoc->URL, -1);
10440
10441 } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10442 xmlParserCtxtPtr parserCtxt;
10443
10444 parserCtxt = xmlNewParserCtxt();
10445 if (parserCtxt == NULL) {
10446 xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10447 "allocating a parser context", NULL);
10448 goto exit_failure;
10449 }
10450 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10451 /*
10452 * TODO: Do we have to burden the schema parser dict with all
10453 * the content of the schema doc?
10454 */
10455 xmlDictFree(parserCtxt->dict);
10456 parserCtxt->dict = pctxt->dict;
10457 xmlDictReference(parserCtxt->dict);
10458 }
10459 if (schemaLocation != NULL) {
10460 /* Parse from file. */
10461 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10462 NULL, SCHEMAS_PARSE_OPTIONS);
10463 } else if (schemaBuffer != NULL) {
10464 /* Parse from memory buffer. */
10465 doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10466 NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10467 schemaLocation = xmlStrdup(BAD_CAST "in_memory_buffer");
10468 if (doc != NULL)
10469 doc->URL = schemaLocation;
10470 }
10471 /*
10472 * For <import>:
10473 * 2.1 The referent is (a fragment of) a resource which is an
10474 * XML document (see clause 1.1), which in turn corresponds to
10475 * a <schema> element information item in a well-formed information
10476 * set, which in turn corresponds to a valid schema.
10477 * TODO: (2.1) fragments of XML documents are not supported.
10478 *
10479 * 2.2 The referent is a <schema> element information item in
10480 * a well-formed information set, which in turn corresponds
10481 * to a valid schema.
10482 * TODO: (2.2) is not supported.
10483 */
10484 if (doc == NULL) {
10485 xmlErrorPtr lerr;
10486 lerr = xmlGetLastError();
10487 /*
10488 * Check if this a parser error, or if the document could
10489 * just not be located.
10490 * TODO: Try to find specific error codes to react only on
10491 * localisation failures.
10492 */
10493 if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10494 /*
10495 * We assume a parser error here.
10496 */
10497 located = 1;
10498 /* TODO: Error code ?? */
10499 res = XML_SCHEMAP_SRC_IMPORT_2_1;
10500 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10501 invokingNode, NULL,
10502 "Failed to parse the XML resource '%s'",
10503 schemaLocation, NULL);
10504 }
10505 }
10506 xmlFreeParserCtxt(parserCtxt);
10507 if ((doc == NULL) && located)
10508 goto exit_error;
10509 } else {
10510 xmlSchemaPErr(pctxt, NULL,
10511 XML_SCHEMAP_NOTHING_TO_PARSE,
10512 "No information for parsing was provided with the "
10513 "given schema parser context.\n",
10514 NULL, NULL);
10515 goto exit_failure;
10516 }
10517 /*
10518 * Preprocess the document.
10519 */
10520 if (doc != NULL) {
10521 xmlNodePtr docElem = NULL;
10522
10523 located = 1;
10524 docElem = xmlDocGetRootElement(doc);
10525 if (docElem == NULL) {
10526 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10527 invokingNode, NULL,
10528 "The document '%s' has no document element",
10529 schemaLocation, NULL);
10530 xmlFreeDoc(doc);
10531 doc = NULL;
10532 goto exit_error;
10533 }
10534 /*
10535 * Remove all the blank text nodes.
10536 */
10537 xmlSchemaCleanupDoc(pctxt, docElem);
10538 /*
10539 * Check the schema's top level element.
10540 */
10541 if (!IS_SCHEMA(docElem, "schema")) {
10542 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10543 invokingNode, NULL,
10544 "The XML document '%s' is not a schema document",
10545 schemaLocation, NULL);
10546 xmlFreeDoc(doc);
10547 doc = NULL;
10548 goto exit_error;
10549 }
10550 /*
10551 * Note that we don't apply a type check for the
10552 * targetNamespace value here.
10553 */
10554 targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10555 "targetNamespace");
10556 }
10557
10558/* after_doc_loading: */
10559 if ((bkt == NULL) && located) {
10560 /* Only create a bucket if the schema was located. */
10561 bkt = xmlSchemaBucketCreate(pctxt, type,
10562 targetNamespace);
10563 if (bkt == NULL)
10564 goto exit_failure;
10565 }
10566 if (bkt != NULL) {
10567 bkt->schemaLocation = schemaLocation;
10568 bkt->located = located;
10569 if (doc != NULL) {
10570 bkt->doc = doc;
10571 bkt->targetNamespace = targetNamespace;
10572 bkt->origTargetNamespace = targetNamespace;
10573 if (preserveDoc)
10574 bkt->preserveDoc = 1;
10575 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010576 if (WXS_IS_BUCKET_IMPMAIN(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010577 bkt->imported++;
10578 /*
10579 * Add it to the graph of schemas.
10580 */
10581 if (relation != NULL)
10582 relation->bucket = bkt;
10583 }
10584
10585exit:
10586 /*
10587 * Return the bucket explicitely; this is needed for the
10588 * main schema.
10589 */
10590 if (bucket != NULL)
10591 *bucket = bkt;
10592 return (0);
10593
10594exit_error:
10595 if ((doc != NULL) && (! preserveDoc)) {
10596 xmlFreeDoc(doc);
10597 if (bkt != NULL)
10598 bkt->doc = NULL;
10599 }
10600 return(pctxt->err);
10601
10602exit_failure:
10603 if ((doc != NULL) && (! preserveDoc)) {
10604 xmlFreeDoc(doc);
10605 if (bkt != NULL)
10606 bkt->doc = NULL;
10607 }
10608 return (-1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010609}
10610
William M. Brack2f2a6632004-08-20 23:09:47 +000010611/**
10612 * xmlSchemaParseImport:
10613 * @ctxt: a schema validation context
10614 * @schema: the schema being built
10615 * @node: a subtree containing XML Schema informations
10616 *
10617 * parse a XML schema Import definition
10618 * *WARNING* this interface is highly subject to change
10619 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010620 * Returns 0 in case of success, a positive error code if
10621 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +000010622 */
10623static int
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010624xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +000010625 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010626{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010627 xmlNodePtr child;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010628 const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10629 const xmlChar *thisTargetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +000010630 xmlAttrPtr attr;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010631 int ret = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010632 xmlSchemaBucketPtr bucket = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000010633
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010634 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
William M. Brack2f2a6632004-08-20 23:09:47 +000010635 return (-1);
10636
10637 /*
10638 * Check for illegal attributes.
10639 */
10640 attr = node->properties;
10641 while (attr != NULL) {
10642 if (attr->ns == NULL) {
10643 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10644 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10645 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010646 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010647 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010648 }
10649 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010650 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010651 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010652 }
10653 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010654 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010655 /*
10656 * Extract and validate attributes.
10657 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010658 if (xmlSchemaPValAttr(pctxt, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010659 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010660 &namespaceName) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010661 xmlSchemaPSimpleTypeErr(pctxt,
10662 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010663 NULL, node,
10664 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010665 NULL, namespaceName, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010666 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010667 }
10668
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010669 if (xmlSchemaPValAttr(pctxt, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010670 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +000010671 &schemaLocation) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010672 xmlSchemaPSimpleTypeErr(pctxt,
10673 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010674 NULL, node,
10675 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010676 NULL, namespaceName, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010677 return (pctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010678 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010679 /*
10680 * And now for the children...
10681 */
10682 child = node->children;
10683 if (IS_SCHEMA(child, "annotation")) {
10684 /*
10685 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010686 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +000010687 */
10688 child = child->next;
10689 }
10690 if (child != NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010691 xmlSchemaPContentErr(pctxt,
10692 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010693 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010694 "(annotation?)");
10695 }
10696 /*
10697 * Apply additional constraints.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010698 *
10699 * Note that it is important to use the original @targetNamespace
10700 * (or none at all), to rule out imports of schemas _with_ a
10701 * @targetNamespace if the importing schema is a chameleon schema
10702 * (with no @targetNamespace).
William M. Brack2f2a6632004-08-20 23:09:47 +000010703 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010704 thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010705 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000010706 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010707 * 1.1 If the namespace [attribute] is present, then its ·actual value·
10708 * must not match the ·actual value· of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +000010709 * targetNamespace [attribute].
10710 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010711 if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010712 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000010713 XML_SCHEMAP_SRC_IMPORT_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010714 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +000010715 "The value of the attribute 'namespace' must not match "
10716 "the target namespace '%s' of the importing schema",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010717 thisTargetNamespace);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010718 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010719 }
10720 } else {
10721 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010722 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +000010723 * <schema> must have a targetNamespace [attribute].
10724 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010725 if (thisTargetNamespace == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010726 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000010727 XML_SCHEMAP_SRC_IMPORT_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010728 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +000010729 "The attribute 'namespace' must be existent if "
10730 "the importing schema has no target namespace",
10731 NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010732 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010733 }
10734 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010735 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000010736 * Locate and acquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +000010737 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010738 if (schemaLocation != NULL)
10739 schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10740 schemaLocation, node);
10741 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010742 schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010743 namespaceName, &bucket);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010744
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010745 if (ret != 0)
10746 return(ret);
10747
10748 /*
10749 * For <import>: "It is *not* an error for the application
10750 * schema reference strategy to fail."
10751 * So just don't parse if no schema document was found.
10752 * Note that we will get no bucket if the schema could not be
10753 * located or if there was no schemaLocation.
10754 */
10755 if ((bucket == NULL) && (schemaLocation != NULL)) {
10756 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10757 XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10758 node, NULL,
10759 "Failed to locate a schema at location '%s'. "
10760 "Skipping the import", schemaLocation, NULL, NULL);
10761 }
10762
10763 if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10764 ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10765 }
10766
10767 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000010768}
10769
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010770static int
10771xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10772 xmlSchemaPtr schema,
10773 xmlNodePtr node,
10774 xmlChar **schemaLocation,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010775 int type)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010776{
10777 xmlAttrPtr attr;
10778
10779 if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10780 (schemaLocation == NULL))
10781 return (-1);
10782
10783 *schemaLocation = NULL;
10784 /*
10785 * Check for illegal attributes.
10786 * Applies for both <include> and <redefine>.
10787 */
10788 attr = node->properties;
10789 while (attr != NULL) {
10790 if (attr->ns == NULL) {
10791 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10792 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10793 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010794 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010795 }
10796 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10797 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010798 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010799 }
10800 attr = attr->next;
10801 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010802 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010803 /*
10804 * Preliminary step, extract the URI-Reference and make an URI
10805 * from the base.
10806 */
10807 /*
10808 * Attribute "schemaLocation" is mandatory.
10809 */
10810 attr = xmlSchemaGetPropNode(node, "schemaLocation");
10811 if (attr != NULL) {
10812 xmlChar *base = NULL;
10813 xmlChar *uri = NULL;
10814
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010815 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010816 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10817 (const xmlChar **) schemaLocation) != 0)
10818 goto exit_error;
10819 base = xmlNodeGetBase(node->doc, node);
10820 if (base == NULL) {
10821 uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10822 } else {
10823 uri = xmlBuildURI(*schemaLocation, base);
10824 xmlFree(base);
10825 }
10826 if (uri == NULL) {
10827 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10828 "could not build an URI from the schemaLocation")
10829 goto exit_failure;
10830 }
10831 (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10832 xmlFree(uri);
10833 } else {
10834 xmlSchemaPMissingAttrErr(pctxt,
10835 XML_SCHEMAP_S4S_ATTR_MISSING,
10836 NULL, node, "schemaLocation", NULL);
10837 goto exit_error;
10838 }
10839 /*
10840 * Report self-inclusion and self-redefinition.
10841 */
10842 if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010843 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010844 xmlSchemaPCustomErr(pctxt,
10845 XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010846 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010847 "The schema document '%s' cannot redefine itself.",
10848 *schemaLocation);
10849 } else {
10850 xmlSchemaPCustomErr(pctxt,
10851 XML_SCHEMAP_SRC_INCLUDE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010852 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010853 "The schema document '%s' cannot include itself.",
10854 *schemaLocation);
10855 }
10856 goto exit_error;
10857 }
10858
10859 return(0);
10860exit_error:
10861 return(pctxt->err);
10862exit_failure:
10863 return(-1);
10864}
10865
10866static int
10867xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10868 xmlSchemaPtr schema,
10869 xmlNodePtr node,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010870 int type)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010871{
10872 xmlNodePtr child = NULL;
10873 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000010874 int res = 0; /* hasRedefinitions = 0 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010875 int isChameleon = 0, wasChameleon = 0;
10876 xmlSchemaBucketPtr bucket = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010877
10878 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10879 return (-1);
10880
10881 /*
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010882 * Parse attributes. Note that the returned schemaLocation will
10883 * be already converted to an absolute URI.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010884 */
10885 res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010886 node, (xmlChar **) (&schemaLocation), type);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010887 if (res != 0)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010888 return(res);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010889 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010890 * Load and add the schema document.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010891 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010892 res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10893 NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010894 if (res != 0)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010895 return(res);
10896 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010897 * If we get no schema bucket back, then this means that the schema
10898 * document could not be located or was broken XML or was not
10899 * a schema document.
10900 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010901 if ((bucket == NULL) || (bucket->doc == NULL)) {
10902 if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10903 /*
10904 * WARNING for <include>:
10905 * We will raise an error if the schema cannot be located
10906 * for inclusions, since the that was the feedback from the
10907 * schema people. I.e. the following spec piece will *not* be
10908 * satisfied:
10909 * SPEC src-include: "It is not an error for the ·actual value· of the
10910 * schemaLocation [attribute] to fail to resolve it all, in which
10911 * case no corresponding inclusion is performed.
10912 * So do we need a warning report here?"
10913 */
10914 res = XML_SCHEMAP_SRC_INCLUDE;
10915 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10916 node, NULL,
10917 "Failed to load the document '%s' for inclusion",
10918 schemaLocation, NULL);
10919 } else {
10920 /*
10921 * NOTE: This was changed to raise an error even if no redefinitions
10922 * are specified.
10923 *
10924 * SPEC src-redefine (1)
10925 * "If there are any element information items among the [children]
10926 * other than <annotation> then the ·actual value· of the
10927 * schemaLocation [attribute] must successfully resolve."
10928 * TODO: Ask the WG if a the location has always to resolve
10929 * here as well!
10930 */
10931 res = XML_SCHEMAP_SRC_REDEFINE;
10932 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10933 node, NULL,
10934 "Failed to load the document '%s' for redefinition",
10935 schemaLocation, NULL);
10936 }
10937 } else {
10938 /*
10939 * Check targetNamespace sanity before parsing the new schema.
10940 * TODO: Note that we won't check further content if the
10941 * targetNamespace was bad.
10942 */
10943 if (bucket->origTargetNamespace != NULL) {
10944 /*
10945 * SPEC src-include (2.1)
10946 * "SII has a targetNamespace [attribute], and its ·actual
10947 * value· is identical to the ·actual value· of the targetNamespace
10948 * [attribute] of SIIÂ’ (which must have such an [attribute])."
10949 */
10950 if (pctxt->targetNamespace == NULL) {
10951 xmlSchemaCustomErr(ACTXT_CAST pctxt,
10952 XML_SCHEMAP_SRC_INCLUDE,
10953 node, NULL,
10954 "The target namespace of the included/redefined schema "
10955 "'%s' has to be absent, since the including/redefining "
10956 "schema has no target namespace",
10957 schemaLocation, NULL);
10958 goto exit_error;
10959 } else if (!xmlStrEqual(bucket->origTargetNamespace,
10960 pctxt->targetNamespace)) {
10961 /* TODO: Change error function. */
10962 xmlSchemaPCustomErrExt(pctxt,
10963 XML_SCHEMAP_SRC_INCLUDE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010964 NULL, node,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010965 "The target namespace '%s' of the included/redefined "
10966 "schema '%s' differs from '%s' of the "
10967 "including/redefining schema",
10968 bucket->origTargetNamespace, schemaLocation,
10969 pctxt->targetNamespace);
10970 goto exit_error;
10971 }
10972 } else if (pctxt->targetNamespace != NULL) {
10973 /*
10974 * Chameleons: the original target namespace will
10975 * differ from the resulting namespace.
10976 */
10977 isChameleon = 1;
10978 if (bucket->parsed &&
10979 (bucket->targetNamespace != pctxt->targetNamespace)) {
10980 /*
10981 * This is a sanity check, I dunno yet if this can happen.
10982 */
10983 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10984 "trying to use an already parsed schema for a "
10985 "different targetNamespace");
10986 return(-1);
10987 }
10988 bucket->targetNamespace = pctxt->targetNamespace;
10989 }
10990 }
10991 /*
10992 * Parse the schema.
10993 */
10994 if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
10995 if (isChameleon) {
10996 /* TODO: Get rid of this flag on the schema itself. */
10997 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
10998 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
10999 } else
11000 wasChameleon = 1;
11001 }
11002 xmlSchemaParseNewDoc(pctxt, schema, bucket);
11003 /* Restore chameleon flag. */
11004 if (isChameleon && (!wasChameleon))
11005 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11006 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011007 /*
11008 * And now for the children...
11009 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011010 child = node->children;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011011 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011012 /*
11013 * Parse (simpleType | complexType | group | attributeGroup))*
11014 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011015 pctxt->redefined = bucket;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011016 /*
11017 * How to proceed if the redefined schema was not located?
11018 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011019 pctxt->isRedefine = 1;
11020 while (IS_SCHEMA(child, "annotation") ||
11021 IS_SCHEMA(child, "simpleType") ||
11022 IS_SCHEMA(child, "complexType") ||
11023 IS_SCHEMA(child, "group") ||
11024 IS_SCHEMA(child, "attributeGroup")) {
11025 if (IS_SCHEMA(child, "annotation")) {
11026 /*
11027 * TODO: discard or not?
11028 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011029 } else if (IS_SCHEMA(child, "simpleType")) {
11030 xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11031 } else if (IS_SCHEMA(child, "complexType")) {
11032 xmlSchemaParseComplexType(pctxt, schema, child, 1);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011033 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011034 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011035 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011036 xmlSchemaParseModelGroupDefinition(pctxt,
11037 schema, child);
11038 } else if (IS_SCHEMA(child, "attributeGroup")) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011039 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011040 xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11041 child);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011042 }
11043 child = child->next;
11044 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011045 pctxt->redefined = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011046 pctxt->isRedefine = 0;
11047 } else {
11048 if (IS_SCHEMA(child, "annotation")) {
11049 /*
11050 * TODO: discard or not?
11051 */
11052 child = child->next;
11053 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011054 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011055 if (child != NULL) {
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011056 res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011057 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11058 xmlSchemaPContentErr(pctxt, res,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011059 NULL, node, child, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011060 "(annotation | (simpleType | complexType | group | attributeGroup))*");
11061 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011062 xmlSchemaPContentErr(pctxt, res,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011063 NULL, node, child, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011064 "(annotation?)");
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011065 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011066 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011067 return(res);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011068
11069exit_error:
11070 return(pctxt->err);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011071}
11072
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011073static int
11074xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11075 xmlNodePtr node)
11076{
11077 int res;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011078#ifndef ENABLE_REDEFINE
11079 TODO
11080 return(0);
11081#endif
11082 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11083 XML_SCHEMA_SCHEMA_REDEFINE);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011084 if (res != 0)
11085 return(res);
11086 return(0);
11087}
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011088
11089static int
11090xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11091 xmlNodePtr node)
11092{
11093 int res;
11094
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011095 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11096 XML_SCHEMA_SCHEMA_INCLUDE);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011097 if (res != 0)
11098 return(res);
11099 return(0);
11100}
11101
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011102/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011103 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011104 * @ctxt: a schema validation context
11105 * @schema: the schema being built
11106 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011107 * @type: the "compositor" type
11108 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +000011109 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011110 * parse a XML schema Sequence definition.
11111 * Applies parts of:
11112 * Schema Representation Constraint:
11113 * Redefinition Constraints and Semantics (src-redefine)
11114 * (6.1), (6.1.1), (6.1.2)
11115 *
11116 * Schema Component Constraint:
11117 * All Group Limited (cos-all-limited) (2)
11118 * TODO: Actually this should go to component-level checks,
11119 * but is done here due to performance. Move it to an other layer
11120 * is schema construction via an API is implemented.
11121 *
Daniel Veillard4255d502002-04-16 15:50:10 +000011122 * *WARNING* this interface is highly subject to change
11123 *
William M. Bracke7091952004-05-11 15:09:58 +000011124 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +000011125 * 1 in case of success.
11126 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011127static xmlSchemaTreeItemPtr
11128xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11129 xmlNodePtr node, xmlSchemaTypeType type,
11130 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +000011131{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011132 xmlSchemaModelGroupPtr item;
11133 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011134 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000011135 xmlAttrPtr attr;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011136 int min = 1, max = 1, isElemRef, hasRefs = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000011137
11138 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011139 return (NULL);
11140 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011141 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +000011142 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011143 item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011144 if (item == NULL)
11145 return (NULL);
11146
11147 if (withParticle) {
11148 if (type == XML_SCHEMA_TYPE_ALL) {
11149 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011150 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011151 } else {
11152 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011153 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11154 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11155 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011156 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011157 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11158 /*
11159 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011160 */
11161 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
11162 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011163 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011164 particle->children = (xmlSchemaTreeItemPtr) item;
11165 /*
11166 * Check for illegal attributes.
11167 */
11168 attr = node->properties;
11169 while (attr != NULL) {
11170 if (attr->ns == NULL) {
11171 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11172 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11173 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011174 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011175 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011176 }
11177 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011178 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011179 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011180 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011181 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000011182 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011183 } else {
11184 /*
11185 * Check for illegal attributes.
11186 */
11187 attr = node->properties;
11188 while (attr != NULL) {
11189 if (attr->ns == NULL) {
11190 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
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);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011193 }
11194 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011195 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011196 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011197 }
11198 attr = attr->next;
11199 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011200 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011201
William M. Brack2f2a6632004-08-20 23:09:47 +000011202 /*
11203 * Extract and validate attributes.
11204 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011205 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000011206 /*
11207 * And now for the children...
11208 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011209 child = node->children;
11210 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011211 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011212 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011213 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011214 if (type == XML_SCHEMA_TYPE_ALL) {
11215 xmlSchemaParticlePtr part, last = NULL;
11216
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011217 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011218 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011219 schema, child, &isElemRef, 0);
11220 /*
11221 * SPEC cos-all-limited (2)
11222 * "The {max occurs} of all the particles in the {particles}
11223 * of the ('all') group must be 0 or 1.
11224 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011225 if (part != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011226 if (isElemRef)
11227 hasRefs++;
11228 if (part->minOccurs > 1) {
11229 xmlSchemaPCustomErr(ctxt,
11230 XML_SCHEMAP_COS_ALL_LIMITED,
11231 NULL, child,
11232 "Invalid value for minOccurs (must be 0 or 1)",
11233 NULL);
11234 /* Reset to 1. */
11235 part->minOccurs = 1;
11236 }
11237 if (part->maxOccurs > 1) {
11238 xmlSchemaPCustomErr(ctxt,
11239 XML_SCHEMAP_COS_ALL_LIMITED,
11240 NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011241 "Invalid value for maxOccurs (must be 0 or 1)",
11242 NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011243 /* Reset to 1. */
11244 part->maxOccurs = 1;
11245 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011246 if (last == NULL)
11247 item->children = (xmlSchemaTreeItemPtr) part;
11248 else
11249 last->next = (xmlSchemaTreeItemPtr) part;
11250 last = part;
11251 }
11252 child = child->next;
11253 }
11254 if (child != NULL) {
11255 xmlSchemaPContentErr(ctxt,
11256 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011257 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011258 "(annotation?, (annotation?, element*)");
11259 }
11260 } else {
11261 /* choice + sequence */
11262 xmlSchemaTreeItemPtr part = NULL, last = NULL;
11263
11264 while ((IS_SCHEMA(child, "element")) ||
11265 (IS_SCHEMA(child, "group")) ||
11266 (IS_SCHEMA(child, "any")) ||
11267 (IS_SCHEMA(child, "choice")) ||
11268 (IS_SCHEMA(child, "sequence"))) {
11269
11270 if (IS_SCHEMA(child, "element")) {
11271 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011272 xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11273 if (part && isElemRef)
11274 hasRefs++;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011275 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011276 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011277 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011278 if (part != NULL)
11279 hasRefs++;
11280 /*
11281 * Handle redefinitions.
11282 */
11283 if (ctxt->isRedefine && ctxt->redef &&
11284 (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11285 part && part->children)
11286 {
11287 if ((xmlSchemaGetQNameRefName(part->children) ==
11288 ctxt->redef->refName) &&
11289 (xmlSchemaGetQNameRefTargetNs(part->children) ==
11290 ctxt->redef->refTargetNs))
11291 {
11292 /*
11293 * SPEC src-redefine:
11294 * (6.1) "If it has a <group> among its contents at
11295 * some level the ·actual value· of whose ref
11296 * [attribute] is the same as the ·actual value· of
11297 * its own name attribute plus target namespace, then
11298 * all of the following must be true:"
11299 * (6.1.1) "It must have exactly one such group."
11300 */
11301 if (ctxt->redefCounter != 0) {
11302 xmlChar *str = NULL;
11303
11304 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11305 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11306 "The redefining model group definition "
11307 "'%s' must not contain more than one "
11308 "reference to the redefined definition",
11309 xmlSchemaFormatQName(&str,
11310 ctxt->redef->refTargetNs,
11311 ctxt->redef->refName),
11312 NULL);
11313 FREE_AND_NULL(str)
11314 part = NULL;
11315 } else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11316 ((WXS_PARTICLE(part))->maxOccurs != 1))
11317 {
11318 xmlChar *str = NULL;
11319 /*
11320 * SPEC src-redefine:
11321 * (6.1.2) "The ·actual value· of both that
11322 * group's minOccurs and maxOccurs [attribute]
11323 * must be 1 (or ·absent·).
11324 */
11325 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11326 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11327 "The redefining model group definition "
11328 "'%s' must not contain a reference to the "
11329 "redefined definition with a "
11330 "maxOccurs/minOccurs other than 1",
11331 xmlSchemaFormatQName(&str,
11332 ctxt->redef->refTargetNs,
11333 ctxt->redef->refName),
11334 NULL);
11335 FREE_AND_NULL(str)
11336 part = NULL;
11337 }
11338 ctxt->redef->reference = WXS_BASIC_CAST part;
11339 ctxt->redefCounter++;
11340 }
11341 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011342 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011343 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011344 xmlSchemaParseAny(ctxt, schema, child);
11345 } else if (IS_SCHEMA(child, "choice")) {
11346 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11347 XML_SCHEMA_TYPE_CHOICE, 1);
11348 } else if (IS_SCHEMA(child, "sequence")) {
11349 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11350 XML_SCHEMA_TYPE_SEQUENCE, 1);
11351 }
11352 if (part != NULL) {
11353 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011354 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011355 else
11356 last->next = part;
11357 last = part;
11358 }
11359 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011360 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011361 if (child != NULL) {
11362 xmlSchemaPContentErr(ctxt,
11363 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011364 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011365 "(annotation?, (element | group | choice | sequence | any)*)");
11366 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011367 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011368 if ((max == 0) && (min == 0))
11369 return (NULL);
11370 if (hasRefs) {
11371 /*
11372 * We need to resolve references.
11373 */
11374 WXS_ADD_PENDING(ctxt, item);
11375 }
11376 if (withParticle)
11377 return ((xmlSchemaTreeItemPtr) particle);
11378 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011379 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +000011380}
11381
11382/**
11383 * xmlSchemaParseRestriction:
11384 * @ctxt: a schema validation context
11385 * @schema: the schema being built
11386 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +000011387 *
11388 * parse a XML schema Restriction definition
11389 * *WARNING* this interface is highly subject to change
11390 *
11391 * Returns the type definition or NULL in case of error
11392 */
11393static xmlSchemaTypePtr
11394xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011395 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000011396{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011397 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011398 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000011399 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011400
11401 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11402 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011403 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011404 type = ctxt->ctxtType;
11405 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011406
11407 /*
William M. Brack2f2a6632004-08-20 23:09:47 +000011408 * Check for illegal attributes.
11409 */
11410 attr = node->properties;
11411 while (attr != NULL) {
11412 if (attr->ns == NULL) {
11413 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11414 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011415 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011416 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011417 }
11418 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011419 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011420 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011421 }
11422 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011423 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011424 /*
11425 * Extract and validate attributes.
11426 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011427 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000011428 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011429 * Attribute
William M. Brack2f2a6632004-08-20 23:09:47 +000011430 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011431 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011432 * Extract the base type. The "base" attribute is mandatory if inside
11433 * a complex type or if redefining.
11434 *
11435 * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011436 * among its [children]), the simple type definition which is
11437 * the {content type} of the type definition ·resolved· to by
11438 * the ·actual value· of the base [attribute]"
11439 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011440 if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011441 &(type->baseNs), &(type->base)) == 0)
11442 {
11443 if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11444 xmlSchemaPMissingAttrErr(ctxt,
11445 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011446 NULL, node, "base", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011447 } else if ((ctxt->isRedefine) &&
11448 (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11449 {
11450 if (type->base == NULL) {
11451 xmlSchemaPMissingAttrErr(ctxt,
11452 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011453 NULL, node, "base", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011454 } else if ((! xmlStrEqual(type->base, type->name)) ||
11455 (! xmlStrEqual(type->baseNs, type->targetNamespace)))
11456 {
11457 xmlChar *str1 = NULL, *str2 = NULL;
11458 /*
11459 * REDEFINE: SPEC src-redefine (5)
11460 * "Within the [children], each <simpleType> must have a
11461 * <restriction> among its [children] ... the ·actual value· of
11462 * whose base [attribute] must be the same as the ·actual value·
11463 * of its own name attribute plus target namespace;"
11464 */
11465 xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011466 NULL, node, "This is a redefinition, but the QName "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011467 "value '%s' of the 'base' attribute does not match the "
11468 "type's designation '%s'",
11469 xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11470 xmlSchemaFormatQName(&str1, type->targetNamespace,
11471 type->name), NULL);
11472 FREE_AND_NULL(str1);
11473 FREE_AND_NULL(str2);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011474 /* Avoid confusion and erase the values. */
11475 type->base = NULL;
11476 type->baseNs = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011477 }
11478 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011479 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011480 /*
11481 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011482 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011483 child = node->children;
11484 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011485 /*
11486 * Add the annotation to the simple type ancestor.
11487 */
11488 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011489 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011490 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011491 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011492 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11493 /*
11494 * Corresponds to <simpleType><restriction><simpleType>.
11495 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011496 if (IS_SCHEMA(child, "simpleType")) {
11497 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011498 /*
William M. Brack2f2a6632004-08-20 23:09:47 +000011499 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011500 * Either the base [attribute] or the simpleType [child] of the
11501 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +000011502 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011503 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000011504 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011505 NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +000011506 "The attribute 'base' and the <simpleType> child are "
11507 "mutually exclusive", NULL);
11508 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011509 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +000011510 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011511 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011512 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011513 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011514 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011515 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011516 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011517 "Either the attribute 'base' or a <simpleType> child "
11518 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000011519 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011520 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11521 /*
11522 * Corresponds to <complexType><complexContent><restriction>...
11523 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011524 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011525 * Model groups <all>, <choice> and <sequence>.
11526 */
11527 if (IS_SCHEMA(child, "all")) {
11528 type->subtypes = (xmlSchemaTypePtr)
11529 xmlSchemaParseModelGroup(ctxt, schema, child,
11530 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011531 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011532 } else if (IS_SCHEMA(child, "choice")) {
11533 type->subtypes = (xmlSchemaTypePtr)
11534 xmlSchemaParseModelGroup(ctxt,
11535 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11536 child = child->next;
11537 } else if (IS_SCHEMA(child, "sequence")) {
11538 type->subtypes = (xmlSchemaTypePtr)
11539 xmlSchemaParseModelGroup(ctxt, schema, child,
11540 XML_SCHEMA_TYPE_SEQUENCE, 1);
11541 child = child->next;
11542 /*
11543 * Model group reference <group>.
11544 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011545 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011546 type->subtypes = (xmlSchemaTypePtr)
11547 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011548 /*
11549 * Note that the reference will be resolved in
11550 * xmlSchemaResolveTypeReferences();
11551 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011552 child = child->next;
11553 }
11554 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011555 /*
11556 * Corresponds to <complexType><simpleContent><restriction>...
11557 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011558 * "1.1 the simple type definition corresponding to the <simpleType>
11559 * among the [children] of <restriction> if there is one;"
11560 */
11561 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011562 /*
11563 * We will store the to-be-restricted simple type in
11564 * type->contentTypeDef *temporarily*.
11565 */
11566 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011567 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011568 if ( type->contentTypeDef == NULL)
11569 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011570 child = child->next;
11571 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011572 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011573
11574 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011575 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011576 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011577 /*
11578 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011579 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011580 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011581
Daniel Veillard01fa6152004-06-29 17:04:39 +000011582 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011583 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011584 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011585 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011586 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11587 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +000011588 * *Single Facet Value*
11589 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011590 while ((IS_SCHEMA(child, "minInclusive")) ||
11591 (IS_SCHEMA(child, "minExclusive")) ||
11592 (IS_SCHEMA(child, "maxInclusive")) ||
11593 (IS_SCHEMA(child, "maxExclusive")) ||
11594 (IS_SCHEMA(child, "totalDigits")) ||
11595 (IS_SCHEMA(child, "fractionDigits")) ||
11596 (IS_SCHEMA(child, "pattern")) ||
11597 (IS_SCHEMA(child, "enumeration")) ||
11598 (IS_SCHEMA(child, "whiteSpace")) ||
11599 (IS_SCHEMA(child, "length")) ||
11600 (IS_SCHEMA(child, "maxLength")) ||
11601 (IS_SCHEMA(child, "minLength"))) {
11602 facet = xmlSchemaParseFacet(ctxt, schema, child);
11603 if (facet != NULL) {
11604 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011605 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011606 else
11607 lastfacet->next = facet;
11608 lastfacet = facet;
11609 lastfacet->next = NULL;
11610 }
11611 child = child->next;
11612 }
11613 /*
11614 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011615 */
11616 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011617 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11618
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011619 facet = type->facets;
11620 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011621 facetLink = (xmlSchemaFacetLinkPtr)
11622 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +000011623 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011624 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011625 xmlFree(facetLink);
11626 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011627 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011628 facetLink->facet = facet;
11629 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011630 if (lastFacetLink == NULL)
11631 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011632 else
11633 lastFacetLink->next = facetLink;
11634 lastFacetLink = facetLink;
11635 facet = facet->next;
11636 } while (facet != NULL);
11637 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011638 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011639 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11640 /*
11641 * Attribute uses/declarations.
11642 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011643 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11644 (xmlSchemaItemListPtr *) &(type->attrUses),
11645 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11646 return(NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011647 /*
11648 * Attribute wildcard.
11649 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011650 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011651 type->attributeWildcard =
11652 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011653 child = child->next;
11654 }
11655 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011656 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011657 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11658 xmlSchemaPContentErr(ctxt,
11659 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011660 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011661 "annotation?, (group | all | choice | sequence)?, "
11662 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011663 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011664 xmlSchemaPContentErr(ctxt,
11665 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011666 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011667 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11668 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11669 "length | minLength | maxLength | enumeration | whiteSpace | "
11670 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11671 } else {
11672 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011673 xmlSchemaPContentErr(ctxt,
11674 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011675 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011676 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11677 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11678 "length | minLength | maxLength | enumeration | whiteSpace | "
11679 "pattern)*))");
11680 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011681 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011682 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011683}
11684
11685/**
11686 * xmlSchemaParseExtension:
11687 * @ctxt: a schema validation context
11688 * @schema: the schema being built
11689 * @node: a subtree containing XML Schema informations
11690 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011691 * Parses an <extension>, which is found inside a
11692 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011693 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000011694 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011695 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000011696 */
11697static xmlSchemaTypePtr
11698xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011699 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000011700{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011701 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011702 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011703 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011704
11705 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11706 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011707 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011708 type = ctxt->ctxtType;
11709 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000011710
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011711 /*
11712 * Check for illegal attributes.
11713 */
11714 attr = node->properties;
11715 while (attr != NULL) {
11716 if (attr->ns == NULL) {
11717 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11718 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011719 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011720 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011721 }
11722 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011723 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011724 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011725 }
11726 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011727 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011728
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011729 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011730
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011731 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011732 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011733 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011734 if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11735 "base", &(type->baseNs), &(type->base)) == 0) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011736 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011737 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011738 XML_SCHEMAP_S4S_ATTR_MISSING,
11739 NULL, node, "base", NULL);
11740 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011741 /*
11742 * And now for the children...
11743 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011744 child = node->children;
11745 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011746 /*
11747 * Add the annotation to the type ancestor.
11748 */
11749 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011750 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011751 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011752 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011753 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11754 /*
11755 * Corresponds to <complexType><complexContent><extension>... and:
11756 *
11757 * Model groups <all>, <choice>, <sequence> and <group>.
11758 */
11759 if (IS_SCHEMA(child, "all")) {
11760 type->subtypes = (xmlSchemaTypePtr)
11761 xmlSchemaParseModelGroup(ctxt, schema,
11762 child, XML_SCHEMA_TYPE_ALL, 1);
11763 child = child->next;
11764 } else if (IS_SCHEMA(child, "choice")) {
11765 type->subtypes = (xmlSchemaTypePtr)
11766 xmlSchemaParseModelGroup(ctxt, schema,
11767 child, XML_SCHEMA_TYPE_CHOICE, 1);
11768 child = child->next;
11769 } else if (IS_SCHEMA(child, "sequence")) {
11770 type->subtypes = (xmlSchemaTypePtr)
11771 xmlSchemaParseModelGroup(ctxt, schema,
11772 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11773 child = child->next;
11774 } else if (IS_SCHEMA(child, "group")) {
11775 type->subtypes = (xmlSchemaTypePtr)
11776 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011777 /*
11778 * Note that the reference will be resolved in
11779 * xmlSchemaResolveTypeReferences();
11780 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011781 child = child->next;
11782 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011783 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011784 if (child != NULL) {
11785 /*
11786 * Attribute uses/declarations.
11787 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011788 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11789 (xmlSchemaItemListPtr *) &(type->attrUses),
11790 XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11791 return(NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011792 /*
11793 * Attribute wildcard.
11794 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011795 if (IS_SCHEMA(child, "anyAttribute")) {
11796 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011797 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11798 child = child->next;
11799 }
11800 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011801 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011802 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11803 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011804 xmlSchemaPContentErr(ctxt,
11805 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011806 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011807 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011808 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011809 } else {
11810 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011811 xmlSchemaPContentErr(ctxt,
11812 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011813 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011814 "(annotation?, ((attribute | attributeGroup)*, "
11815 "anyAttribute?))");
11816 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011817 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011818 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011819}
11820
11821/**
11822 * xmlSchemaParseSimpleContent:
11823 * @ctxt: a schema validation context
11824 * @schema: the schema being built
11825 * @node: a subtree containing XML Schema informations
11826 *
11827 * parse a XML schema SimpleContent definition
11828 * *WARNING* this interface is highly subject to change
11829 *
11830 * Returns the type definition or NULL in case of error
11831 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011832static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011833xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011834 xmlSchemaPtr schema, xmlNodePtr node,
11835 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000011836{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011837 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011838 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011839 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011840
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011841 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11842 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011843 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011844 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011845 /* Not a component, don't create it. */
11846 type = ctxt->ctxtType;
11847 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11848 /*
11849 * Check for illegal attributes.
11850 */
11851 attr = node->properties;
11852 while (attr != NULL) {
11853 if (attr->ns == NULL) {
11854 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011855 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011856 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011857 }
11858 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011859 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011860 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011861 }
11862 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011863 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011864
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011865 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000011866
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011867 /*
11868 * And now for the children...
11869 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011870 child = node->children;
11871 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011872 /*
11873 * Add the annotation to the complex type ancestor.
11874 */
11875 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011876 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011877 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011878 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011879 if (child == NULL) {
11880 xmlSchemaPContentErr(ctxt,
11881 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011882 NULL, node, NULL, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011883 "(annotation?, (restriction | extension))");
11884 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011885 if (child == NULL) {
11886 xmlSchemaPContentErr(ctxt,
11887 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011888 NULL, node, NULL, NULL,
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011889 "(annotation?, (restriction | extension))");
11890 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011891 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011892 xmlSchemaParseRestriction(ctxt, schema, child,
11893 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011894 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011895 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011896 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011897 xmlSchemaParseExtension(ctxt, schema, child,
11898 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011899 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011900 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011901 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011902 if (child != NULL) {
11903 xmlSchemaPContentErr(ctxt,
11904 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011905 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011906 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000011907 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011908 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000011909}
11910
11911/**
11912 * xmlSchemaParseComplexContent:
11913 * @ctxt: a schema validation context
11914 * @schema: the schema being built
11915 * @node: a subtree containing XML Schema informations
11916 *
11917 * parse a XML schema ComplexContent definition
11918 * *WARNING* this interface is highly subject to change
11919 *
11920 * Returns the type definition or NULL in case of error
11921 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011922static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011923xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011924 xmlSchemaPtr schema, xmlNodePtr node,
11925 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000011926{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011927 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011928 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011929 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011930
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011931 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11932 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011933 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011934 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011935 /* Not a component, don't create it. */
11936 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011937 /*
11938 * Check for illegal attributes.
11939 */
11940 attr = node->properties;
11941 while (attr != NULL) {
11942 if (attr->ns == NULL) {
11943 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011944 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011945 {
11946 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011947 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011948 }
11949 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11950 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011951 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011952 }
11953 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011954 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011955
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011956 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011957
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011958 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011959 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011960 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011961 if (xmlGetBooleanProp(ctxt, node, "mixed", 0)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011962 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
11963 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011964 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011965 child = node->children;
11966 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011967 /*
11968 * Add the annotation to the complex type ancestor.
11969 */
11970 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011971 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011972 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011973 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011974 if (child == NULL) {
11975 xmlSchemaPContentErr(ctxt,
11976 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011977 NULL, node, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011978 NULL, "(annotation?, (restriction | extension))");
11979 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011980 if (child == NULL) {
11981 xmlSchemaPContentErr(ctxt,
11982 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011983 NULL, node, NULL,
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011984 NULL, "(annotation?, (restriction | extension))");
11985 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011986 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011987 xmlSchemaParseRestriction(ctxt, schema, child,
11988 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011989 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011990 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011991 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011992 xmlSchemaParseExtension(ctxt, schema, child,
11993 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011994 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011995 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011996 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011997 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011998 xmlSchemaPContentErr(ctxt,
11999 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012000 NULL, node, child,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012001 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000012002 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012003 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000012004}
12005
12006/**
12007 * xmlSchemaParseComplexType:
12008 * @ctxt: a schema validation context
12009 * @schema: the schema being built
12010 * @node: a subtree containing XML Schema informations
12011 *
12012 * parse a XML schema Complex Type definition
12013 * *WARNING* this interface is highly subject to change
12014 *
12015 * Returns the type definition or NULL in case of error
12016 */
12017static xmlSchemaTypePtr
12018xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000012019 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000012020{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012021 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000012022 xmlNodePtr child = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012023 const xmlChar *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012024 xmlAttrPtr attr;
12025 const xmlChar *attrValue;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012026#ifdef ENABLE_NAMED_LOCALS
Daniel Veillard1a380b82004-10-21 16:00:06 +000012027 char buf[40];
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012028#endif
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012029 int final = 0, block = 0, hasRestrictionOrExtension = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000012030
Daniel Veillard4255d502002-04-16 15:50:10 +000012031
12032 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12033 return (NULL);
12034
Daniel Veillard01fa6152004-06-29 17:04:39 +000012035 ctxtType = ctxt->ctxtType;
12036
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012037 if (topLevel) {
12038 attr = xmlSchemaGetPropNode(node, "name");
12039 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012040 xmlSchemaPMissingAttrErr(ctxt,
12041 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012042 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012043 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012044 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12045 return (NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012046 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012047 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012048
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012049 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012050 /*
12051 * Parse as local complex type definition.
12052 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012053#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000012054 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012055 type = xmlSchemaAddType(ctxt, schema,
12056 XML_SCHEMA_TYPE_COMPLEX,
12057 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012058 ctxt->targetNamespace, node, 0);
12059#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012060 type = xmlSchemaAddType(ctxt, schema,
12061 XML_SCHEMA_TYPE_COMPLEX,
12062 NULL, ctxt->targetNamespace, node, 0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012063#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012064 if (type == NULL)
12065 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012066 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012067 type->node = node;
12068 type->type = XML_SCHEMA_TYPE_COMPLEX;
12069 /*
12070 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012071 */
12072 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012073 /*
12074 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012075 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012076 type = xmlSchemaAddType(ctxt, schema,
12077 XML_SCHEMA_TYPE_COMPLEX,
12078 name, ctxt->targetNamespace, node, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012079 if (type == NULL)
12080 return (NULL);
12081 type->node = node;
12082 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012083 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000012084 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012085 type->targetNamespace = ctxt->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012086 /*
12087 * Handle attributes.
12088 */
12089 attr = node->properties;
12090 while (attr != NULL) {
12091 if (attr->ns == NULL) {
12092 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12093 /*
12094 * Attribute "id".
12095 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012096 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012097 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12098 /*
12099 * Attribute "mixed".
12100 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012101 if (xmlSchemaPGetBoolNodeValue(ctxt,
12102 NULL, (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012103 type->flags |= XML_SCHEMAS_TYPE_MIXED;
12104 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012105 /*
12106 * Attributes of global complex type definitions.
12107 */
12108 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12109 /* Pass. */
12110 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12111 /*
12112 * Attribute "abstract".
12113 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012114 if (xmlSchemaPGetBoolNodeValue(ctxt,
12115 NULL, (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012116 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12117 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12118 /*
12119 * Attribute "final".
12120 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012121 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012122 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012123 if (xmlSchemaPValAttrBlockFinal(attrValue,
12124 &(type->flags),
12125 -1,
12126 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12127 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12128 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012129 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012130 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012131 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012132 NULL, (xmlNodePtr) attr, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012133 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012134 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012135 } else
12136 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012137 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12138 /*
12139 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012140 */
12141 attrValue = xmlSchemaGetNodeContent(ctxt,
12142 (xmlNodePtr) attr);
12143 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012144 -1,
12145 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012146 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012147 -1, -1, -1) != 0) {
12148 xmlSchemaPSimpleTypeErr(ctxt,
12149 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012150 NULL, (xmlNodePtr) attr, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012151 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012152 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012153 } else
12154 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012155 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012156 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012157 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012158 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012159 } else {
12160 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012161 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012162 }
12163 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012164 xmlSchemaPIllegalAttrErr(ctxt,
12165 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012166 }
12167 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012168 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012169 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000012170 /*
12171 * Apply default "block" values.
12172 */
12173 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12174 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12175 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12176 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12177 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012178 if (! final) {
12179 /*
12180 * Apply default "block" values.
12181 */
12182 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12183 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12184 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12185 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12186 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012187 /*
12188 * And now for the children...
12189 */
Daniel Veillard4255d502002-04-16 15:50:10 +000012190 child = node->children;
12191 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012192 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012193 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012194 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012195 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000012196 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012197 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012198 * <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012199 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012200 * Specifying mixed='true' when the <simpleContent>
12201 * alternative is chosen has no effect
12202 */
William M. Bracke7091952004-05-11 15:09:58 +000012203 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12204 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012205 xmlSchemaParseSimpleContent(ctxt, schema, child,
12206 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012207 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012208 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012209 /*
12210 * <complexType><complexContent>...
12211 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012212 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012213 xmlSchemaParseComplexContent(ctxt, schema, child,
12214 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012215 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012216 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012217 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012218 * E.g <complexType><sequence>... or <complexType><attribute>... etc.
12219 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012220 * SPEC
12221 * "...the third alternative (neither <simpleContent> nor
12222 * <complexContent>) is chosen. This case is understood as shorthand
12223 * for complex content restricting the ·ur-type definition·, and the
12224 * details of the mappings should be modified as necessary.
12225 */
12226 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12227 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012228 /*
12229 * Parse model groups.
12230 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012231 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012232 type->subtypes = (xmlSchemaTypePtr)
12233 xmlSchemaParseModelGroup(ctxt, schema, child,
12234 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012235 child = child->next;
12236 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012237 type->subtypes = (xmlSchemaTypePtr)
12238 xmlSchemaParseModelGroup(ctxt, schema, child,
12239 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012240 child = child->next;
12241 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012242 type->subtypes = (xmlSchemaTypePtr)
12243 xmlSchemaParseModelGroup(ctxt, schema, child,
12244 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012245 child = child->next;
12246 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012247 type->subtypes = (xmlSchemaTypePtr)
12248 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012249 /*
12250 * Note that the reference will be resolved in
12251 * xmlSchemaResolveTypeReferences();
12252 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012253 child = child->next;
12254 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012255 /*
12256 * Parse attribute decls/refs.
12257 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012258 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12259 (xmlSchemaItemListPtr *) &(type->attrUses),
12260 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12261 return(NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012262 /*
12263 * Parse attribute wildcard.
12264 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012265 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012266 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12267 child = child->next;
12268 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012269 }
12270 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012271 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012272 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012273 NULL, node, child,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012274 NULL, "(annotation?, (simpleContent | complexContent | "
12275 "((group | all | choice | sequence)?, ((attribute | "
12276 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000012277 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012278 /*
12279 * REDEFINE: SPEC src-redefine (5)
12280 */
12281 if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12282 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012283 NULL, node, "This is a redefinition, thus the "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012284 "<complexType> must have a <restriction> or <extension> "
12285 "grand-child", NULL);
12286 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012287 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000012288 return (type);
12289}
12290
Daniel Veillard4255d502002-04-16 15:50:10 +000012291/************************************************************************
12292 * *
12293 * Validating using Schemas *
12294 * *
12295 ************************************************************************/
12296
12297/************************************************************************
12298 * *
12299 * Reading/Writing Schemas *
12300 * *
12301 ************************************************************************/
12302
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012303#if 0 /* Will be enabled if it is clear what options are needed. */
12304/**
12305 * xmlSchemaParserCtxtSetOptions:
12306 * @ctxt: a schema parser context
12307 * @options: a combination of xmlSchemaParserOption
12308 *
12309 * Sets the options to be used during the parse.
12310 *
12311 * Returns 0 in case of success, -1 in case of an
12312 * API error.
12313 */
12314static int
12315xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12316 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012317
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012318{
12319 int i;
12320
12321 if (ctxt == NULL)
12322 return (-1);
12323 /*
12324 * WARNING: Change the start value if adding to the
12325 * xmlSchemaParseOption.
12326 */
12327 for (i = 1; i < (int) sizeof(int) * 8; i++) {
12328 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012329 return (-1);
12330 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012331 }
12332 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012333 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012334}
12335
12336/**
12337 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012338 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012339 *
12340 * Returns the option combination of the parser context.
12341 */
12342static int
12343xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012344
12345{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012346 if (ctxt == NULL)
12347 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012348 else
12349 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012350}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012351#endif
12352
Daniel Veillard4255d502002-04-16 15:50:10 +000012353/**
12354 * xmlSchemaNewParserCtxt:
12355 * @URL: the location of the schema
12356 *
12357 * Create an XML Schemas parse context for that file/resource expected
12358 * to contain an XML Schemas file.
12359 *
12360 * Returns the parser context or NULL in case of error
12361 */
12362xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012363xmlSchemaNewParserCtxt(const char *URL)
12364{
Daniel Veillard4255d502002-04-16 15:50:10 +000012365 xmlSchemaParserCtxtPtr ret;
12366
12367 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012368 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000012369
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012370 ret = xmlSchemaParserCtxtCreate();
12371 if (ret == NULL)
12372 return(NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012373 ret->dict = xmlDictCreate();
12374 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012375 return (ret);
12376}
12377
12378/**
Daniel Veillard6045c902002-10-09 21:13:59 +000012379 * xmlSchemaNewMemParserCtxt:
12380 * @buffer: a pointer to a char array containing the schemas
12381 * @size: the size of the array
12382 *
12383 * Create an XML Schemas parse context for that memory buffer expected
12384 * to contain an XML Schemas file.
12385 *
12386 * Returns the parser context or NULL in case of error
12387 */
12388xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012389xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12390{
Daniel Veillard6045c902002-10-09 21:13:59 +000012391 xmlSchemaParserCtxtPtr ret;
12392
12393 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012394 return (NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012395 ret = xmlSchemaParserCtxtCreate();
12396 if (ret == NULL)
12397 return(NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000012398 ret->buffer = buffer;
12399 ret->size = size;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012400 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000012401 return (ret);
12402}
12403
12404/**
Daniel Veillard9d751502003-10-29 13:21:47 +000012405 * xmlSchemaNewDocParserCtxt:
12406 * @doc: a preparsed document tree
12407 *
12408 * Create an XML Schemas parse context for that document.
12409 * NB. The document may be modified during the parsing process.
12410 *
12411 * Returns the parser context or NULL in case of error
12412 */
12413xmlSchemaParserCtxtPtr
12414xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12415{
12416 xmlSchemaParserCtxtPtr ret;
12417
12418 if (doc == NULL)
12419 return (NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012420 ret = xmlSchemaParserCtxtCreate();
12421 if (ret == NULL)
12422 return(NULL);
Daniel Veillard9d751502003-10-29 13:21:47 +000012423 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000012424 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000012425 /* The application has responsibility for the document */
12426 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000012427
12428 return (ret);
12429}
12430
12431/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012432 * xmlSchemaFreeParserCtxt:
12433 * @ctxt: the schema parser context
12434 *
12435 * Free the resources associated to the schema parser context
12436 */
12437void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012438xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12439{
Daniel Veillard4255d502002-04-16 15:50:10 +000012440 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012441 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000012442 if (ctxt->doc != NULL && !ctxt->preserve)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012443 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012444 if (ctxt->vctxt != NULL) {
12445 xmlSchemaFreeValidCtxt(ctxt->vctxt);
12446 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012447 if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12448 xmlSchemaConstructionCtxtFree(ctxt->constructor);
12449 ctxt->constructor = NULL;
12450 ctxt->ownsConstructor = 0;
12451 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012452 if (ctxt->attrProhibs != NULL)
12453 xmlSchemaItemListFree(ctxt->attrProhibs);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012454 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000012455 xmlFree(ctxt);
12456}
12457
12458/************************************************************************
12459 * *
12460 * Building the content models *
12461 * *
12462 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012463
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012464static void
12465xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012466 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012467{
Daniel Veillarda980bef2005-07-18 21:34:03 +000012468 xmlAutomataStatePtr start, tmp;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012469 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012470 xmlSchemaSubstGroupPtr substGroup;
12471 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012472
12473 elemDecl = (xmlSchemaElementPtr) particle->children;
12474 /*
12475 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012476 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012477 start = pctxt->state;
Daniel Veillarda980bef2005-07-18 21:34:03 +000012478 if (end == NULL)
12479 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012480 substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012481 if (substGroup == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012482 xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012483 XML_SCHEMAP_INTERNAL,
12484 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12485 "declaration is marked having a subst. group but none "
12486 "available.\n", elemDecl->name, NULL);
12487 return;
12488 }
Daniel Veillarda980bef2005-07-18 21:34:03 +000012489 if (counter >= 0) {
12490 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012491 * NOTE that we put the declaration in, even if it's abstract.
12492 * However, an error will be raised during *validation* if an element
12493 * information item shall be validated against an abstract element
12494 * declaration.
Daniel Veillarda980bef2005-07-18 21:34:03 +000012495 */
12496 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12497 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12498 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12499 /*
12500 * Add subst. group members.
12501 */
12502 for (i = 0; i < substGroup->members->nbItems; i++) {
12503 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12504 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12505 member->name, member->targetNamespace, member);
12506 }
12507 } else if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012508 /*
12509 * NOTE that we put the declaration in, even if it's abstract,
12510 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012511 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012512 xmlAutomataNewTransition2(pctxt->am,
12513 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012514 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12515 /*
12516 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012517 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012518 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012519 member = (xmlSchemaElementPtr) substGroup->members->items[i];
Daniel Veillarda980bef2005-07-18 21:34:03 +000012520 tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12521 member->name, member->targetNamespace,
12522 1, 1, member);
12523 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012524 }
12525 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012526 xmlAutomataStatePtr hop;
12527 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12528 UNBOUNDED : particle->maxOccurs - 1;
12529 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12530
12531 counter =
12532 xmlAutomataNewCounter(pctxt->am, minOccurs,
12533 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012534 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012535
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012536 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012537 xmlAutomataNewTransition2(pctxt->am,
12538 start, NULL,
12539 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012540 hop);
12541 /*
Daniel Veillarda980bef2005-07-18 21:34:03 +000012542 * Add subst. group members.
12543 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012544 for (i = 0; i < substGroup->members->nbItems; i++) {
12545 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12546 xmlAutomataNewEpsilon(pctxt->am,
12547 xmlAutomataNewTransition2(pctxt->am,
12548 start, NULL,
12549 member->name, member->targetNamespace, member),
12550 hop);
12551 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012552 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12553 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12554 }
12555 if (particle->minOccurs == 0)
12556 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012557 pctxt->state = end;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012558}
12559
12560static void
12561xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12562 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012563{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012564 if (((xmlSchemaElementPtr) particle->children)->flags &
12565 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012566 /*
12567 * Substitution groups.
12568 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000012569 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012570 } else {
12571 xmlSchemaElementPtr elemDecl;
12572 xmlAutomataStatePtr start;
12573
12574 elemDecl = (xmlSchemaElementPtr) particle->children;
12575
12576 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012577 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012578 if (particle->maxOccurs == 1) {
12579 start = ctxt->state;
12580 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012581 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12582 } else if ((particle->maxOccurs >= UNBOUNDED) &&
12583 (particle->minOccurs < 2)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012584 /* Special case. */
12585 start = ctxt->state;
12586 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12587 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012588 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, start);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012589 } else {
12590 int counter;
12591 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12592 UNBOUNDED : particle->maxOccurs - 1;
12593 int minOccurs = particle->minOccurs < 1 ?
12594 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012595
12596 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012597 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12598 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12599 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12600 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12601 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12602 NULL, counter);
12603 }
12604 if (particle->minOccurs == 0)
12605 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12606 }
12607}
12608
Daniel Veillard4255d502002-04-16 15:50:10 +000012609/**
12610 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000012611 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012612 * @particle: the particle component
12613 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000012614 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012615 * Create the automaton for the {content type} of a complex type.
12616 *
Daniel Veillard4255d502002-04-16 15:50:10 +000012617 */
12618static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012619xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012620 xmlSchemaParticlePtr particle)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012621{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012622 if (particle == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012623 PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012624 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000012625 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012626 if (particle->children == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012627 /*
12628 * Just return in this case. A missing "term" of the particle
12629 * might arise due to an invalid "term" component.
12630 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012631 return;
12632 }
12633
12634 switch (particle->children->type) {
12635 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012636 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012637 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012638 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000012639
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012640 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012641
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012642 start = pctxt->state;
12643 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012644
12645 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012646 if (wild->any == 1) {
12647 /*
12648 * We need to add both transitions:
12649 *
12650 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012651 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012652 pctxt->state =
12653 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012654 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012655 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012656 /*
12657 * 2. the {"*"} for elements in no namespace.
12658 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012659 pctxt->state =
12660 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012661 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012662 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012663
12664 } else if (wild->nsSet != NULL) {
12665 ns = wild->nsSet;
12666 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012667 pctxt->state = start;
12668 pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12669 pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12670 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012671 ns = ns->next;
12672 } while (ns != NULL);
12673
12674 } else if (wild->negNsSet != NULL) {
Daniel Veillard6e65e152005-08-09 11:09:52 +000012675 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12676 start, end, BAD_CAST "*", wild->negNsSet->value,
12677 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012678 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012679 } else {
12680 int counter;
12681 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012682 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012683 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012684 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012685 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012686
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012687 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12688 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012689 if (wild->any == 1) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012690 pctxt->state =
12691 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012692 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012693 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12694 pctxt->state =
12695 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012696 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012697 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012698 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012699 ns = wild->nsSet;
12700 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012701 pctxt->state =
12702 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012703 start, NULL, BAD_CAST "*", ns->value, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012704 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012705 ns = ns->next;
12706 } while (ns != NULL);
12707
12708 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012709 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
Daniel Veillard9efc4762005-07-19 14:33:55 +000012710 start, hop, BAD_CAST "*", wild->negNsSet->value,
12711 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012712 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012713 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12714 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012715 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012716 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012717 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012718 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012719 pctxt->state = end;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012720 break;
12721 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012722 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012723 xmlSchemaBuildContentModelForElement(pctxt, particle);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012724 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012725 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012726 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012727
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012728 /*
12729 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012730 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012731 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012732 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12733 sub = particle->children->children;
12734 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012735 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012736 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012737 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012738 }
12739 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012740 xmlAutomataStatePtr oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012741
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012742 if (particle->maxOccurs >= UNBOUNDED) {
12743 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012744 xmlAutomataStatePtr tmp;
12745 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012746
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012747 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012748 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012749 oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012750
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012751 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012752 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000012753
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012754 sub = particle->children->children;
12755 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012756 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012757 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012758 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012759 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012760 tmp = pctxt->state;
12761 xmlAutomataNewCountedTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012762 oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012763 pctxt->state =
12764 xmlAutomataNewCounterTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012765 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000012766
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012767 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012768 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Daniel Veillardafc05b62005-07-17 06:11:19 +000012769 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012770 oldstate = pctxt->state;
Daniel Veillardafc05b62005-07-17 06:11:19 +000012771
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012772 sub = particle->children->children;
12773 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012774 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012775 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012776 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012777 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012778 xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012779 oldstate);
Daniel Veillardafc05b62005-07-17 06:11:19 +000012780 /*
12781 * epsilon needed to block previous trans from
12782 * being allowed to enter back from another
12783 * construct
12784 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012785 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12786 pctxt->state, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012787 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012788 xmlAutomataNewEpsilon(pctxt->am,
12789 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012790 }
12791 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012792 } else if ((particle->maxOccurs > 1)
12793 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012794 xmlAutomataStatePtr tmp;
12795 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012796
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012797 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012798 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012799 oldstate = pctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000012800
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012801 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012802 particle->minOccurs - 1,
12803 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012804
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012805 sub = particle->children->children;
12806 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012807 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012808 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012809 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012810 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012811 tmp = pctxt->state;
12812 xmlAutomataNewCountedTrans(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012813 tmp, oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012814 pctxt->state =
12815 xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012816 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012817 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012818 xmlAutomataNewEpsilon(pctxt->am,
12819 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012820 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012821 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012822 sub = particle->children->children;
12823 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012824 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012825 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012826 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012827 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012828 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012829 xmlAutomataNewEpsilon(pctxt->am, oldstate,
12830 pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012831 }
12832 }
12833 }
12834 break;
12835 }
12836 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012837 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012838 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000012839
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012840 start = pctxt->state;
12841 end = xmlAutomataNewState(pctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000012842
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012843 /*
12844 * iterate over the subtypes and remerge the end with an
12845 * epsilon transition
12846 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012847 if (particle->maxOccurs == 1) {
12848 sub = particle->children->children;
12849 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012850 pctxt->state = start;
12851 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012852 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012853 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012854 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012855 }
12856 } else {
12857 int counter;
Daniel Veillardafc05b62005-07-17 06:11:19 +000012858 xmlAutomataStatePtr hop, base;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012859 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12860 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012861 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012862 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000012863
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012864 /*
12865 * use a counter to keep track of the number of transtions
12866 * which went through the choice.
12867 */
12868 counter =
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012869 xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12870 hop = xmlAutomataNewState(pctxt->am);
12871 base = xmlAutomataNewState(pctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000012872
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012873 sub = particle->children->children;
12874 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012875 pctxt->state = base;
12876 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012877 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012878 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012879 sub = sub->next;
Daniel Veillarda980bef2005-07-18 21:34:03 +000012880 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012881 xmlAutomataNewEpsilon(pctxt->am, start, base);
12882 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
12883 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012884 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012885 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012886 xmlAutomataNewEpsilon(pctxt->am, start, end);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012887 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012888 pctxt->state = end;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012889 break;
12890 }
12891 case XML_SCHEMA_TYPE_ALL:{
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +000012892 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012893 xmlSchemaParticlePtr sub;
12894 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012895 int lax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012896
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012897 sub = (xmlSchemaParticlePtr) particle->children->children;
12898 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012899 break;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012900 start = pctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012901 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012902 pctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012903
12904 elemDecl = (xmlSchemaElementPtr) sub->children;
12905 if (elemDecl == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012906 PERROR_INT("xmlSchemaBuildAContentModel",
12907 "<element> particle has no term");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012908 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012909 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012910 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012911 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000012912 * {particles} of the group must be 0 or 1; this is
12913 * already ensured during the parse of the content of
12914 * <all>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012915 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000012916 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12917 int counter;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012918
Daniel Veillarda980bef2005-07-18 21:34:03 +000012919 /*
12920 * This is an abstract group, we need to share
12921 * the same counter for all the element transitions
12922 * derived from the group
12923 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012924 counter = xmlAutomataNewCounter(pctxt->am,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012925 sub->minOccurs, sub->maxOccurs);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012926 xmlSchemaBuildContentModelForSubstGroup(pctxt,
12927 sub, counter, pctxt->state);
Daniel Veillarda980bef2005-07-18 21:34:03 +000012928 } else {
12929 if ((sub->minOccurs == 1) &&
12930 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012931 xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
12932 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012933 elemDecl->name,
12934 elemDecl->targetNamespace,
12935 1, 1, elemDecl);
12936 } else if ((sub->minOccurs == 0) &&
12937 (sub->maxOccurs == 1)) {
12938
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012939 xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
12940 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012941 elemDecl->name,
12942 elemDecl->targetNamespace,
12943 0,
12944 1,
12945 elemDecl);
12946 }
12947 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012948 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012949 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012950 lax = particle->minOccurs == 0;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012951 pctxt->state =
12952 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012953 break;
12954 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012955 case XML_SCHEMA_TYPE_GROUP:
12956 /*
12957 * If we hit a model group definition, then this means that
12958 * it was empty, thus was not substituted for the containing
12959 * model group. Just do nothing in this case.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012960 * TODO: But the group should be substituted and not occur at
12961 * all in the content model at this point. Fix this.
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012962 */
12963 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012964 default:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012965 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
12966 "xmlSchemaBuildAContentModel",
12967 "found unexpected term of type '%s' in content model",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012968 WXS_ITEM_TYPE_NAME(particle->children), NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012969 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000012970 }
12971}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012972
Daniel Veillard4255d502002-04-16 15:50:10 +000012973/**
12974 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000012975 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012976 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000012977 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000012978 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012979 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000012980 */
12981static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012982xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012983 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012984{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012985 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
12986 (type->contModel != NULL) ||
12987 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
12988 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012989 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000012990
12991#ifdef DEBUG_CONTENT
12992 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012993 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000012994#endif
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012995 ctxt->am = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000012996 ctxt->am = xmlNewAutomata();
12997 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012998 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012999 "Cannot create automata for complex type %s\n", type->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013000 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000013001 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000013002 ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013003 /*
13004 * Build the automaton.
13005 */
13006 xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
Daniel Veillard4255d502002-04-16 15:50:10 +000013007 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013008 type->contModel = xmlAutomataCompile(ctxt->am);
13009 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013010 xmlSchemaPCustomErr(ctxt,
13011 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013012 WXS_BASIC_CAST type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013013 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013014 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013015 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013016 XML_SCHEMAP_NOT_DETERMINISTIC,
13017 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013018 WXS_BASIC_CAST type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013019 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000013020 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000013021#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013022 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013023 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013024 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000013025#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000013026 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000013027 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013028 xmlFreeAutomata(ctxt->am);
13029 ctxt->am = NULL;
13030}
13031
13032/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013033 * xmlSchemaResolveElementReferences:
Daniel Veillard4255d502002-04-16 15:50:10 +000013034 * @elem: the schema element context
13035 * @ctxt: the schema parser context
13036 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000013037 * Resolves the references of an element declaration
13038 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013039 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000013040 */
13041static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013042xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13043 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000013044{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013045 if ((ctxt == NULL) || (elemDecl == NULL) ||
13046 ((elemDecl != NULL) &&
13047 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013048 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013049 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013050
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013051 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013052 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013053
13054 /* (type definition) ... otherwise the type definition ·resolved·
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013055 * to by the ·actual value· of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013056 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013057 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013058 elemDecl->namedTypeNs);
13059 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013060 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013061 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013062 WXS_BASIC_CAST elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013063 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013064 XML_SCHEMA_TYPE_BASIC, "type definition");
13065 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013066 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013067 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013068 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013069 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013070
Daniel Veillardc0826a72004-08-10 14:17:33 +000013071 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013072 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013073 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000013074 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013075 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13076 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013077 if (substHead == NULL) {
13078 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013079 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013080 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013081 "substitutionGroup", elemDecl->substGroup,
13082 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013083 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013084 xmlSchemaResolveElementReferences(substHead, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013085 /*
13086 * Set the "substitution group affiliation".
13087 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013088 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013089 WXS_SUBST_HEAD(elemDecl) = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013090 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013091 * The type definitions is set to:
13092 * SPEC "...the {type definition} of the element
13093 * declaration ·resolved· to by the ·actual value·
13094 * of the substitutionGroup [attribute], if present"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013095 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013096 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013097 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013098 }
13099 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013100 /*
13101 * SPEC "The definition of anyType serves as the default type definition
13102 * for element declarations whose XML representation does not specify one."
13103 */
13104 if ((elemDecl->subtypes == NULL) &&
13105 (elemDecl->namedType == NULL) &&
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013106 (elemDecl->substGroup == NULL))
13107 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000013108}
13109
13110/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013111 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000013112 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013113 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000013114 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013115 * Checks and builds the "member type definitions" property of the union
13116 * simple type. This handles part (1), part (2) is done in
13117 * xmlSchemaFinishMemberTypeDefinitionsProperty()
13118 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000013119 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000013120 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013121static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013122xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13123 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000013124{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013125
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013126 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013127 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000013128
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013129 /*
13130 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13131 * define the explicit members as the type definitions ·resolved·
13132 * to by the items in the ·actual value· of the memberTypes [attribute],
13133 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013134 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000013135 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013136 /*
13137 * Resolve references.
13138 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013139 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013140 lastLink = NULL;
13141 while (link != NULL) {
13142 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013143
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013144 name = ((xmlSchemaQNameRefPtr) link->type)->name;
13145 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13146
13147 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013148 if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013149 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013150 WXS_BASIC_CAST type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013151 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13152 /*
13153 * Remove the member type link.
13154 */
13155 if (lastLink == NULL)
13156 type->memberTypes = link->next;
13157 else
13158 lastLink->next = link->next;
13159 newLink = link;
13160 link = link->next;
13161 xmlFree(newLink);
13162 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013163 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013164 lastLink = link;
13165 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013166 }
13167 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013168 /*
13169 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013170 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013171 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013172 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013173 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13174 if (link == NULL) {
13175 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13176 return (-1);
13177 }
13178 link->type = memberType;
13179 link->next = NULL;
13180 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013181 type->memberTypes = link;
13182 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000013183 lastLink->next = link;
13184 lastLink = link;
13185 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013186 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013187 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000013188}
13189
Daniel Veillard4255d502002-04-16 15:50:10 +000013190/**
Daniel Veillard3646d642004-06-02 19:19:14 +000013191 * xmlSchemaIsDerivedFromBuiltInType:
13192 * @ctxt: the schema parser context
13193 * @type: the type definition
13194 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013195 *
Daniel Veillard3646d642004-06-02 19:19:14 +000013196 *
13197 * Returns 1 if the type has the given value type, or
13198 * is derived from such a type.
13199 */
William M. Brack803812b2004-06-03 02:11:24 +000013200static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013201xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000013202{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013203 if (type == NULL)
13204 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013205 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013206 return (0);
13207 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13208 if (type->builtInType == valType)
13209 return(1);
13210 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13211 (type->builtInType == XML_SCHEMAS_ANYTYPE))
13212 return (0);
13213 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13214 } else
13215 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000013216
13217 return (0);
13218}
13219
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013220#if 0
13221/**
13222 * xmlSchemaIsDerivedFromBuiltInType:
13223 * @ctxt: the schema parser context
13224 * @type: the type definition
13225 * @valType: the value type
13226 *
13227 *
13228 * Returns 1 if the type has the given value type, or
13229 * is derived from such a type.
13230 */
13231static int
13232xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13233{
13234 if (type == NULL)
13235 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013236 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013237 return (0);
13238 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13239 if (type->builtInType == valType)
13240 return(1);
13241 return (0);
13242 } else
13243 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13244
13245 return (0);
13246}
13247#endif
13248
13249static xmlSchemaTypePtr
13250xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13251{
13252 if (type == NULL)
13253 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013254 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013255 return (NULL);
13256 if (type->type == XML_SCHEMA_TYPE_BASIC)
13257 return(type);
13258 else
13259 return(xmlSchemaQueryBuiltInType(type->subtypes));
13260
13261 return (NULL);
13262}
13263
Daniel Veillard3646d642004-06-02 19:19:14 +000013264/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013265 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013266 * @type: the simpleType definition
13267 *
13268 * Returns the primitive type of the given type or
13269 * NULL in case of error.
13270 */
13271static xmlSchemaTypePtr
13272xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13273{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013274
Daniel Veillard01fa6152004-06-29 17:04:39 +000013275 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013276 /*
13277 * Note that anySimpleType is actually not a primitive type
13278 * but we need that here.
13279 */
13280 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13281 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013282 return (type);
13283 type = type->baseType;
13284 }
13285
13286 return (NULL);
13287}
13288
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013289#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013290/**
13291 * xmlSchemaGetBuiltInTypeAncestor:
13292 * @type: the simpleType definition
13293 *
13294 * Returns the primitive type of the given type or
13295 * NULL in case of error.
13296 */
13297static xmlSchemaTypePtr
13298xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13299{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013300 if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013301 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013302 while (type != NULL) {
13303 if (type->type == XML_SCHEMA_TYPE_BASIC)
13304 return (type);
13305 type = type->baseType;
13306 }
13307
13308 return (NULL);
13309}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013310#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013311
Daniel Veillard01fa6152004-06-29 17:04:39 +000013312/**
Daniel Veillard50355f02004-06-08 17:52:16 +000013313 * xmlSchemaCloneWildcardNsConstraints:
13314 * @ctxt: the schema parser context
13315 * @dest: the destination wildcard
13316 * @source: the source wildcard
13317 *
13318 * Clones the namespace constraints of source
13319 * and assignes them to dest.
13320 * Returns -1 on internal error, 0 otherwise.
13321 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013322static int
13323xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013324 xmlSchemaWildcardPtr dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013325 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000013326{
13327 xmlSchemaWildcardNsPtr cur, tmp, last;
13328
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013329 if ((source == NULL) || (dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013330 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013331 dest->any = source->any;
Daniel Veillard3646d642004-06-02 19:19:14 +000013332 cur = source->nsSet;
13333 last = NULL;
13334 while (cur != NULL) {
13335 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13336 if (tmp == NULL)
13337 return(-1);
13338 tmp->value = cur->value;
13339 if (last == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013340 dest->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013341 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013342 last->next = tmp;
13343 last = tmp;
13344 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013345 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013346 if (dest->negNsSet != NULL)
13347 xmlSchemaFreeWildcardNsSet(dest->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000013348 if (source->negNsSet != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013349 dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13350 if (dest->negNsSet == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013351 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013352 dest->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000013353 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013354 dest->negNsSet = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000013355 return(0);
13356}
13357
Daniel Veillard50355f02004-06-08 17:52:16 +000013358/**
13359 * xmlSchemaUnionWildcards:
13360 * @ctxt: the schema parser context
13361 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013362 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013363 *
13364 * Unions the namespace constraints of the given wildcards.
13365 * @completeWild will hold the resulting union.
13366 * Returns a positive error code on failure, -1 in case of an
13367 * internal error, 0 otherwise.
13368 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013369static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013370xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000013371 xmlSchemaWildcardPtr completeWild,
13372 xmlSchemaWildcardPtr curWild)
13373{
13374 xmlSchemaWildcardNsPtr cur, curB, tmp;
13375
13376 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013377 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013378 * value.
13379 */
13380 if ((completeWild->any == curWild->any) &&
13381 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13382 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013383
Daniel Veillard3646d642004-06-02 19:19:14 +000013384 if ((completeWild->negNsSet == NULL) ||
13385 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013386
Daniel Veillard3646d642004-06-02 19:19:14 +000013387 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000013388 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013389
13390 /*
13391 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000013392 */
13393 cur = completeWild->nsSet;
13394 while (cur != NULL) {
13395 found = 0;
13396 curB = curWild->nsSet;
13397 while (curB != NULL) {
13398 if (cur->value == curB->value) {
13399 found = 1;
13400 break;
13401 }
13402 curB = curB->next;
13403 }
13404 if (!found)
13405 break;
13406 cur = cur->next;
13407 }
13408 if (found)
13409 return(0);
13410 } else
13411 return(0);
13412 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013413 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013414 /*
13415 * 2 If either O1 or O2 is any, then any must be the value
13416 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013417 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013418 if (completeWild->any == 0) {
13419 completeWild->any = 1;
13420 if (completeWild->nsSet != NULL) {
13421 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13422 completeWild->nsSet = NULL;
13423 }
13424 if (completeWild->negNsSet != NULL) {
13425 xmlFree(completeWild->negNsSet);
13426 completeWild->negNsSet = NULL;
13427 }
13428 }
Daniel Veillard50355f02004-06-08 17:52:16 +000013429 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013430 }
13431 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013432 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000013433 * then the union of those sets must be the value.
13434 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013435 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013436 int found;
13437 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013438
Daniel Veillard3646d642004-06-02 19:19:14 +000013439 cur = curWild->nsSet;
13440 start = completeWild->nsSet;
13441 while (cur != NULL) {
13442 found = 0;
13443 curB = start;
13444 while (curB != NULL) {
13445 if (cur->value == curB->value) {
13446 found = 1;
13447 break;
13448 }
13449 curB = curB->next;
13450 }
13451 if (!found) {
13452 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013453 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013454 return (-1);
13455 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013456 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000013457 completeWild->nsSet = tmp;
13458 }
13459 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013460 }
13461
Daniel Veillard3646d642004-06-02 19:19:14 +000013462 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013463 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013464 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013465 * 4 If the two are negations of different values (namespace names
Daniel Veillard3646d642004-06-02 19:19:14 +000013466 * or ·absent·), then a pair of not and ·absent· must be the value.
13467 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013468 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013469 (curWild->negNsSet != NULL) &&
13470 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
13471 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000013472
13473 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013474 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013475 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013476 * 5.
13477 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013478 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013479 (completeWild->negNsSet->value != NULL) &&
13480 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013481 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013482 (curWild->negNsSet->value != NULL) &&
13483 (completeWild->nsSet != NULL))) {
13484
13485 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013486
Daniel Veillard3646d642004-06-02 19:19:14 +000013487 if (completeWild->nsSet != NULL) {
13488 cur = completeWild->nsSet;
13489 curB = curWild->negNsSet;
13490 } else {
13491 cur = curWild->nsSet;
13492 curB = completeWild->negNsSet;
13493 }
13494 nsFound = 0;
13495 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013496 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013497 absentFound = 1;
13498 else if (cur->value == curB->value)
13499 nsFound = 1;
13500 if (nsFound && absentFound)
13501 break;
13502 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013503 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013504
13505 if (nsFound && absentFound) {
13506 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013507 * 5.1 If the set S includes both the negated namespace
Daniel Veillard3646d642004-06-02 19:19:14 +000013508 * name and ·absent·, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013509 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013510 completeWild->any = 1;
13511 if (completeWild->nsSet != NULL) {
13512 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13513 completeWild->nsSet = NULL;
13514 }
13515 if (completeWild->negNsSet != NULL) {
13516 xmlFree(completeWild->negNsSet);
13517 completeWild->negNsSet = NULL;
13518 }
13519 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013520 /*
13521 * 5.2 If the set S includes the negated namespace name
13522 * but not ·absent·, then a pair of not and ·absent· must
Daniel Veillard3646d642004-06-02 19:19:14 +000013523 * be the value.
13524 */
13525 if (completeWild->nsSet != NULL) {
13526 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13527 completeWild->nsSet = NULL;
13528 }
13529 if (completeWild->negNsSet == NULL) {
13530 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13531 if (completeWild->negNsSet == NULL)
13532 return (-1);
13533 }
13534 completeWild->negNsSet->value = NULL;
13535 } else if ((!nsFound) && absentFound) {
13536 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013537 * 5.3 If the set S includes ·absent· but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000013538 * namespace name, then the union is not expressible.
13539 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013540 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000013541 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013542 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013543 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000013544 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000013545 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013546 /*
13547 * 5.4 If the set S does not include either the negated namespace
13548 * name or ·absent·, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000013549 * and a namespace name must be the value.
13550 */
13551 if (completeWild->negNsSet == NULL) {
13552 if (completeWild->nsSet != NULL) {
13553 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13554 completeWild->nsSet = NULL;
13555 }
13556 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13557 if (completeWild->negNsSet == NULL)
13558 return (-1);
13559 completeWild->negNsSet->value = curWild->negNsSet->value;
13560 }
13561 }
13562 return (0);
13563 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013564 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013565 * 6.
13566 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013567 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013568 (completeWild->negNsSet->value == NULL) &&
13569 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013570 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013571 (curWild->negNsSet->value == NULL) &&
13572 (completeWild->nsSet != NULL))) {
13573
13574 if (completeWild->nsSet != NULL) {
13575 cur = completeWild->nsSet;
13576 } else {
13577 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013578 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013579 while (cur != NULL) {
13580 if (cur->value == NULL) {
13581 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013582 * 6.1 If the set S includes ·absent·, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013583 * value.
13584 */
13585 completeWild->any = 1;
13586 if (completeWild->nsSet != NULL) {
13587 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13588 completeWild->nsSet = NULL;
13589 }
13590 if (completeWild->negNsSet != NULL) {
13591 xmlFree(completeWild->negNsSet);
13592 completeWild->negNsSet = NULL;
13593 }
13594 return (0);
13595 }
13596 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013597 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013598 if (completeWild->negNsSet == NULL) {
13599 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013600 * 6.2 If the set S does not include ·absent·, then a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000013601 * and ·absent· must be the value.
13602 */
13603 if (completeWild->nsSet != NULL) {
13604 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13605 completeWild->nsSet = NULL;
13606 }
13607 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13608 if (completeWild->negNsSet == NULL)
13609 return (-1);
13610 completeWild->negNsSet->value = NULL;
13611 }
13612 return (0);
13613 }
13614 return (0);
13615
13616}
13617
Daniel Veillard50355f02004-06-08 17:52:16 +000013618/**
13619 * xmlSchemaIntersectWildcards:
13620 * @ctxt: the schema parser context
13621 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013622 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013623 *
13624 * Intersects the namespace constraints of the given wildcards.
13625 * @completeWild will hold the resulting intersection.
13626 * Returns a positive error code on failure, -1 in case of an
13627 * internal error, 0 otherwise.
13628 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013629static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013630xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000013631 xmlSchemaWildcardPtr completeWild,
13632 xmlSchemaWildcardPtr curWild)
13633{
William M. Brack803812b2004-06-03 02:11:24 +000013634 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013635
13636 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013637 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013638 * value.
13639 */
13640 if ((completeWild->any == curWild->any) &&
13641 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13642 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013643
Daniel Veillard3646d642004-06-02 19:19:14 +000013644 if ((completeWild->negNsSet == NULL) ||
13645 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013646
Daniel Veillard3646d642004-06-02 19:19:14 +000013647 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000013648 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013649
13650 /*
13651 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000013652 */
13653 cur = completeWild->nsSet;
13654 while (cur != NULL) {
13655 found = 0;
13656 curB = curWild->nsSet;
13657 while (curB != NULL) {
13658 if (cur->value == curB->value) {
13659 found = 1;
13660 break;
13661 }
13662 curB = curB->next;
13663 }
13664 if (!found)
13665 break;
13666 cur = cur->next;
13667 }
13668 if (found)
13669 return(0);
13670 } else
13671 return(0);
13672 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013673 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013674 /*
13675 * 2 If either O1 or O2 is any, then the other must be the value.
13676 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013677 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013678 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013679 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000013680 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013681 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013682 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013683 * 3 If either O1 or O2 is a pair of not and a value (a namespace
13684 * name or ·absent·) and the other is a set of (namespace names or
13685 * ·absent·), then that set, minus the negated value if it was in
Daniel Veillard3646d642004-06-02 19:19:14 +000013686 * the set, minus ·absent· if it was in the set, must be the value.
13687 */
13688 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13689 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13690 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013691
Daniel Veillard3646d642004-06-02 19:19:14 +000013692 if (completeWild->nsSet == NULL) {
13693 neg = completeWild->negNsSet->value;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013694 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
Daniel Veillard3646d642004-06-02 19:19:14 +000013695 return(-1);
13696 } else
13697 neg = curWild->negNsSet->value;
13698 /*
13699 * Remove absent and negated.
13700 */
13701 prev = NULL;
13702 cur = completeWild->nsSet;
13703 while (cur != NULL) {
13704 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013705 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013706 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013707 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013708 prev->next = cur->next;
13709 xmlFree(cur);
13710 break;
13711 }
13712 prev = cur;
13713 cur = cur->next;
13714 }
13715 if (neg != NULL) {
13716 prev = NULL;
13717 cur = completeWild->nsSet;
13718 while (cur != NULL) {
13719 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013720 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013721 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013722 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013723 prev->next = cur->next;
13724 xmlFree(cur);
13725 break;
13726 }
13727 prev = cur;
13728 cur = cur->next;
13729 }
13730 }
13731
13732 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013733 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013734 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013735 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000013736 * then the intersection of those sets must be the value.
13737 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013738 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013739 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013740
Daniel Veillard3646d642004-06-02 19:19:14 +000013741 cur = completeWild->nsSet;
13742 prev = NULL;
13743 while (cur != NULL) {
13744 found = 0;
13745 curB = curWild->nsSet;
13746 while (curB != NULL) {
13747 if (cur->value == curB->value) {
13748 found = 1;
13749 break;
13750 }
13751 curB = curB->next;
13752 }
13753 if (!found) {
13754 if (prev == NULL)
13755 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013756 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013757 prev->next = cur->next;
13758 tmp = cur->next;
13759 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013760 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013761 continue;
13762 }
13763 prev = cur;
13764 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013765 }
13766
Daniel Veillard3646d642004-06-02 19:19:14 +000013767 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013768 }
13769 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000013770 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013771 */
13772 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013773 (curWild->negNsSet != NULL) &&
13774 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013775 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013776 (curWild->negNsSet->value != NULL)) {
13777
13778 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013779 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013780 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000013781 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013782 }
13783 /*
13784 * 6 If the one is a negation of a namespace name and the other
13785 * is a negation of ·absent·, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000013786 * of a namespace name must be the value.
13787 */
13788 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13789 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013790 (completeWild->negNsSet->value == NULL)) {
13791 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000013792 }
13793 return(0);
13794}
13795
Daniel Veillard50355f02004-06-08 17:52:16 +000013796/**
13797 * xmlSchemaIsWildcardNsConstraintSubset:
13798 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013799 * @sub: the first wildcard
13800 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013801 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013802 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13803 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013804 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013805 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000013806 */
13807static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013808xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13809 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013810{
Daniel Veillard50355f02004-06-08 17:52:16 +000013811 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013812 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000013813 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013814 if (super->any)
13815 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000013816 /*
13817 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
13818 * 2.2 super must be a pair of not and the same value.
13819 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013820 if ((sub->negNsSet != NULL) &&
13821 (super->negNsSet != NULL) &&
13822 (sub->negNsSet->value == sub->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013823 return (0);
13824 /*
13825 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
Daniel Veillard50355f02004-06-08 17:52:16 +000013826 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013827 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013828 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013829 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000013830 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013831 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013832 xmlSchemaWildcardNsPtr cur, curB;
13833 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013834
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013835 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000013836 while (cur != NULL) {
13837 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013838 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000013839 while (curB != NULL) {
13840 if (cur->value == curB->value) {
13841 found = 1;
13842 break;
13843 }
13844 curB = curB->next;
13845 }
13846 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013847 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013848 cur = cur->next;
13849 }
13850 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013851 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013852 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013853 xmlSchemaWildcardNsPtr cur;
13854 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013855 * 3.2.2 super must be a pair of not and a namespace name or
13856 * ·absent· and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000013857 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013858 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013859 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013860 if (cur->value == super->negNsSet->value)
13861 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013862 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013863 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013864 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000013865 }
13866 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013867 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013868}
13869
Daniel Veillard50355f02004-06-08 17:52:16 +000013870static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013871xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013872 int *fixed,
13873 const xmlChar **value,
13874 xmlSchemaValPtr *val)
13875{
13876 *fixed = 0;
13877 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013878 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013879 *val = NULL;
13880
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013881 if (attruse->defValue != NULL) {
13882 *value = attruse->defValue;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000013883 if (val != NULL)
13884 *val = attruse->defVal;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013885 if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013886 *fixed = 1;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013887 return(1);
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000013888 } else if ((attruse->attrDecl != NULL) &&
13889 (attruse->attrDecl->defValue != NULL)) {
13890 *value = attruse->attrDecl->defValue;
13891 if (val != NULL)
13892 *val = attruse->attrDecl->defVal;
13893 if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013894 *fixed = 1;
13895 return(1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013896 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013897 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013898}
Daniel Veillard3646d642004-06-02 19:19:14 +000013899/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013900 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000013901 * @wild: the wildcard
13902 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013903 *
13904 * Validation Rule: Wildcard allows Namespace Name
13905 * (cvc-wildcard-namespace)
13906 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013907 * Returns 0 if the given namespace matches the wildcard,
13908 * 1 otherwise and -1 on API errors.
Daniel Veillard3646d642004-06-02 19:19:14 +000013909 */
13910static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013911xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
13912 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000013913{
13914 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013915 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000013916
13917 if (wild->any)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013918 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013919 else if (wild->nsSet != NULL) {
13920 xmlSchemaWildcardNsPtr cur;
13921
13922 cur = wild->nsSet;
13923 while (cur != NULL) {
13924 if (xmlStrEqual(cur->value, ns))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013925 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013926 cur = cur->next;
13927 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013928 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013929 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013930 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013931
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013932 return(1);
13933}
13934
13935#define XML_SCHEMA_ACTION_DERIVE 0
13936#define XML_SCHEMA_ACTION_REDEFINE 1
13937
13938#define WXS_ACTION_STR(a) \
13939((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
13940
13941/*
13942* Schema Component Constraint:
13943* Derivation Valid (Restriction, Complex)
13944* derivation-ok-restriction (2) - (4)
13945*
13946* ATTENTION:
13947* In XML Schema 1.1 this will be:
13948* Validation Rule:
13949* Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
13950*
13951*/
13952static int
13953xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
13954 int action,
13955 xmlSchemaBasicItemPtr item,
13956 xmlSchemaBasicItemPtr baseItem,
13957 xmlSchemaItemListPtr uses,
13958 xmlSchemaItemListPtr baseUses,
13959 xmlSchemaWildcardPtr wild,
13960 xmlSchemaWildcardPtr baseWild)
13961{
13962 xmlSchemaAttributeUsePtr cur = NULL, bcur;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000013963 int i, j, found; /* err = 0; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013964 const xmlChar *bEffValue;
13965 int effFixed;
13966
13967 if (uses != NULL) {
13968 for (i = 0; i < uses->nbItems; i++) {
13969 cur = uses->items[i];
13970 found = 0;
13971 if (baseUses == NULL)
13972 goto not_found;
13973 for (j = 0; j < baseUses->nbItems; j++) {
13974 bcur = baseUses->items[j];
13975 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
13976 WXS_ATTRUSE_DECL_NAME(bcur)) &&
13977 (WXS_ATTRUSE_DECL_TNS(cur) ==
13978 WXS_ATTRUSE_DECL_TNS(bcur)))
13979 {
13980 /*
13981 * (2.1) "If there is an attribute use in the {attribute
13982 * uses} of the {base type definition} (call this B) whose
13983 * {attribute declaration} has the same {name} and {target
13984 * namespace}, then all of the following must be true:"
13985 */
13986 found = 1;
13987
13988 if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
13989 (bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
13990 {
13991 xmlChar *str = NULL;
13992 /*
13993 * (2.1.1) "one of the following must be true:"
13994 * (2.1.1.1) "B's {required} is false."
13995 * (2.1.1.2) "R's {required} is true."
13996 */
13997 xmlSchemaPAttrUseErr4(pctxt,
13998 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
13999 WXS_ITEM_NODE(item), item, cur,
14000 "The 'optional' attribute use is inconsistent "
14001 "with the corresponding 'required' attribute use of "
14002 "the %s %s",
14003 WXS_ACTION_STR(action),
14004 xmlSchemaGetComponentDesignation(&str, baseItem),
14005 NULL, NULL);
14006 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014007 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014008 } else if (xmlSchemaCheckCOSSTDerivedOK(pctxt,
14009 WXS_ATTRUSE_TYPEDEF(cur),
14010 WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14011 {
14012 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14013
14014 /*
14015 * SPEC (2.1.2) "R's {attribute declaration}'s
14016 * {type definition} must be validly derived from
14017 * B's {type definition} given the empty set as
14018 * defined in Type Derivation OK (Simple) (§3.14.6)."
14019 */
14020 xmlSchemaPAttrUseErr4(pctxt,
14021 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14022 WXS_ITEM_NODE(item), item, cur,
14023 "The attribute declaration's %s "
14024 "is not validly derived from "
14025 "the corresponding %s of the "
14026 "attribute declaration in the %s %s",
14027 xmlSchemaGetComponentDesignation(&strA,
14028 WXS_ATTRUSE_TYPEDEF(cur)),
14029 xmlSchemaGetComponentDesignation(&strB,
14030 WXS_ATTRUSE_TYPEDEF(bcur)),
14031 WXS_ACTION_STR(action),
14032 xmlSchemaGetComponentDesignation(&strC, baseItem));
14033 /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14034 FREE_AND_NULL(strA);
14035 FREE_AND_NULL(strB);
14036 FREE_AND_NULL(strC);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014037 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014038 } else {
14039 /*
14040 * 2.1.3 [Definition:] Let the effective value
14041 * constraint of an attribute use be its {value
14042 * constraint}, if present, otherwise its {attribute
14043 * declaration}'s {value constraint} .
14044 */
14045 xmlSchemaGetEffectiveValueConstraint(bcur,
14046 &effFixed, &bEffValue, NULL);
14047 /*
14048 * 2.1.3 ... one of the following must be true
14049 *
14050 * 2.1.3.1 B's ·effective value constraint· is
14051 * ·absent· or default.
14052 */
14053 if ((bEffValue != NULL) &&
14054 (effFixed == 1)) {
14055 const xmlChar *rEffValue = NULL;
14056
14057 xmlSchemaGetEffectiveValueConstraint(bcur,
14058 &effFixed, &rEffValue, NULL);
14059 /*
14060 * 2.1.3.2 R's ·effective value constraint· is
14061 * fixed with the same string as B's.
14062 * MAYBE TODO: Compare the computed values.
14063 * Hmm, it says "same string" so
14064 * string-equality might really be sufficient.
14065 */
14066 if ((effFixed == 0) ||
14067 (! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14068 {
14069 xmlChar *str = NULL;
14070
14071 xmlSchemaPAttrUseErr4(pctxt,
14072 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14073 WXS_ITEM_NODE(item), item, cur,
14074 "The effective value constraint of the "
14075 "attribute use is inconsistent with "
14076 "its correspondent in the %s %s",
14077 WXS_ACTION_STR(action),
14078 xmlSchemaGetComponentDesignation(&str,
14079 baseItem),
14080 NULL, NULL);
14081 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014082 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014083 }
14084 }
14085 }
14086 break;
14087 }
14088 }
14089not_found:
14090 if (!found) {
14091 /*
14092 * (2.2) "otherwise the {base type definition} must have an
14093 * {attribute wildcard} and the {target namespace} of the
14094 * R's {attribute declaration} must be ·valid· with respect
14095 * to that wildcard, as defined in Wildcard allows Namespace
14096 * Name (§3.10.4)."
14097 */
14098 if ((baseWild == NULL) ||
14099 (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14100 (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14101 {
14102 xmlChar *str = NULL;
14103
14104 xmlSchemaPAttrUseErr4(pctxt,
14105 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14106 WXS_ITEM_NODE(item), item, cur,
14107 "Neither a matching attribute use, "
14108 "nor a matching wildcard exists in the %s %s",
14109 WXS_ACTION_STR(action),
14110 xmlSchemaGetComponentDesignation(&str, baseItem),
14111 NULL, NULL);
14112 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014113 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014114 }
14115 }
14116 }
14117 }
14118 /*
14119 * SPEC derivation-ok-restriction (3):
14120 * (3) "For each attribute use in the {attribute uses} of the {base type
14121 * definition} whose {required} is true, there must be an attribute
14122 * use with an {attribute declaration} with the same {name} and
14123 * {target namespace} as its {attribute declaration} in the {attribute
14124 * uses} of the complex type definition itself whose {required} is true.
14125 */
14126 if (baseUses != NULL) {
14127 for (j = 0; j < baseUses->nbItems; j++) {
14128 bcur = baseUses->items[j];
14129 if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14130 continue;
14131 found = 0;
14132 if (uses != NULL) {
14133 for (i = 0; i < uses->nbItems; i++) {
14134 cur = uses->items[i];
14135 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14136 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14137 (WXS_ATTRUSE_DECL_TNS(cur) ==
14138 WXS_ATTRUSE_DECL_TNS(bcur))) {
14139 found = 1;
14140 break;
14141 }
14142 }
14143 }
14144 if (!found) {
14145 xmlChar *strA = NULL, *strB = NULL;
14146
14147 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14148 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14149 NULL, item,
14150 "A matching attribute use for the "
14151 "'required' %s of the %s %s is missing",
14152 xmlSchemaGetComponentDesignation(&strA, bcur),
14153 WXS_ACTION_STR(action),
14154 xmlSchemaGetComponentDesignation(&strB, baseItem),
14155 NULL);
14156 FREE_AND_NULL(strA);
14157 FREE_AND_NULL(strB);
14158 }
14159 }
14160 }
14161 /*
14162 * derivation-ok-restriction (4)
14163 */
14164 if (wild != NULL) {
14165 /*
14166 * (4) "If there is an {attribute wildcard}, all of the
14167 * following must be true:"
14168 */
14169 if (baseWild == NULL) {
14170 xmlChar *str = NULL;
14171
14172 /*
14173 * (4.1) "The {base type definition} must also have one."
14174 */
14175 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14176 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14177 NULL, item,
14178 "The %s has an attribute wildcard, "
14179 "but the %s %s '%s' does not have one",
14180 WXS_ITEM_TYPE_NAME(item),
14181 WXS_ACTION_STR(action),
14182 WXS_ITEM_TYPE_NAME(baseItem),
14183 xmlSchemaGetComponentQName(&str, baseItem));
14184 FREE_AND_NULL(str);
14185 return(pctxt->err);
14186 } else if ((baseWild->any == 0) &&
14187 xmlSchemaCheckCOSNSSubset(wild, baseWild))
14188 {
14189 xmlChar *str = NULL;
14190 /*
14191 * (4.2) "The complex type definition's {attribute wildcard}'s
14192 * {namespace constraint} must be a subset of the {base type
14193 * definition}'s {attribute wildcard}'s {namespace constraint},
14194 * as defined by Wildcard Subset (§3.10.6)."
14195 */
14196 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14197 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14198 NULL, item,
14199 "The attribute wildcard is not a valid "
14200 "subset of the wildcard in the %s %s '%s'",
14201 WXS_ACTION_STR(action),
14202 WXS_ITEM_TYPE_NAME(baseItem),
14203 xmlSchemaGetComponentQName(&str, baseItem),
14204 NULL);
14205 FREE_AND_NULL(str);
14206 return(pctxt->err);
14207 }
14208 /* 4.3 Unless the {base type definition} is the ·ur-type
14209 * definition·, the complex type definition's {attribute
14210 * wildcard}'s {process contents} must be identical to or
14211 * stronger than the {base type definition}'s {attribute
14212 * wildcard}'s {process contents}, where strict is stronger
14213 * than lax is stronger than skip.
14214 */
14215 if ((! WXS_IS_ANYTYPE(baseItem)) &&
14216 (wild->processContents < baseWild->processContents)) {
14217 xmlChar *str = NULL;
14218 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14219 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14220 NULL, baseItem,
14221 "The {process contents} of the attribute wildcard is "
14222 "weaker than the one in the %s %s '%s'",
14223 WXS_ACTION_STR(action),
14224 WXS_ITEM_TYPE_NAME(baseItem),
14225 xmlSchemaGetComponentQName(&str, baseItem),
14226 NULL);
14227 FREE_AND_NULL(str)
14228 return(pctxt->err);
14229 }
14230 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014231 return(0);
14232}
14233
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014234
14235static int
14236xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14237 xmlSchemaBasicItemPtr item,
14238 xmlSchemaWildcardPtr *completeWild,
14239 xmlSchemaItemListPtr list,
14240 xmlSchemaItemListPtr prohibs);
Daniel Veillard3646d642004-06-02 19:19:14 +000014241/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014242 * xmlSchemaFixupTypeAttributeUses:
Daniel Veillard3646d642004-06-02 19:19:14 +000014243 * @ctxt: the schema parser context
14244 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014245 *
Daniel Veillard3646d642004-06-02 19:19:14 +000014246 *
14247 * Builds the wildcard and the attribute uses on the given complex type.
14248 * Returns -1 if an internal error occurs, 0 otherwise.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014249 *
14250 * ATTENTION TODO: Experimantally this uses pointer comparisons for
14251 * strings, so recheck this if we start to hardcode some schemata, since
14252 * they might not be in the same dict.
14253 * NOTE: It is allowed to "extend" the xs:anyType type.
Daniel Veillard3646d642004-06-02 19:19:14 +000014254 */
14255static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014256xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014257 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000014258{
14259 xmlSchemaTypePtr baseType = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014260 xmlSchemaAttributeUsePtr use;
14261 xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000014262
Daniel Veillard01fa6152004-06-29 17:04:39 +000014263 if (type->baseType == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014264 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014265 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014266 return (-1);
14267 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014268 baseType = type->baseType;
14269 if (WXS_IS_TYPE_NOT_FIXED(baseType))
14270 if (xmlSchemaTypeFixup(baseType, pctxt) == -1)
14271 return(-1);
14272
14273 uses = type->attrUses;
14274 baseUses = baseType->attrUses;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014275 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014276 * Expand attribute group references. And build the 'complete'
14277 * wildcard, i.e. intersect multiple wildcards.
14278 * Move attribute prohibitions into a separate list.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014279 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014280 if (uses != NULL) {
14281 if (WXS_IS_RESTRICTION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014282 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014283 * This one will transfer all attr. prohibitions
14284 * into pctxt->attrProhibs.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014285 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014286 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14287 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14288 pctxt->attrProhibs) == -1)
14289 {
14290 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14291 "failed to expand attributes");
14292 }
14293 if (pctxt->attrProhibs->nbItems != 0)
14294 prohibs = pctxt->attrProhibs;
14295 } else {
14296 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14297 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14298 NULL) == -1)
14299 {
14300 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14301 "failed to expand attributes");
14302 }
14303 }
14304 }
14305 /*
14306 * Inherit the attribute uses of the base type.
14307 */
14308 if (baseUses != NULL) {
14309 int i, j;
14310 xmlSchemaAttributeUseProhibPtr pro;
14311
14312 if (WXS_IS_RESTRICTION(type)) {
14313 int usesCount;
14314 xmlSchemaAttributeUsePtr tmp;
14315
14316 if (uses != NULL)
14317 usesCount = uses->nbItems;
14318 else
14319 usesCount = 0;
14320
14321 /* Restriction. */
14322 for (i = 0; i < baseUses->nbItems; i++) {
14323 use = baseUses->items[i];
14324 if (prohibs) {
14325 /*
14326 * Filter out prohibited uses.
14327 */
14328 for (j = 0; j < prohibs->nbItems; j++) {
14329 pro = prohibs->items[j];
14330 if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14331 (WXS_ATTRUSE_DECL_TNS(use) ==
14332 pro->targetNamespace))
14333 {
14334 goto inherit_next;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014335 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014336 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014337 }
14338 if (usesCount) {
14339 /*
14340 * Filter out existing uses.
14341 */
14342 for (j = 0; j < usesCount; j++) {
14343 tmp = uses->items[j];
14344 if ((WXS_ATTRUSE_DECL_NAME(use) ==
14345 WXS_ATTRUSE_DECL_NAME(tmp)) &&
14346 (WXS_ATTRUSE_DECL_TNS(use) ==
14347 WXS_ATTRUSE_DECL_TNS(tmp)))
14348 {
14349 goto inherit_next;
14350 }
14351 }
14352 }
14353 if (uses == NULL) {
14354 type->attrUses = xmlSchemaItemListCreate();
14355 if (type->attrUses == NULL)
14356 goto exit_failure;
14357 uses = type->attrUses;
14358 }
14359 xmlSchemaItemListAddSize(uses, 2, use);
14360inherit_next: {}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014361 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014362 } else {
14363 /* Extension. */
14364 for (i = 0; i < baseUses->nbItems; i++) {
14365 use = baseUses->items[i];
14366 if (uses == NULL) {
14367 type->attrUses = xmlSchemaItemListCreate();
14368 if (type->attrUses == NULL)
14369 goto exit_failure;
14370 uses = type->attrUses;
14371 }
14372 xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14373 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014374 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014375 }
14376 /*
14377 * Shrink attr. uses.
14378 */
14379 if (uses) {
14380 if (uses->nbItems == 0) {
14381 xmlSchemaItemListFree(uses);
14382 type->attrUses = NULL;
14383 }
14384 /*
14385 * TODO: We could shrink the size of the array
14386 * to fit the actual number of items.
14387 */
14388 }
14389 /*
14390 * Compute the complete wildcard.
14391 */
14392 if (WXS_IS_EXTENSION(type)) {
14393 if (baseType->attributeWildcard != NULL) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014394 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014395 * (3.2.2.1) "If the ·base wildcard· is non-·absent·, then
14396 * the appropriate case among the following:"
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014397 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014398 if (type->attributeWildcard != NULL) {
14399 /*
14400 * Union the complete wildcard with the base wildcard.
14401 * SPEC {attribute wildcard}
14402 * (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14403 * and {annotation} are those of the ·complete wildcard·,
14404 * and whose {namespace constraint} is the intensional union
14405 * of the {namespace constraint} of the ·complete wildcard·
14406 * and of the ·base wildcard·, as defined in Attribute
14407 * Wildcard Union (§3.10.6)."
14408 */
14409 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14410 baseType->attributeWildcard) == -1)
14411 goto exit_failure;
14412 } else {
14413 /*
14414 * (3.2.2.1.1) "If the ·complete wildcard· is ·absent·,
14415 * then the ·base wildcard·."
14416 */
14417 type->attributeWildcard = baseType->attributeWildcard;
14418 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014419 } else {
14420 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014421 * (3.2.2.2) "otherwise (the ·base wildcard· is ·absent·) the
14422 * ·complete wildcard"
14423 * NOOP
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014424 */
Daniel Veillard50355f02004-06-08 17:52:16 +000014425 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014426 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014427 /*
14428 * SPEC {attribute wildcard}
14429 * (3.1) "If the <restriction> alternative is chosen, then the
14430 * ·complete wildcard·;"
14431 * NOOP
14432 */
Daniel Veillard50355f02004-06-08 17:52:16 +000014433 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014434
Daniel Veillard3646d642004-06-02 19:19:14 +000014435 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014436
14437exit_failure:
14438 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000014439}
14440
14441/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000014442 * xmlSchemaTypeFinalContains:
14443 * @schema: the schema
14444 * @type: the type definition
14445 * @final: the final
14446 *
14447 * Evaluates if a type definition contains the given "final".
14448 * This does take "finalDefault" into account as well.
14449 *
14450 * Returns 1 if the type does containt the given "final",
14451 * 0 otherwise.
14452 */
14453static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014454xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014455{
Daniel Veillard01fa6152004-06-29 17:04:39 +000014456 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014457 return (0);
14458 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014459 return (1);
14460 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014461 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014462}
14463
14464/**
14465 * xmlSchemaGetUnionSimpleTypeMemberTypes:
14466 * @type: the Union Simple Type
14467 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014468 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014469 * returns NULL otherwise.
14470 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014471static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000014472xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14473{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014474 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014475 if (type->memberTypes != NULL)
14476 return (type->memberTypes);
14477 else
14478 type = type->baseType;
14479 }
14480 return (NULL);
14481}
14482
14483/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014484 * xmlSchemaGetParticleTotalRangeMin:
14485 * @particle: the particle
14486 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014487 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014488 * (all and sequence) + (choice)
14489 *
14490 * Returns the minimun Effective Total Range.
14491 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014492static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014493xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014494{
14495 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014496 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014497 return (0);
14498 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014499 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014500 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014501 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014502
14503 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014504 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014505 while (part != NULL) {
14506 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14507 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014508 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014509 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014510 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014511 if (cur == 0)
14512 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014513 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014514 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014515 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014516 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014517 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014518 } else {
14519 /* <all> and <sequence> */
14520 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014521 xmlSchemaParticlePtr part =
14522 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014523
14524 if (part == NULL)
14525 return (0);
14526 do {
14527 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14528 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014529 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014530 else
14531 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014532 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014533 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014534 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014535 }
14536}
14537
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014538/**
14539 * xmlSchemaGetParticleTotalRangeMax:
14540 * @particle: the particle
14541 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014542 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014543 * (all and sequence) + (choice)
14544 *
14545 * Returns the maximum Effective Total Range.
14546 */
14547static int
14548xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14549{
14550 if ((particle->children == NULL) ||
14551 (particle->children->children == NULL))
14552 return (0);
14553 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14554 int max = -1, cur;
14555 xmlSchemaParticlePtr part =
14556 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014557
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014558 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14559 if (part->children == NULL)
14560 continue;
14561 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14562 (part->children->type == XML_SCHEMA_TYPE_ANY))
14563 cur = part->maxOccurs;
14564 else
14565 cur = xmlSchemaGetParticleTotalRangeMax(part);
14566 if (cur == UNBOUNDED)
14567 return (UNBOUNDED);
14568 if ((max < cur) || (max == -1))
14569 max = cur;
14570 }
14571 /* TODO: Handle overflows? */
14572 return (particle->maxOccurs * max);
14573 } else {
14574 /* <all> and <sequence> */
14575 int sum = 0, cur;
14576 xmlSchemaParticlePtr part =
14577 (xmlSchemaParticlePtr) particle->children->children;
14578
14579 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14580 if (part->children == NULL)
14581 continue;
14582 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14583 (part->children->type == XML_SCHEMA_TYPE_ANY))
14584 cur = part->maxOccurs;
14585 else
14586 cur = xmlSchemaGetParticleTotalRangeMax(part);
14587 if (cur == UNBOUNDED)
14588 return (UNBOUNDED);
14589 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14590 return (UNBOUNDED);
14591 sum += cur;
14592 }
14593 /* TODO: Handle overflows? */
14594 return (particle->maxOccurs * sum);
14595 }
14596}
14597
14598/**
14599 * xmlSchemaIsParticleEmptiable:
14600 * @particle: the particle
14601 *
14602 * Schema Component Constraint: Particle Emptiable
14603 * Checks whether the given particle is emptiable.
14604 *
14605 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014606 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014607static int
14608xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14609{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014610 /*
14611 * SPEC (1) "Its {min occurs} is 0."
14612 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014613 if ((particle == NULL) || (particle->minOccurs == 0) ||
14614 (particle->children == NULL))
14615 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014616 /*
14617 * SPEC (2) "Its {term} is a group and the minimum part of the
14618 * effective total range of that group, [...] is 0."
14619 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014620 if (WXS_IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014621 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014622 return (1);
14623 }
14624 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014625}
14626
14627/**
14628 * xmlSchemaCheckCOSSTDerivedOK:
14629 * @type: the derived simple type definition
14630 * @baseType: the base type definition
14631 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014632 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014633 * Type Derivation OK (Simple) (cos-st-derived-OK)
14634 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014635 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000014636 * derived from @baseType.
14637 *
14638 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014639 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014640static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014641xmlSchemaCheckCOSSTDerivedOK(xmlSchemaParserCtxtPtr ctxt,
14642 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014643 xmlSchemaTypePtr baseType,
14644 int subset)
14645{
Daniel Veillard01fa6152004-06-29 17:04:39 +000014646 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014647 * 1 They are the same type definition.
14648 * TODO: The identy check might have to be more complex than this.
14649 */
14650 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014651 return (0);
14652 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014653 * 2.1 restriction is not in the subset, or in the {final}
14654 * of its own {base type definition};
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014655 * TODO: Revise this, it looks strange.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014656 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014657 if (WXS_IS_TYPE_NOT_FIXED(type))
14658 if (xmlSchemaTypeFixup(type, ctxt) == -1)
14659 return(-1);
14660 if (WXS_IS_TYPE_NOT_FIXED(baseType))
14661 if (xmlSchemaTypeFixup(baseType, ctxt) == -1)
14662 return(-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014663 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014664 (xmlSchemaTypeFinalContains(type->baseType,
14665 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14666 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014667 }
14668 /* 2.2 */
14669 if (type->baseType == baseType) {
14670 /*
14671 * 2.2.1 D's ·base type definition· is B.
14672 */
14673 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014674 }
14675 /*
14676 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
14677 * and is validly derived from B given the subset, as defined by this
14678 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014679 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014680 if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14681 (xmlSchemaCheckCOSSTDerivedOK(ctxt, type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014682 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014683 return (0);
14684 }
14685 /*
14686 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
Daniel Veillard01fa6152004-06-29 17:04:39 +000014687 * definition·.
14688 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014689 if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14690 (WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014691 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014692 }
14693 /*
14694 * 2.2.4 B's {variety} is union and D is validly derived from a type
14695 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000014696 * defined by this constraint.
14697 *
14698 * NOTE: This seems not to involve built-in types, since there is no
14699 * built-in Union Simple Type.
14700 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014701 if (WXS_IS_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014702 xmlSchemaTypeLinkPtr cur;
14703
14704 cur = baseType->memberTypes;
14705 while (cur != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014706 if (WXS_IS_TYPE_NOT_FIXED(cur->type))
14707 if (xmlSchemaTypeFixup(cur->type, ctxt) == -1)
14708 return(-1);
14709 if (xmlSchemaCheckCOSSTDerivedOK(ctxt,
14710 type, cur->type, subset) == 0)
14711 {
14712 /*
14713 * It just has to be validly derived from at least one
14714 * member-type.
14715 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014716 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014717 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014718 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014719 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014720 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014721 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14722}
14723
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014724/**
14725 * xmlSchemaCheckTypeDefCircularInternal:
14726 * @pctxt: the schema parser context
14727 * @ctxtType: the type definition
14728 * @ancestor: an ancestor of @ctxtType
14729 *
14730 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014731 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014732 *
14733 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14734 * circular, 0 otherwise.
14735 */
14736static int
14737xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14738 xmlSchemaTypePtr ctxtType,
14739 xmlSchemaTypePtr ancestor)
14740{
14741 int ret;
14742
14743 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14744 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014745
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014746 if (ctxtType == ancestor) {
14747 xmlSchemaPCustomErr(pctxt,
14748 XML_SCHEMAP_ST_PROPS_CORRECT_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014749 WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014750 "The definition is circular", NULL);
14751 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14752 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014753 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14754 /*
14755 * Avoid inifinite recursion on circular types not yet checked.
14756 */
14757 return (0);
14758 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014759 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14760 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14761 ancestor->baseType);
14762 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14763 return (ret);
14764}
14765
14766/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014767 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014768 * @item: the complex/simple type definition
14769 * @ctxt: the parser context
14770 * @name: the name
14771 *
14772 * Checks for circular type definitions.
14773 */
14774static void
14775xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014776 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014777{
14778 if ((item == NULL) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014779 (item->type == XML_SCHEMA_TYPE_BASIC) ||
14780 (item->baseType == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014781 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014782 xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14783 item->baseType);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014784}
Daniel Veillard01fa6152004-06-29 17:04:39 +000014785
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014786/*
14787* Simple Type Definition Representation OK (src-simple-type) 4
14788*
14789* "4 Circular union type definition is disallowed. That is, if the
14790* <union> alternative is chosen, there must not be any entries in the
14791* memberTypes [attribute] at any depth which resolve to the component
14792* corresponding to the <simpleType>."
14793*
14794* Note that this should work on the *representation* of a component,
14795* thus assumes any union types in the member types not being yet
14796* substituted. At this stage we need the variety of the types
14797* to be already computed.
14798*/
14799static int
14800xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14801 xmlSchemaTypePtr ctxType,
14802 xmlSchemaTypeLinkPtr members)
14803{
14804 xmlSchemaTypeLinkPtr member;
14805 xmlSchemaTypePtr memberType;
14806
14807 member = members;
14808 while (member != NULL) {
14809 memberType = member->type;
14810 while ((memberType != NULL) &&
14811 (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14812 if (memberType == ctxType) {
14813 xmlSchemaPCustomErr(pctxt,
14814 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014815 WXS_BASIC_CAST ctxType, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014816 "The union type definition is circular", NULL);
14817 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14818 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014819 if ((WXS_IS_UNION(memberType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014820 ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14821 {
14822 int res;
14823 memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14824 res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
14825 ctxType,
14826 xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
14827 memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
14828 if (res != 0)
14829 return(res);
14830 }
14831 memberType = memberType->baseType;
14832 }
14833 member = member->next;
14834 }
14835 return(0);
14836}
14837
14838static int
14839xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
14840 xmlSchemaTypePtr type)
14841{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014842 if (! WXS_IS_UNION(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014843 return(0);
14844 return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
14845 type->memberTypes));
14846}
14847
Daniel Veillard01fa6152004-06-29 17:04:39 +000014848/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014849 * xmlSchemaResolveTypeReferences:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014850 * @item: the complex/simple type definition
14851 * @ctxt: the parser context
14852 * @name: the name
14853 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014854 * Resolvese type definition references
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014855 */
14856static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014857xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014858 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014859{
14860 if (typeDef == NULL)
14861 return;
14862
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014863 /*
14864 * Resolve the base type.
14865 */
14866 if (typeDef->baseType == NULL) {
14867 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
14868 typeDef->base, typeDef->baseNs);
14869 if (typeDef->baseType == NULL) {
14870 xmlSchemaPResCompAttrErr(ctxt,
14871 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014872 WXS_BASIC_CAST typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014873 "base", typeDef->base, typeDef->baseNs,
14874 XML_SCHEMA_TYPE_SIMPLE, NULL);
14875 return;
14876 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014877 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014878 if (WXS_IS_SIMPLE(typeDef)) {
14879 if (WXS_IS_UNION(typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014880 /*
14881 * Resolve the memberTypes.
14882 */
14883 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
14884 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014885 } else if (WXS_IS_LIST(typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014886 /*
14887 * Resolve the itemType.
14888 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014889 if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
14890
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014891 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014892 typeDef->base, typeDef->baseNs);
14893
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014894 if ((typeDef->subtypes == NULL) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014895 (! WXS_IS_SIMPLE(typeDef->subtypes)))
14896 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014897 typeDef->subtypes = NULL;
14898 xmlSchemaPResCompAttrErr(ctxt,
14899 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014900 WXS_BASIC_CAST typeDef, typeDef->node,
14901 "itemType", typeDef->base, typeDef->baseNs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014902 XML_SCHEMA_TYPE_SIMPLE, NULL);
14903 }
14904 }
14905 return;
14906 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014907 }
14908 /*
14909 * The ball of letters below means, that if we have a particle
14910 * which has a QName-helper component as its {term}, we want
14911 * to resolve it...
14912 */
14913 else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
14914 ((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
14915 XML_SCHEMA_TYPE_PARTICLE) &&
14916 (WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
14917 ((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
14918 XML_SCHEMA_EXTRA_QNAMEREF))
14919 {
14920 xmlSchemaQNameRefPtr ref =
14921 WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
14922 xmlSchemaModelGroupDefPtr groupDef;
14923
14924 /*
14925 * URGENT TODO: Test this.
14926 */
14927 WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
14928 /*
14929 * Resolve the MG definition reference.
14930 */
14931 groupDef =
14932 WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
14933 ref->itemType, ref->name, ref->targetNamespace);
14934 if (groupDef == NULL) {
14935 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
14936 NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
14937 "ref", ref->name, ref->targetNamespace, ref->itemType,
14938 NULL);
14939 /* Remove the particle. */
14940 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
14941 } else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
14942 /* Remove the particle. */
14943 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
14944 else {
14945 /*
14946 * Assign the MG definition's {model group} to the
14947 * particle's {term}.
14948 */
14949 WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
14950
14951 if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
14952 /*
14953 * SPEC cos-all-limited (1.2)
14954 * "1.2 the {term} property of a particle with
14955 * {max occurs}=1 which is part of a pair which constitutes
14956 * the {content type} of a complex type definition."
14957 */
14958 if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
14959 xmlSchemaCustomErr(ACTXT_CAST ctxt,
14960 /* TODO: error code */
14961 XML_SCHEMAP_COS_ALL_LIMITED,
14962 WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
14963 "The particle's {max occurs} must be 1, since the "
14964 "reference resolves to an 'all' model group",
14965 NULL, NULL);
14966 }
14967 }
14968 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014969 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014970}
14971
14972
14973
14974/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000014975 * xmlSchemaCheckSTPropsCorrect:
14976 * @ctxt: the schema parser context
14977 * @type: the simple type definition
14978 *
14979 * Checks st-props-correct.
14980 *
14981 * Returns 0 if the properties are correct,
14982 * if not, a positive error code and -1 on internal
14983 * errors.
14984 */
14985static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014986xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014987 xmlSchemaTypePtr type)
14988{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014989 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014990 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014991
Daniel Veillardc0826a72004-08-10 14:17:33 +000014992 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014993 /*
14994 * Schema Component Constraint: Simple Type Definition Properties Correct
14995 *
14996 * NOTE: This is somehow redundant, since we actually built a simple type
14997 * to have all the needed information; this acts as an self test.
14998 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014999 /* Base type: If the datatype has been ·derived· by ·restriction·
15000 * then the Simple Type Definition component from which it is ·derived·,
15001 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000015002 */
15003 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015004 /*
15005 * TODO: Think about: "modulo the impact of Missing
15006 * Sub-components (§5.3)."
15007 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015008 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015009 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015010 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015011 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015012 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015013
Daniel Veillard01fa6152004-06-29 17:04:39 +000015014 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015015 if (! WXS_IS_SIMPLE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015016 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015017 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015018 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015019 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015020 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015021 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015022 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15023 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015024 if ( (WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015025 (WXS_IS_RESTRICTION(type) == 0) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015026 (! WXS_IS_ANY_SIMPLE_TYPE(baseType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015027 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015028 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015029 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015030 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015031 "the simple ur-type definition as base type, not '%s'",
15032 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015033 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015034 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15035 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015036 /*
15037 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015038 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015039 if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15040 (! WXS_IS_LIST(type))) {
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 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015045 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15046 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015047 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015048
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015049 /*
15050 * 3 The {final} of the {base type definition} must not contain restriction.
15051 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015052 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015053 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15054 xmlSchemaPCustomErr(ctxt,
15055 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015056 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015057 "The 'final' of its base type '%s' must not contain "
15058 "'restriction'",
15059 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015060 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015061 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015062 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015063
15064 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015065 * 2 All simple type definitions must be derived ultimately from the ·simple
15066 * ur-type definition (so· circular definitions are disallowed). That is, it
15067 * must be possible to reach a built-in primitive datatype or the ·simple
15068 * ur-type definition· by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015069 *
15070 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000015071 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015072 return (0);
15073}
15074
15075/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015076 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000015077 * @ctxt: the schema parser context
15078 * @type: the simple type definition
15079 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015080 * Schema Component Constraint:
15081 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15082
15083 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015084 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000015085 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015086 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015087 * a positive error code otherwise.
15088 */
15089static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015090xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015091 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015092{
Daniel Veillardc0826a72004-08-10 14:17:33 +000015093 xmlChar *str = NULL;
15094
Daniel Veillard01fa6152004-06-29 17:04:39 +000015095 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015096 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15097 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015098 return (-1);
15099 }
15100
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015101 if (WXS_IS_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015102 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015103 /*
15104 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000015105 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015106 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015107 if (! WXS_IS_ATOMIC(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015108 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015109 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015110 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015111 "The base type '%s' is not an atomic simple type",
15112 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015113 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015114 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15115 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015116 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000015117 * restriction.
15118 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015119 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015120 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015121 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
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_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015124 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015125 "The final of its base type '%s' must not contain 'restriction'",
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_2);
15129 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015130
15131 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000015132 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015133 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000015134 * Primitive datatypes.
15135 */
15136 if (type->facets != NULL) {
15137 xmlSchemaFacetPtr facet;
15138 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015139
Daniel Veillard01fa6152004-06-29 17:04:39 +000015140 primitive = xmlSchemaGetPrimitiveType(type);
15141 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015142 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15143 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015144 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015145 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015146 facet = type->facets;
15147 do {
15148 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015149 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015150 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015151 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015152 type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015153 }
15154 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015155 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015156 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015157 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015158 }
15159 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015160 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15161 * of the {base type definition} (call this BF),then the DF's {value}
15162 * must be a valid restriction of BF's {value} as defined in
15163 * [XML Schemas: Datatypes]."
15164 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015165 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015166 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015167 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015168 } else if (WXS_IS_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015169 xmlSchemaTypePtr itemType = NULL;
15170
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015171 itemType = type->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015172 if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015173 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15174 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015175 return (-1);
15176 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015177 if (WXS_IS_TYPE_NOT_FIXED(itemType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015178 xmlSchemaTypeFixup(itemType, pctxt);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015179 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015180 * 2.1 The {item type definition} must have a {variety} of atomic or
15181 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000015182 * must be atomic).
15183 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015184 if ((! WXS_IS_ATOMIC(itemType)) &&
15185 (! WXS_IS_UNION(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015186 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015187 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015188 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015189 "The item type '%s' does not have a variety of atomic or union",
15190 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015191 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015192 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015193 } else if (WXS_IS_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015194 xmlSchemaTypeLinkPtr member;
15195
15196 member = itemType->memberTypes;
15197 while (member != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015198 if (! WXS_IS_ATOMIC(member->type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015199 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015200 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015201 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015202 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015203 "member type '%s' of this item type is not atomic",
15204 xmlSchemaGetComponentQName(&str, member->type));
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);
15207 }
15208 member = member->next;
15209 }
15210 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015211
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015212 if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015213 xmlSchemaFacetPtr facet;
15214 /*
15215 * This is the case if we have: <simpleType><list ..
15216 */
15217 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015218 * 2.3.1
15219 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000015220 * contain list.
15221 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015222 if (xmlSchemaTypeFinalContains(itemType,
15223 XML_SCHEMAS_TYPE_FINAL_LIST)) {
15224 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015225 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015226 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015227 "The final of its item type '%s' must not contain 'list'",
15228 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015229 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015230 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15231 }
15232 /*
15233 * 2.3.1.2 The {facets} must only contain the whiteSpace
15234 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015235 * OPTIMIZE TODO: the S4S already disallows any facet
15236 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015237 */
15238 if (type->facets != NULL) {
15239 facet = type->facets;
15240 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015241 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015242 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015243 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015244 type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015245 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15246 }
15247 facet = facet->next;
15248 } while (facet != NULL);
15249 }
15250 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015251 * MAYBE TODO: (Hmm, not really) Datatypes states:
15252 * A ·list· datatype can be ·derived· from an ·atomic· datatype
15253 * whose ·lexical space· allows space (such as string or anyURI)or
15254 * a ·union· datatype any of whose {member type definitions}'s
Daniel Veillard01fa6152004-06-29 17:04:39 +000015255 * ·lexical space· allows space.
15256 */
15257 } else {
15258 /*
15259 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015260 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015261 */
15262 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015263 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000015264 * 2.3.2.1 The {base type definition} must have a {variety} of list.
15265 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015266 if (! WXS_IS_LIST(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015267 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015268 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015269 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015270 "The base type '%s' must be a list type",
15271 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015272 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015273 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15274 }
15275 /*
15276 * 2.3.2.2 The {final} of the {base type definition} must not
15277 * contain restriction.
15278 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015279 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015280 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
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_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015283 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015284 "The 'final' of the base type '%s' must not contain 'restriction'",
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_2);
15288 }
15289 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015290 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000015291 * from the {base type definition}'s {item type definition} given
15292 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
15293 */
15294 {
15295 xmlSchemaTypePtr baseItemType;
15296
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015297 baseItemType = type->baseType->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015298 if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015299 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15300 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015301 return (-1);
15302 }
15303 if ((itemType != baseItemType) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015304 (xmlSchemaCheckCOSSTDerivedOK(pctxt, itemType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015305 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015306 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015307 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015308 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015309 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015310 "The item type '%s' is not validly derived from "
15311 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015312 xmlSchemaGetComponentQName(&str, itemType),
15313 xmlSchemaGetComponentQName(&strBIT, baseItemType),
15314 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015315
15316 FREE_AND_NULL(str)
15317 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015318 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015319 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15320 }
15321 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015322
Daniel Veillard01fa6152004-06-29 17:04:39 +000015323 if (type->facets != NULL) {
15324 xmlSchemaFacetPtr facet;
15325 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015326 /*
15327 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000015328 * and enumeration facet components are allowed among the {facets}.
15329 */
15330 facet = type->facets;
15331 do {
15332 switch (facet->type) {
15333 case XML_SCHEMA_FACET_LENGTH:
15334 case XML_SCHEMA_FACET_MINLENGTH:
15335 case XML_SCHEMA_FACET_MAXLENGTH:
15336 case XML_SCHEMA_FACET_WHITESPACE:
15337 /*
15338 * TODO: 2.5.1.2 List datatypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015339 * The value of ·whiteSpace· is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015340 */
15341 case XML_SCHEMA_FACET_PATTERN:
15342 case XML_SCHEMA_FACET_ENUMERATION:
15343 break;
15344 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015345 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015346 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015347 type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015348 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015349 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000015350 * invalid facets.
15351 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015352 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015353 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015354 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015355 facet = facet->next;
15356 } while (facet != NULL);
15357 if (ok == 0)
15358 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15359 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015360 * SPEC (2.3.2.5) (same as 1.3.2)
15361 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015362 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015363 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015364 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015365 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015366 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015367 } else if (WXS_IS_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015368 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015369 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000015370 * atomic or list.
15371 */
15372 xmlSchemaTypeLinkPtr member;
15373
15374 member = type->memberTypes;
15375 while (member != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015376 if (WXS_IS_TYPE_NOT_FIXED(member->type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015377 xmlSchemaTypeFixup(member->type, pctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015378
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015379 if ((! WXS_IS_ATOMIC(member->type)) &&
15380 (! WXS_IS_LIST(member->type))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015381 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015382 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015383 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015384 "The member type '%s' is neither an atomic, nor a list type",
15385 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015386 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015387 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15388 }
15389 member = member->next;
15390 }
15391 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015392 * 3.3.1 If the {base type definition} is the ·simple ur-type
15393 * definition·
Daniel Veillard01fa6152004-06-29 17:04:39 +000015394 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015395 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015396 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015397 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000015398 * {final} which does not contain union.
15399 */
15400 member = type->memberTypes;
15401 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015402 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015403 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015404 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015405 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015406 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015407 "The 'final' of member type '%s' contains 'union'",
15408 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015409 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015410 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15411 }
15412 member = member->next;
15413 }
15414 /*
15415 * 3.3.1.2 The {facets} must be empty.
15416 */
15417 if (type->facetSet != NULL) {
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_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015420 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015421 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015422 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15423 }
15424 } else {
15425 /*
15426 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015427 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015428 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015429 if (! WXS_IS_UNION(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015430 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015431 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015432 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015433 "The base type '%s' is not a union type",
15434 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015435 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015436 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15437 }
15438 /*
15439 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15440 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015441 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015442 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015443 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015444 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015445 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015446 "The 'final' of its base type '%s' must not contain 'restriction'",
15447 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015448 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015449 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15450 }
15451 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015452 * 3.3.2.3 The {member type definitions}, in order, must be validly
15453 * derived from the corresponding type definitions in the {base
15454 * type definition}'s {member type definitions} given the empty set,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015455 * as defined in Type Derivation OK (Simple) (§3.14.6).
15456 */
15457 {
15458 xmlSchemaTypeLinkPtr baseMember;
15459
15460 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015461 * OPTIMIZE: if the type is restricting, it has no local defined
15462 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015463 * thus a check for equality can be skipped.
15464 */
15465 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015466 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015467 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000015468 * types of it's base type. This check seems not necessary with
15469 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015470 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015471 */
15472 if (type->memberTypes != NULL) {
15473 member = type->memberTypes;
15474 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015475 if ((member == NULL) && (baseMember != NULL)) {
15476 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15477 "different number of member types in base");
15478 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015479 while (member != NULL) {
15480 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015481 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15482 "different number of member types in base");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015483 }
15484 if ((member->type != baseMember->type) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015485 (xmlSchemaCheckCOSSTDerivedOK(pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015486 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015487 xmlChar *strBMT = NULL, *strBT = NULL;
15488
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015489 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015490 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015491 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015492 "The member type %s is not validly "
15493 "derived from its corresponding member "
15494 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015495 xmlSchemaGetComponentQName(&str, member->type),
15496 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15497 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015498 FREE_AND_NULL(str)
15499 FREE_AND_NULL(strBMT)
15500 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015501 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015502 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015503 member = member->next;
15504 baseMember = baseMember->next;
15505 }
15506 }
15507 }
15508 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015509 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000015510 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015511 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015512 if (type->facets != NULL) {
15513 xmlSchemaFacetPtr facet;
15514 int ok = 1;
15515
15516 facet = type->facets;
15517 do {
15518 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15519 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015520 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015521 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015522 type, facet);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015523 ok = 0;
15524 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015525 facet = facet->next;
15526 } while (facet != NULL);
15527 if (ok == 0)
15528 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015529
Daniel Veillard01fa6152004-06-29 17:04:39 +000015530 }
15531 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015532 * SPEC (3.3.2.5) (same as 1.3.2)
15533 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015534 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015535 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015536 */
15537 }
15538 }
15539
15540 return (0);
15541}
15542
15543/**
15544 * xmlSchemaCheckSRCSimpleType:
15545 * @ctxt: the schema parser context
15546 * @type: the simple type definition
15547 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015548 * Checks crc-simple-type constraints.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015549 *
15550 * Returns 0 if the constraints are satisfied,
15551 * if not a positive error code and -1 on internal
15552 * errors.
15553 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015554#if 0
Daniel Veillard01fa6152004-06-29 17:04:39 +000015555static int
15556xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15557 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015558{
15559 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000015560 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015561 * must satisfy the conditions set out in Constraints on Simple Type
15562 * Definition Schema Components (§3.14.6).
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015563 */
15564 if (WXS_IS_RESTRICTION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015565 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015566 * src-simple-type.2 "If the <restriction> alternative is chosen,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015567 * either it must have a base [attribute] or a <simpleType> among its
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015568 * [children], but not both."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015569 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015570 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015571 /*
15572 *
15573 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015574 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015575 /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015576 * an itemType [attribute] or a <simpleType> among its [children],
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015577 * but not both."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015578 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015579 * NOTE: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015580 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015581 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015582 /*
15583 * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015584 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015585 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015586 return (0);
15587}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015588#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000015589
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015590static int
15591xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15592{
15593 if (ctxt->vctxt == NULL) {
15594 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15595 if (ctxt->vctxt == NULL) {
15596 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015597 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015598 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015599 "failed to create a temp. validation context.\n",
15600 NULL, NULL);
15601 return (-1);
15602 }
15603 /* TODO: Pass user data. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015604 xmlSchemaSetValidErrors(ctxt->vctxt,
15605 ctxt->error, ctxt->warning, ctxt->userData);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015606 }
15607 return (0);
15608}
15609
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015610static int
15611xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15612 xmlNodePtr node,
15613 xmlSchemaTypePtr type,
15614 const xmlChar *value,
15615 xmlSchemaValPtr *retVal,
15616 int fireErrors,
15617 int normalize,
15618 int isNormalized);
15619
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015620/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015621 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015622 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015623 * @type: the simple type definition
15624 * @value: the default value
15625 * @node: an optional node (the holder of the value)
15626 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015627 * Schema Component Constraint: Element Default Valid (Immediate)
15628 * (cos-valid-default)
15629 * This will be used by the parser only. For the validator there's
15630 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015631 *
15632 * Returns 0 if the constraints are satisfied,
15633 * if not, a positive error code and -1 on internal
15634 * errors.
15635 */
15636static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015637xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15638 xmlNodePtr node,
15639 xmlSchemaTypePtr type,
15640 const xmlChar *value,
15641 xmlSchemaValPtr *val)
15642{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015643 int ret = 0;
15644
15645 /*
15646 * cos-valid-default:
15647 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015648 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015649 * definition the appropriate case among the following must be true:
15650 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015651 if WXS_IS_COMPLEX(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015652 /*
15653 * Complex type.
15654 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015655 * SPEC (2.1) "its {content type} must be a simple type definition
15656 * or mixed."
15657 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015658 * type}'s particle must be ·emptiable· as defined by
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015659 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000015660 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015661 if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15662 ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015663 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015664 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015665 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015666 WXS_BASIC_CAST type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015667 "For a string to be a valid default, the type definition "
15668 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015669 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015670 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15671 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015672 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015673 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015674 * 1 If the type definition is a simple type definition, then the string
15675 * must be ·valid· with respect to that definition as defined by String
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015676 * Valid (§3.14.4).
15677 *
15678 * AND
15679 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015680 * 2.2.1 If the {content type} is a simple type definition, then the
15681 * string must be ·valid· with respect to that simple type definition
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015682 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015683 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015684 if (WXS_IS_SIMPLE(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015685 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015686 type, value, val, 1, 1, 0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015687 else if (WXS_HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015688 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015689 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015690 else
15691 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015692
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015693 if (ret < 0) {
15694 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15695 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015696 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015697
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015698 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000015699}
15700
15701/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015702 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000015703 * @ctxt: the schema parser context
15704 * @type: the complex type definition
15705 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015706 *.(4.6) Constraints on Complex Type Definition Schema Components
15707 * Schema Component Constraint:
15708 * Complex Type Definition Properties Correct (ct-props-correct)
15709 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000015710 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015711 * Returns 0 if the constraints are satisfied, a positive
15712 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000015713 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015714static int
15715xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15716 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000015717{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015718 /*
15719 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15720 *
15721 * SPEC (1) "The values of the properties of a complex type definition must
15722 * be as described in the property tableau in The Complex Type Definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015723 * Schema Component (§3.4.1), modulo the impact of Missing
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015724 * Sub-components (§5.3)."
15725 */
15726 if ((type->baseType != NULL) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015727 (WXS_IS_SIMPLE(type->baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015728 (WXS_IS_EXTENSION(type) == 0)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015729 /*
15730 * SPEC (2) "If the {base type definition} is a simple type definition,
15731 * the {derivation method} must be extension."
15732 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015733 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015734 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015735 NULL, WXS_BASIC_CAST type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015736 "If the base type is a simple type, the derivation method must be "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015737 "'extension'", NULL, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015738 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015739 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015740 /*
15741 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
15742 * definition·. That is, it must be possible to reach the ·ur-type
15743 * definition by repeatedly following the {base type definition}."
15744 *
15745 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015746 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015747 /*
15748 * NOTE that (4) and (5) need the following:
15749 * - attribute uses need to be already inherited (apply attr. prohibitions)
15750 * - attribute group references need to be expanded already
15751 * - simple types need to be typefixed already
15752 */
15753 if (type->attrUses &&
15754 (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15755 {
15756 xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15757 xmlSchemaAttributeUsePtr use, tmp;
15758 int i, j, hasId = 0;
15759
15760 for (i = uses->nbItems -1; i >= 0; i--) {
15761 use = uses->items[i];
15762
15763 /*
15764 * SPEC ct-props-correct
15765 * (4) "Two distinct attribute declarations in the
15766 * {attribute uses} must not have identical {name}s and
15767 * {target namespace}s."
15768 */
15769 if (i > 0) {
15770 for (j = i -1; j >= 0; j--) {
15771 tmp = uses->items[j];
15772 if ((WXS_ATTRUSE_DECL_NAME(use) ==
15773 WXS_ATTRUSE_DECL_NAME(tmp)) &&
15774 (WXS_ATTRUSE_DECL_TNS(use) ==
15775 WXS_ATTRUSE_DECL_TNS(tmp)))
15776 {
15777 xmlChar *str = NULL;
15778
15779 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15780 XML_SCHEMAP_AG_PROPS_CORRECT,
15781 NULL, WXS_BASIC_CAST type,
15782 "Duplicate %s",
15783 xmlSchemaGetComponentDesignation(&str, use),
15784 NULL);
15785 FREE_AND_NULL(str);
15786 /*
15787 * Remove the duplicate.
15788 */
15789 if (xmlSchemaItemListRemove(uses, i) == -1)
15790 goto exit_failure;
15791 goto next_use;
15792 }
15793 }
15794 }
15795 /*
15796 * SPEC ct-props-correct
15797 * (5) "Two distinct attribute declarations in the
15798 * {attribute uses} must not have {type definition}s which
15799 * are or are derived from ID."
15800 */
15801 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15802 if (xmlSchemaIsDerivedFromBuiltInType(
15803 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15804 {
15805 if (hasId) {
15806 xmlChar *str = NULL;
15807
15808 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15809 XML_SCHEMAP_AG_PROPS_CORRECT,
15810 NULL, WXS_BASIC_CAST type,
15811 "There must not exist more than one attribute "
15812 "declaration of type 'xs:ID' "
15813 "(or derived from 'xs:ID'). The %s violates this "
15814 "constraint",
15815 xmlSchemaGetComponentDesignation(&str, use),
15816 NULL);
15817 FREE_AND_NULL(str);
15818 if (xmlSchemaItemListRemove(uses, i) == -1)
15819 goto exit_failure;
15820 }
15821
15822 hasId = 1;
15823 }
15824 }
15825next_use: {}
15826 }
15827 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015828 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015829exit_failure:
15830 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +000015831}
15832
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015833static int
15834xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
15835 xmlSchemaTypePtr typeB)
15836{
15837 /*
15838 * TODO: This should implement component-identity
15839 * in the future.
15840 */
15841 if ((typeA == NULL) || (typeB == NULL))
15842 return (0);
15843 return (typeA == typeB);
15844}
15845
15846/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015847 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015848 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015849 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015850 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015851 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015852 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015853 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015854 * Type Derivation OK (Complex) (cos-ct-derived-ok)
15855 *
15856 * STATUS: completed
15857 *
15858 * Returns 0 if the constraints are satisfied, or 1
15859 * if not.
15860 */
15861static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015862xmlSchemaCheckCOSCTDerivedOK(xmlSchemaParserCtxtPtr ctxt,
15863 xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015864 xmlSchemaTypePtr baseType,
15865 int set)
15866{
15867 int equal = xmlSchemaAreEqualTypes(type, baseType);
15868 /* TODO: Error codes. */
15869 /*
15870 * SPEC "For a complex type definition (call it D, for derived)
15871 * to be validly derived from a type definition (call this
15872 * B, for base) given a subset of {extension, restriction}
15873 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015874 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015875 if (! equal) {
15876 /*
15877 * SPEC (1) "If B and D are not the same type definition, then the
15878 * {derivation method} of D must not be in the subset."
15879 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015880 if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
15881 ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015882 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015883 } else {
15884 /*
15885 * SPEC (2.1) "B and D must be the same type definition."
15886 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015887 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015888 }
15889 /*
15890 * SPEC (2.2) "B must be D's {base type definition}."
15891 */
15892 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015893 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015894 /*
15895 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
15896 * definition·."
15897 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015898 if (WXS_IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015899 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015900
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015901 if (WXS_IS_COMPLEX(type->baseType)) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015902 /*
15903 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
15904 * must be validly derived from B given the subset as defined by this
15905 * constraint."
15906 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015907 return (xmlSchemaCheckCOSCTDerivedOK(ctxt, type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015908 baseType, set));
15909 } else {
15910 /*
15911 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
15912 * must be validly derived from B given the subset as defined in Type
15913 * Derivation OK (Simple) (§3.14.6).
15914 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015915 return (xmlSchemaCheckCOSSTDerivedOK(ctxt, type->baseType,
15916 baseType, set));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015917 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015918}
15919
15920/**
15921 * xmlSchemaCheckCOSDerivedOK:
15922 * @type: the derived simple type definition
15923 * @baseType: the base type definition
15924 *
15925 * Calls:
15926 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015927 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015928 * Checks wheter @type can be validly derived from @baseType.
15929 *
15930 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015931 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015932static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015933xmlSchemaCheckCOSDerivedOK(xmlSchemaParserCtxtPtr ctxt,
15934 xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015935 xmlSchemaTypePtr baseType,
15936 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015937{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015938 if (WXS_IS_SIMPLE(type))
15939 return (xmlSchemaCheckCOSSTDerivedOK(ctxt, type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015940 else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015941 return (xmlSchemaCheckCOSCTDerivedOK(ctxt, type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015942}
15943
William M. Brack2f2a6632004-08-20 23:09:47 +000015944/**
15945 * xmlSchemaCheckCOSCTExtends:
15946 * @ctxt: the schema parser context
15947 * @type: the complex type definition
15948 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015949 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015950 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015951 * Derivation Valid (Extension) (cos-ct-extends)
15952 *
15953 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015954 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015955 * (1.5)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015956 * (1.4.3.2.2.2) "Particle Valid (Extension)"
William M. Brack2f2a6632004-08-20 23:09:47 +000015957 *
15958 * Returns 0 if the constraints are satisfied, a positive
15959 * error code if not and -1 if an internal error occured.
15960 */
15961static int
15962xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
15963 xmlSchemaTypePtr type)
15964{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015965 xmlSchemaTypePtr base = type->baseType;
15966 /*
15967 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
15968 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000015969 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015970 /*
15971 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015972 * then all of the following must be true:"
15973 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015974 if (WXS_IS_COMPLEX(base)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015975 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015976 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015977 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000015978 */
15979 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
15980 xmlSchemaPCustomErr(ctxt,
15981 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015982 WXS_BASIC_CAST type, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000015983 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015984 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000015985 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
15986 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015987
15988 /*
15989 * ATTENTION: The constrains (1.2) and (1.3) are not applied,
15990 * since they are automatically satisfied through the
15991 * inheriting mechanism.
15992 * Note that even if redefining components, the inheriting mechanism
15993 * is used.
15994 */
15995#if 0
William M. Brack2f2a6632004-08-20 23:09:47 +000015996 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015997 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015998 * uses}
15999 * of the complex type definition itself, that is, for every attribute
16000 * use in the {attribute uses} of the {base type definition}, there
16001 * must be an attribute use in the {attribute uses} of the complex
16002 * type definition itself whose {attribute declaration} has the same
16003 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016004 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000016005 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016006 if (base->attrUses != NULL) {
16007 int i, j, found;
16008 xmlSchemaAttributeUsePtr use, buse;
William M. Brack2f2a6632004-08-20 23:09:47 +000016009
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016010 for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16011 buse = (WXS_LIST_CAST base->attrUses)->items[i];
16012 found = 0;
16013 if (type->attrUses != NULL) {
16014 use = (WXS_LIST_CAST type->attrUses)->items[j];
16015 for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16016 {
16017 if ((WXS_ATTRUSE_DECL_NAME(use) ==
16018 WXS_ATTRUSE_DECL_NAME(buse)) &&
16019 (WXS_ATTRUSE_DECL_TNS(use) ==
16020 WXS_ATTRUSE_DECL_TNS(buse)) &&
16021 (WXS_ATTRUSE_TYPEDEF(use) ==
16022 WXS_ATTRUSE_TYPEDEF(buse))
16023 {
16024 found = 1;
16025 break;
16026 }
16027 }
16028 }
16029 if (! found) {
16030 xmlChar *str = NULL;
16031
16032 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16033 XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16034 NULL, WXS_BASIC_CAST type,
16035 /*
16036 * TODO: The report does not indicate that also the
16037 * type needs to be the same.
16038 */
16039 "This type is missing a matching correspondent "
16040 "for its {base type}'s %s in its {attribute uses}",
16041 xmlSchemaGetComponentDesignation(&str,
16042 buse->children),
16043 NULL);
16044 FREE_AND_NULL(str)
16045 }
16046 }
16047 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016048 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016049 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16050 * definition must also have one, and the base type definition's
16051 * {attribute wildcard}'s {namespace constraint} must be a subset
16052 * of the complex type definition's {attribute wildcard}'s {namespace
16053 * constraint}, as defined by Wildcard Subset (§3.10.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016054 */
16055
16056 /*
16057 * MAYBE TODO: Enable if ever needed. But this will be needed only
16058 * if created the type via a schema construction API.
16059 */
16060 if (base->attributeWildcard != NULL) {
16061 if (type->attributeWilcard == NULL) {
16062 xmlChar *str = NULL;
16063
16064 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16065 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16066 NULL, type,
16067 "The base %s has an attribute wildcard, "
16068 "but this type is missing an attribute wildcard",
16069 xmlSchemaGetComponentDesignation(&str, base));
16070 FREE_AND_NULL(str)
16071
16072 } else if (xmlSchemaCheckCOSNSSubset(
16073 base->attributeWildcard, type->attributeWildcard))
16074 {
16075 xmlChar *str = NULL;
16076
16077 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16078 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16079 NULL, type,
16080 "The attribute wildcard is not a valid "
16081 "superset of the one in the base %s",
16082 xmlSchemaGetComponentDesignation(&str, base));
16083 FREE_AND_NULL(str)
16084 }
16085 }
16086#endif
16087 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016088 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000016089 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016090 if ((type->contentTypeDef != NULL) &&
16091 (type->contentTypeDef == base->contentTypeDef)) {
16092 /*
16093 * SPEC (1.4.1) "The {content type} of the {base type definition}
16094 * and the {content type} of the complex type definition itself
16095 * must be the same simple type definition"
16096 * PASS
16097 */
16098 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16099 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16100 /*
16101 * SPEC (1.4.2) "The {content type} of both the {base type
16102 * definition} and the complex type definition itself must
16103 * be empty."
16104 * PASS
16105 */
16106 } else {
16107 /*
16108 * SPEC (1.4.3) "All of the following must be true:"
16109 */
16110 if (type->subtypes == NULL) {
16111 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016112 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016113 * definition itself must specify a particle.
16114 */
16115 xmlSchemaPCustomErr(ctxt,
16116 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016117 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016118 "The content type must specify a particle", NULL);
16119 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16120 }
16121 /*
16122 * SPEC (1.4.3.2) "One of the following must be true:"
16123 */
16124 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16125 /*
16126 * SPEC (1.4.3.2.1) "The {content type} of the {base type
16127 * definition} must be empty.
16128 * PASS
16129 */
16130 } else {
16131 /*
16132 * SPEC (1.4.3.2.2) "All of the following must be true:"
16133 */
16134 if ((type->contentType != base->contentType) ||
16135 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16136 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16137 /*
16138 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16139 * or both must be element-only."
16140 */
16141 xmlSchemaPCustomErr(ctxt,
16142 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016143 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016144 "The content type of both, the type and its base "
16145 "type, must either 'mixed' or 'element-only'", NULL);
16146 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016147 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016148 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016149 * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016150 * complex type definition must be a ·valid extension·
16151 * of the {base type definition}'s particle, as defined
16152 * in Particle Valid (Extension) (§3.9.6)."
16153 *
16154 * NOTE that we won't check "Particle Valid (Extension)",
16155 * since it is ensured by the derivation process in
16156 * xmlSchemaTypeFixup(). We need to implement this when heading
16157 * for a construction API
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016158 * TODO: !! This is needed to be checked if redefining a type !!
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016159 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016160 }
16161 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016162 * URGENT TODO (1.5)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016163 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016164 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016165 } else {
16166 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016167 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016168 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000016169 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016170 if (type->contentTypeDef != base) {
16171 /*
16172 * SPEC (2.1) "The {content type} must be the same simple type
16173 * definition."
16174 */
16175 xmlSchemaPCustomErr(ctxt,
16176 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016177 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016178 "The content type must be the simple base type", NULL);
16179 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16180 }
16181 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16182 /*
16183 * SPEC (2.2) "The {final} of the {base type definition} must not
16184 * contain extension"
16185 * NOTE that this is the same as (1.1).
16186 */
16187 xmlSchemaPCustomErr(ctxt,
16188 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016189 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016190 "The 'final' of the base type definition "
16191 "contains 'extension'", NULL);
16192 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016193 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016194 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016195 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016196}
16197
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016198/**
16199 * xmlSchemaCheckDerivationOKRestriction:
16200 * @ctxt: the schema parser context
16201 * @type: the complex type definition
16202 *
16203 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016204 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016205 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16206 *
16207 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016208 * missing:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016209 * (5.4.2) ???
16210 *
16211 * ATTENTION:
16212 * In XML Schema 1.1 this will be:
16213 * Validation Rule: Checking complex type subsumption
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016214 *
16215 * Returns 0 if the constraints are satisfied, a positive
16216 * error code if not and -1 if an internal error occured.
16217 */
16218static int
16219xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16220 xmlSchemaTypePtr type)
16221{
16222 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016223
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016224 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016225 * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016226 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016227 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016228 base = type->baseType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016229 if (! WXS_IS_COMPLEX(base)) {
16230 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16231 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16232 type->node, WXS_BASIC_CAST type,
16233 "The base type must be a complex type", NULL, NULL);
16234 return(ctxt->err);
16235 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016236 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16237 /*
16238 * SPEC (1) "The {base type definition} must be a complex type
16239 * definition whose {final} does not contain restriction."
16240 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016241 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16242 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16243 type->node, WXS_BASIC_CAST type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016244 "The 'final' of the base type definition "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016245 "contains 'restriction'", NULL, NULL);
16246 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016247 }
16248 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016249 * SPEC (2), (3) and (4)
16250 * Those are handled in a separate function, since the
16251 * same constraints are needed for redefinition of
16252 * attribute groups as well.
16253 */
16254 if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16255 XML_SCHEMA_ACTION_DERIVE,
16256 WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16257 type->attrUses, base->attrUses,
16258 type->attributeWildcard,
16259 base->attributeWildcard) == -1)
16260 {
16261 return(-1);
16262 }
16263 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016264 * SPEC (5) "One of the following must be true:"
16265 */
16266 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16267 /*
16268 * SPEC (5.1) "The {base type definition} must be the
16269 * ·ur-type definition·."
16270 * PASS
16271 */
16272 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16273 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16274 /*
16275 * SPEC (5.2.1) "The {content type} of the complex type definition
16276 * must be a simple type definition"
16277 *
16278 * SPEC (5.2.2) "One of the following must be true:"
16279 */
16280 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016281 (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16282 {
16283 int err;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016284 /*
16285 * SPEC (5.2.2.1) "The {content type} of the {base type
16286 * definition} must be a simple type definition from which
16287 * the {content type} is validly derived given the empty
16288 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016289 *
16290 * ATTENTION TODO: This seems not needed if the type implicitely
16291 * derived from the base type.
16292 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016293 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016294 err = xmlSchemaCheckCOSSTDerivedOK(ctxt, type->contentTypeDef,
16295 base->contentTypeDef, 0);
16296 if (err != 0) {
16297 xmlChar *strA = NULL, *strB = NULL;
16298
16299 if (err == -1)
16300 return(-1);
16301 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16302 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16303 NULL, WXS_BASIC_CAST type,
16304 "The {content type} %s is not validly derived from the "
16305 "base type's {content type} %s",
16306 xmlSchemaGetComponentDesignation(&strA,
16307 type->contentTypeDef),
16308 xmlSchemaGetComponentDesignation(&strB,
16309 base->contentTypeDef));
16310 FREE_AND_NULL(strA);
16311 FREE_AND_NULL(strB);
16312 return(ctxt->err);
16313 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016314 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16315 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016316 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016317 /*
16318 * SPEC (5.2.2.2) "The {base type definition} must be mixed
16319 * and have a particle which is ·emptiable· as defined in
16320 * Particle Emptiable (§3.9.6)."
16321 * PASS
16322 */
16323 } else {
16324 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016325 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16326 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016327 "The content type of the base type must be either "
16328 "a simple type or 'mixed' and an emptiable particle", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016329 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016330 }
16331 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16332 /*
16333 * SPEC (5.3.1) "The {content type} of the complex type itself must
16334 * be empty"
16335 */
16336 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16337 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016338 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016339 * definition} must also be empty."
16340 * PASS
16341 */
16342 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16343 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16344 xmlSchemaIsParticleEmptiable(
16345 (xmlSchemaParticlePtr) base->subtypes)) {
16346 /*
16347 * SPEC (5.3.2.2) "The {content type} of the {base type
16348 * definition} must be elementOnly or mixed and have a particle
16349 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
16350 * PASS
16351 */
16352 } else {
16353 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016354 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16355 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016356 "The content type of the base type must be either "
16357 "empty or 'mixed' (or 'elements-only') and an emptiable "
16358 "particle", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016359 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016360 }
16361 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016362 WXS_HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016363 /*
16364 * SPEC (5.4.1.1) "The {content type} of the complex type definition
16365 * itself must be element-only"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016366 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016367 if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016368 /*
16369 * SPEC (5.4.1.2) "The {content type} of the complex type
16370 * definition itself and of the {base type definition} must be
16371 * mixed"
16372 */
16373 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016374 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16375 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016376 "If the content type is 'mixed', then the content type of the "
16377 "base type must also be 'mixed'", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016378 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016379 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016380 /*
16381 * SPEC (5.4.2) "The particle of the complex type definition itself
16382 * must be a ·valid restriction· of the particle of the {content
16383 * type} of the {base type definition} as defined in Particle Valid
16384 * (Restriction) (§3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016385 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016386 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016387 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016388 } else {
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. Buchcikaba15f72005-04-01 15:17:27 +000016392 "The type is not a valid restriction of its base type", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016393 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016394 }
16395 return (0);
16396}
16397
16398/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016399 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016400 * @ctxt: the schema parser context
16401 * @type: the complex type definition
16402 *
16403 * (3.4.6) Constraints on Complex Type Definition Schema Components
16404 *
16405 * Returns 0 if the constraints are satisfied, a positive
16406 * error code if not and -1 if an internal error occured.
16407 */
16408static int
16409xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16410 xmlSchemaTypePtr type)
16411{
16412 int ret;
16413 /*
16414 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016415 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016416 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16417 if (ret != 0)
16418 return (ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016419 if (WXS_IS_EXTENSION(type))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016420 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16421 else
16422 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16423 return (ret);
16424}
16425
16426/**
16427 * xmlSchemaCheckSRCCT:
16428 * @ctxt: the schema parser context
16429 * @type: the complex type definition
16430 *
16431 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016432 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016433 * Complex Type Definition Representation OK (src-ct)
16434 *
16435 * Returns 0 if the constraints are satisfied, a positive
16436 * error code if not and -1 if an internal error occured.
16437 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016438static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016439xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016440 xmlSchemaTypePtr type)
16441{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016442 xmlSchemaTypePtr base;
16443 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016444
16445 /*
16446 * TODO: Adjust the error codes here, as I used
16447 * XML_SCHEMAP_SRC_CT_1 only yet.
16448 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016449 base = type->baseType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016450 if (! WXS_HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016451 /*
16452 * 1 If the <complexContent> alternative is chosen, the type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016453 * ·resolved· to by the ·actual value· of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016454 * must be a complex type definition;
16455 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016456 if (! WXS_IS_COMPLEX(base)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016457 xmlChar *str = NULL;
16458 xmlSchemaPCustomErr(ctxt,
16459 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016460 WXS_BASIC_CAST type, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016461 "If using <complexContent>, the base type is expected to be "
16462 "a complex type. The base type '%s' is a simple type",
16463 xmlSchemaFormatQName(&str, base->targetNamespace,
16464 base->name));
16465 FREE_AND_NULL(str)
16466 return (XML_SCHEMAP_SRC_CT_1);
16467 }
16468 } else {
16469 /*
16470 * SPEC
16471 * 2 If the <simpleContent> alternative is chosen, all of the
16472 * following must be true:
16473 * 2.1 The type definition ·resolved· to by the ·actual value· of the
16474 * base [attribute] must be one of the following:
16475 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016476 if (WXS_IS_SIMPLE(base)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016477 if (WXS_IS_EXTENSION(type) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016478 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016479 /*
16480 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016481 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016482 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016483 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016484 xmlSchemaPCustomErr(ctxt,
16485 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016486 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016487 "If using <simpleContent> and <restriction>, the base "
16488 "type must be a complex type. The base type '%s' is "
16489 "a simple type",
16490 xmlSchemaFormatQName(&str, base->targetNamespace,
16491 base->name));
16492 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016493 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016494 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016495 } else {
16496 /* Base type is a complex type. */
16497 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16498 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16499 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016500 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016501 * simple type definition;
16502 * PASS
16503 */
16504 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016505 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016506 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016507 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016508 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016509 type->name);
16510 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016511 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016512 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016513 (WXS_IS_RESTRICTION(type))) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016514
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016515 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016516 * 2.1.2 only if the <restriction> alternative is also
16517 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016518 * is mixed and a particle emptiable.
16519 */
16520 if (! xmlSchemaIsParticleEmptiable(
16521 (xmlSchemaParticlePtr) base->subtypes)) {
16522 ret = XML_SCHEMAP_SRC_CT_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016523 } else
16524 /*
16525 * Attention: at this point the <simpleType> child is in
16526 * ->contentTypeDef (put there during parsing).
16527 */
16528 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016529 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016530 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016531 * 2.2 If clause 2.1.2 above is satisfied, then there
16532 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016533 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016534 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016535 /* TODO: Change error code to ..._SRC_CT_2_2. */
16536 xmlSchemaPCustomErr(ctxt,
16537 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016538 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016539 "A <simpleType> is expected among the children "
16540 "of <restriction>, if <simpleContent> is used and "
16541 "the base type '%s' is a complex type",
16542 xmlSchemaFormatQName(&str, base->targetNamespace,
16543 base->name));
16544 FREE_AND_NULL(str)
16545 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016546 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016547 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016548 ret = XML_SCHEMAP_SRC_CT_1;
16549 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016550 }
16551 if (ret > 0) {
16552 xmlChar *str = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016553 if (WXS_IS_RESTRICTION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016554 xmlSchemaPCustomErr(ctxt,
16555 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016556 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016557 "If <simpleContent> and <restriction> is used, the "
16558 "base type must be a simple type or a complex type with "
16559 "mixed content and particle emptiable. The base type "
16560 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016561 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016562 base->name));
16563 } else {
16564 xmlSchemaPCustomErr(ctxt,
16565 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016566 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016567 "If <simpleContent> and <extension> is used, the "
16568 "base type must be a simple type. The base type '%s' "
16569 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016570 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016571 base->name));
16572 }
16573 FREE_AND_NULL(str)
16574 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016575 }
16576 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016577 * SPEC (3) "The corresponding complex type definition component must
16578 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016579 * Definition Schema Components (§3.4.6);"
16580 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016581 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016582 /*
16583 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016584 * above for {attribute wildcard} is satisfied, the intensional
16585 * intersection must be expressible, as defined in Attribute Wildcard
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016586 * Intersection (§3.10.6).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016587 * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016588 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016589 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016590}
William M. Brack2f2a6632004-08-20 23:09:47 +000016591
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016592#ifdef ENABLE_PARTICLE_RESTRICTION
16593/**
16594 * xmlSchemaCheckParticleRangeOK:
16595 * @ctxt: the schema parser context
16596 * @type: the complex type definition
16597 *
16598 * (3.9.6) Constraints on Particle Schema Components
16599 * Schema Component Constraint:
16600 * Occurrence Range OK (range-ok)
16601 *
16602 * STATUS: complete
16603 *
16604 * Returns 0 if the constraints are satisfied, a positive
16605 * error code if not and -1 if an internal error occured.
16606 */
16607static int
16608xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16609 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016610{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016611 if (rmin < bmin)
16612 return (1);
16613 if ((bmax != UNBOUNDED) &&
16614 (rmax > bmax))
16615 return (1);
16616 return (0);
16617}
16618
16619/**
16620 * xmlSchemaCheckRCaseNameAndTypeOK:
16621 * @ctxt: the schema parser context
16622 * @r: the restricting element declaration particle
16623 * @b: the base element declaration particle
16624 *
16625 * (3.9.6) Constraints on Particle Schema Components
16626 * Schema Component Constraint:
16627 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16628 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016629 *
16630 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016631 * MISSING (3.2.3)
16632 * CLARIFY: (3.2.2)
16633 *
16634 * Returns 0 if the constraints are satisfied, a positive
16635 * error code if not and -1 if an internal error occured.
16636 */
16637static int
16638xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16639 xmlSchemaParticlePtr r,
16640 xmlSchemaParticlePtr b)
16641{
16642 xmlSchemaElementPtr elemR, elemB;
16643
16644 /* TODO: Error codes (rcase-NameAndTypeOK). */
16645 elemR = (xmlSchemaElementPtr) r->children;
16646 elemB = (xmlSchemaElementPtr) b->children;
16647 /*
16648 * SPEC (1) "The declarations' {name}s and {target namespace}s are
16649 * the same."
16650 */
16651 if ((elemR != elemB) &&
16652 ((! xmlStrEqual(elemR->name, elemB->name)) ||
16653 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16654 return (1);
16655 /*
16656 * SPEC (2) "R's occurrence range is a valid restriction of B's
16657 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16658 */
16659 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16660 b->minOccurs, b->maxOccurs) != 0)
16661 return (1);
16662 /*
16663 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16664 * {scope} are global."
16665 */
16666 if (elemR == elemB)
16667 return (0);
16668 /*
16669 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16670 */
16671 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16672 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16673 return (1);
16674 /*
16675 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16676 * or is not fixed, or R's declaration's {value constraint} is fixed
16677 * with the same value."
16678 */
16679 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16680 ((elemR->value == NULL) ||
16681 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16682 /* TODO: Equality of the initial value or normalized or canonical? */
16683 (! xmlStrEqual(elemR->value, elemB->value))))
16684 return (1);
16685 /*
16686 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16687 * definitions} is a subset of B's declaration's {identity-constraint
16688 * definitions}, if any."
16689 */
16690 if (elemB->idcs != NULL) {
16691 /* TODO */
16692 }
16693 /*
16694 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16695 * superset of B's declaration's {disallowed substitutions}."
16696 */
16697 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16698 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16699 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16700 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16701 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16702 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16703 return (1);
16704 /*
16705 * SPEC (3.2.5) "R's {type definition} is validly derived given
16706 * {extension, list, union} from B's {type definition}"
16707 *
16708 * BADSPEC TODO: What's the point of adding "list" and "union" to the
16709 * set, if the corresponding constraints handle "restriction" and
16710 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016711 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016712 */
16713 {
16714 int set = 0;
16715
16716 set |= SUBSET_EXTENSION;
16717 set |= SUBSET_LIST;
16718 set |= SUBSET_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016719 if (xmlSchemaCheckCOSDerivedOK(elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016720 elemB->subtypes, set) != 0)
16721 return (1);
16722 }
16723 return (0);
16724}
16725
16726/**
16727 * xmlSchemaCheckRCaseNSCompat:
16728 * @ctxt: the schema parser context
16729 * @r: the restricting element declaration particle
16730 * @b: the base wildcard particle
16731 *
16732 * (3.9.6) Constraints on Particle Schema Components
16733 * Schema Component Constraint:
16734 * Particle Derivation OK (Elt:Any -- NSCompat)
16735 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016736 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016737 * STATUS: complete
16738 *
16739 * Returns 0 if the constraints are satisfied, a positive
16740 * error code if not and -1 if an internal error occured.
16741 */
16742static int
16743xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16744 xmlSchemaParticlePtr r,
16745 xmlSchemaParticlePtr b)
16746{
16747 /* TODO:Error codes (rcase-NSCompat). */
16748 /*
16749 * SPEC "For an element declaration particle to be a ·valid restriction·
16750 * of a wildcard particle all of the following must be true:"
16751 *
16752 * SPEC (1) "The element declaration's {target namespace} is ·valid·
16753 * with respect to the wildcard's {namespace constraint} as defined by
16754 * Wildcard allows Namespace Name (§3.10.4)."
16755 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016756 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016757 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16758 return (1);
16759 /*
16760 * SPEC (2) "R's occurrence range is a valid restriction of B's
16761 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16762 */
16763 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16764 b->minOccurs, b->maxOccurs) != 0)
16765 return (1);
16766
16767 return (0);
16768}
16769
16770/**
16771 * xmlSchemaCheckRCaseRecurseAsIfGroup:
16772 * @ctxt: the schema parser context
16773 * @r: the restricting element declaration particle
16774 * @b: the base model group particle
16775 *
16776 * (3.9.6) Constraints on Particle Schema Components
16777 * Schema Component Constraint:
16778 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16779 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016780 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016781 * STATUS: TODO
16782 *
16783 * Returns 0 if the constraints are satisfied, a positive
16784 * error code if not and -1 if an internal error occured.
16785 */
16786static int
16787xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16788 xmlSchemaParticlePtr r,
16789 xmlSchemaParticlePtr b)
16790{
16791 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16792 TODO
16793 return (0);
16794}
16795
16796/**
16797 * xmlSchemaCheckRCaseNSSubset:
16798 * @ctxt: the schema parser context
16799 * @r: the restricting wildcard particle
16800 * @b: the base wildcard particle
16801 *
16802 * (3.9.6) Constraints on Particle Schema Components
16803 * Schema Component Constraint:
16804 * Particle Derivation OK (Any:Any -- NSSubset)
16805 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016806 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016807 * STATUS: complete
16808 *
16809 * Returns 0 if the constraints are satisfied, a positive
16810 * error code if not and -1 if an internal error occured.
16811 */
16812static int
16813xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16814 xmlSchemaParticlePtr r,
16815 xmlSchemaParticlePtr b,
16816 int isAnyTypeBase)
16817{
16818 /* TODO: Error codes (rcase-NSSubset). */
16819 /*
16820 * SPEC (1) "R's occurrence range is a valid restriction of B's
16821 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16822 */
16823 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16824 b->minOccurs, b->maxOccurs))
16825 return (1);
16826 /*
16827 * SPEC (2) "R's {namespace constraint} must be an intensional subset
16828 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
16829 */
16830 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
16831 (xmlSchemaWildcardPtr) b->children))
16832 return (1);
16833 /*
16834 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
16835 * definition·, R's {process contents} must be identical to or stronger
16836 * than B's {process contents}, where strict is stronger than lax is
16837 * stronger than skip."
16838 */
16839 if (! isAnyTypeBase) {
16840 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
16841 ((xmlSchemaWildcardPtr) b->children)->processContents)
16842 return (1);
16843 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016844
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016845 return (0);
16846}
16847
16848/**
16849 * xmlSchemaCheckCOSParticleRestrict:
16850 * @ctxt: the schema parser context
16851 * @type: the complex type definition
16852 *
16853 * (3.9.6) Constraints on Particle Schema Components
16854 * Schema Component Constraint:
16855 * Particle Valid (Restriction) (cos-particle-restrict)
16856 *
16857 * STATUS: TODO
16858 *
16859 * Returns 0 if the constraints are satisfied, a positive
16860 * error code if not and -1 if an internal error occured.
16861 */
16862static int
16863xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
16864 xmlSchemaParticlePtr r,
16865 xmlSchemaParticlePtr b)
16866{
16867 int ret = 0;
16868
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016869 /*part = WXS_TYPE_PARTICLE(type);
16870 basePart = WXS_TYPE_PARTICLE(base);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016871 */
16872
16873 TODO
16874
16875 /*
16876 * SPEC (1) "They are the same particle."
16877 */
16878 if (r == b)
16879 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016880
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016881
16882 return (0);
16883}
16884
16885/**
16886 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
16887 * @ctxt: the schema parser context
16888 * @r: the model group particle
16889 * @b: the base wildcard particle
16890 *
16891 * (3.9.6) Constraints on Particle Schema Components
16892 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016893 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016894 * NSRecurseCheckCardinality)
16895 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016896 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016897 * STATUS: TODO: subst-groups
16898 *
16899 * Returns 0 if the constraints are satisfied, a positive
16900 * error code if not and -1 if an internal error occured.
16901 */
16902static int
16903xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
16904 xmlSchemaParticlePtr r,
16905 xmlSchemaParticlePtr b)
16906{
16907 xmlSchemaParticlePtr part;
16908 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
16909 if ((r->children == NULL) || (r->children->children == NULL))
16910 return (-1);
16911 /*
16912 * SPEC "For a group particle to be a ·valid restriction· of a
16913 * wildcard particle..."
16914 *
16915 * SPEC (1) "Every member of the {particles} of the group is a ·valid
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016916 * restriction· of the wildcard as defined by
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016917 * Particle Valid (Restriction) (§3.9.6)."
16918 */
16919 part = (xmlSchemaParticlePtr) r->children->children;
16920 do {
16921 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
16922 return (1);
16923 part = (xmlSchemaParticlePtr) part->next;
16924 } while (part != NULL);
16925 /*
16926 * SPEC (2) "The effective total range of the group [...] is a
16927 * valid restriction of B's occurrence range as defined by
16928 * Occurrence Range OK (§3.9.6)."
16929 */
16930 if (xmlSchemaCheckParticleRangeOK(
16931 xmlSchemaGetParticleTotalRangeMin(r),
16932 xmlSchemaGetParticleTotalRangeMax(r),
16933 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016934 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016935 return (0);
16936}
16937
16938/**
16939 * xmlSchemaCheckRCaseRecurse:
16940 * @ctxt: the schema parser context
16941 * @r: the <all> or <sequence> model group particle
16942 * @b: the base <all> or <sequence> model group particle
16943 *
16944 * (3.9.6) Constraints on Particle Schema Components
16945 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016946 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016947 Recurse)
16948 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016949 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016950 * STATUS: ?
16951 * TODO: subst-groups
16952 *
16953 * Returns 0 if the constraints are satisfied, a positive
16954 * error code if not and -1 if an internal error occured.
16955 */
16956static int
16957xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
16958 xmlSchemaParticlePtr r,
16959 xmlSchemaParticlePtr b)
16960{
16961 /* xmlSchemaParticlePtr part; */
16962 /* TODO: Error codes (rcase-Recurse). */
16963 if ((r->children == NULL) || (b->children == NULL) ||
16964 (r->children->type != b->children->type))
16965 return (-1);
16966 /*
16967 * SPEC "For an all or sequence group particle to be a ·valid
16968 * restriction· of another group particle with the same {compositor}..."
16969 *
16970 * SPEC (1) "R's occurrence range is a valid restriction of B's
16971 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16972 */
16973 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16974 b->minOccurs, b->maxOccurs))
16975 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016976
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016977
16978 return (0);
16979}
16980
16981#endif
16982
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016983#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
16984 xmlSchemaPCustomErrExt(pctxt, \
16985 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016986 WXS_BASIC_CAST fac1, fac1->node, \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016987 "It is an error for both '%s' and '%s' to be specified on the "\
16988 "same type definition", \
16989 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
16990 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
16991
16992#define FACET_RESTR_ERR(fac1, msg) \
16993 xmlSchemaPCustomErr(pctxt, \
16994 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016995 WXS_BASIC_CAST fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016996 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016997
16998#define FACET_RESTR_FIXED_ERR(fac) \
16999 xmlSchemaPCustomErr(pctxt, \
17000 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017001 WXS_BASIC_CAST fac, fac->node, \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017002 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017003 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017004
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017005static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017006xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17007 xmlSchemaFacetPtr facet1,
17008 xmlSchemaFacetPtr facet2,
17009 int lessGreater,
17010 int orEqual,
17011 int ofBase)
17012{
17013 xmlChar *msg = NULL;
17014
17015 msg = xmlStrdup(BAD_CAST "'");
17016 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17017 msg = xmlStrcat(msg, BAD_CAST "' has to be");
17018 if (lessGreater == 0)
17019 msg = xmlStrcat(msg, BAD_CAST " equal to");
17020 if (lessGreater == 1)
17021 msg = xmlStrcat(msg, BAD_CAST " greater than");
17022 else
17023 msg = xmlStrcat(msg, BAD_CAST " less than");
17024
17025 if (orEqual)
17026 msg = xmlStrcat(msg, BAD_CAST " or equal to");
17027 msg = xmlStrcat(msg, BAD_CAST " '");
17028 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17029 if (ofBase)
17030 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17031 else
17032 msg = xmlStrcat(msg, BAD_CAST "'");
17033
17034 xmlSchemaPCustomErr(pctxt,
17035 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017036 WXS_BASIC_CAST facet1, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017037 (const char *) msg, NULL);
17038
17039 if (msg != NULL)
17040 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017041}
17042
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017043/*
17044* xmlSchemaDeriveAndValidateFacets:
17045*
17046* Schema Component Constraint: Simple Type Restriction (Facets)
17047* (st-restrict-facets)
17048*/
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017049static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017050xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17051 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017052{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017053 xmlSchemaTypePtr base = type->baseType;
17054 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017055 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017056 flength = NULL, ftotdig = NULL, ffracdig = NULL,
17057 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17058 fmininc = NULL, fmaxinc = NULL,
17059 fminexc = NULL, fmaxexc = NULL,
17060 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17061 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17062 bfmininc = NULL, bfmaxinc = NULL,
17063 bfminexc = NULL, bfmaxexc = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000017064 int res; /* err = 0, fixedErr; */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017065
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017066 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017067 * SPEC st-restrict-facets 1:
17068 * "The {variety} of R is the same as that of B."
17069 */
17070 /*
17071 * SPEC st-restrict-facets 2:
17072 * "If {variety} is atomic, the {primitive type definition}
17073 * of R is the same as that of B."
17074 *
17075 * NOTE: we leave 1 & 2 out for now, since this will be
17076 * satisfied by the derivation process.
17077 * CONSTRUCTION TODO: Maybe needed if using a construction API.
17078 */
17079 /*
17080 * SPEC st-restrict-facets 3:
17081 * "The {facets} of R are the union of S and the {facets}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017082 * of B, eliminating duplicates. To eliminate duplicates,
17083 * when a facet of the same kind occurs in both S and the
17084 * {facets} of B, the one in the {facets} of B is not
17085 * included, with the exception of enumeration and pattern
17086 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017087 * are allowed."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017088 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017089
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017090 if ((type->facetSet == NULL) && (base->facetSet == NULL))
17091 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017092
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017093 last = type->facetSet;
17094 if (last != NULL)
17095 while (last->next != NULL)
17096 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017097
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017098 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17099 facet = cur->facet;
17100 switch (facet->type) {
17101 case XML_SCHEMA_FACET_LENGTH:
17102 flength = facet; break;
17103 case XML_SCHEMA_FACET_MINLENGTH:
17104 fminlen = facet; break;
17105 case XML_SCHEMA_FACET_MININCLUSIVE:
17106 fmininc = facet; break;
17107 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17108 fminexc = facet; break;
17109 case XML_SCHEMA_FACET_MAXLENGTH:
17110 fmaxlen = facet; break;
17111 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17112 fmaxinc = facet; break;
17113 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17114 fmaxexc = facet; break;
17115 case XML_SCHEMA_FACET_TOTALDIGITS:
17116 ftotdig = facet; break;
17117 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17118 ffracdig = facet; break;
17119 default:
17120 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017121 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017122 }
17123 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17124 facet = cur->facet;
17125 switch (facet->type) {
17126 case XML_SCHEMA_FACET_LENGTH:
17127 bflength = facet; break;
17128 case XML_SCHEMA_FACET_MINLENGTH:
17129 bfminlen = facet; break;
17130 case XML_SCHEMA_FACET_MININCLUSIVE:
17131 bfmininc = facet; break;
17132 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17133 bfminexc = facet; break;
17134 case XML_SCHEMA_FACET_MAXLENGTH:
17135 bfmaxlen = facet; break;
17136 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17137 bfmaxinc = facet; break;
17138 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17139 bfmaxexc = facet; break;
17140 case XML_SCHEMA_FACET_TOTALDIGITS:
17141 bftotdig = facet; break;
17142 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17143 bffracdig = facet; break;
17144 default:
17145 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017146 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017147 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017148 /*
17149 * length and minLength or maxLength (2.2) + (3.2)
17150 */
17151 if (flength && (fminlen || fmaxlen)) {
17152 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17153 "either of 'minLength' or 'maxLength' to be specified on "
17154 "the same type definition")
17155 }
17156 /*
17157 * Mutual exclusions in the same derivation step.
17158 */
17159 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017160 /*
17161 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017162 */
17163 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17164 }
17165 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017166 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017167 * SCC "minInclusive and minExclusive"
17168 */
17169 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017170 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017171
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017172 if (flength && bflength) {
17173 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017174 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017175 * The values have to be equal.
17176 */
17177 res = xmlSchemaCompareValues(flength->val, bflength->val);
17178 if (res == -2)
17179 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017180 if (res != 0)
17181 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17182 if ((res != 0) && (bflength->fixed)) {
17183 FACET_RESTR_FIXED_ERR(flength)
17184 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017185
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017186 }
17187 if (fminlen && bfminlen) {
17188 /*
17189 * SCC "minLength valid restriction"
17190 * minLength >= BASE minLength
17191 */
17192 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17193 if (res == -2)
17194 goto internal_error;
17195 if (res == -1)
17196 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17197 if ((res != 0) && (bfminlen->fixed)) {
17198 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017199 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017200 }
17201 if (fmaxlen && bfmaxlen) {
17202 /*
17203 * SCC "maxLength valid restriction"
17204 * maxLength <= BASE minLength
17205 */
17206 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17207 if (res == -2)
17208 goto internal_error;
17209 if (res == 1)
17210 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17211 if ((res != 0) && (bfmaxlen->fixed)) {
17212 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017213 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017214 }
17215 /*
17216 * SCC "length and minLength or maxLength"
17217 */
17218 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017219 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017220 if (flength) {
17221 if (! fminlen)
17222 flength = bflength;
17223 if (fminlen) {
17224 /* (1.1) length >= minLength */
17225 res = xmlSchemaCompareValues(flength->val, fminlen->val);
17226 if (res == -2)
17227 goto internal_error;
17228 if (res == -1)
17229 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17230 }
17231 if (! fmaxlen)
17232 fmaxlen = bfmaxlen;
17233 if (fmaxlen) {
17234 /* (2.1) length <= maxLength */
17235 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17236 if (res == -2)
17237 goto internal_error;
17238 if (res == 1)
17239 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17240 }
17241 }
17242 if (fmaxinc) {
17243 /*
17244 * "maxInclusive"
17245 */
17246 if (fmininc) {
17247 /* SCC "maxInclusive >= minInclusive" */
17248 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17249 if (res == -2)
17250 goto internal_error;
17251 if (res == -1) {
17252 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17253 }
17254 }
17255 /*
17256 * SCC "maxInclusive valid restriction"
17257 */
17258 if (bfmaxinc) {
17259 /* maxInclusive <= BASE maxInclusive */
17260 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17261 if (res == -2)
17262 goto internal_error;
17263 if (res == 1)
17264 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17265 if ((res != 0) && (bfmaxinc->fixed)) {
17266 FACET_RESTR_FIXED_ERR(fmaxinc)
17267 }
17268 }
17269 if (bfmaxexc) {
17270 /* maxInclusive < BASE maxExclusive */
17271 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17272 if (res == -2)
17273 goto internal_error;
17274 if (res != -1) {
17275 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17276 }
17277 }
17278 if (bfmininc) {
17279 /* maxInclusive >= BASE minInclusive */
17280 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17281 if (res == -2)
17282 goto internal_error;
17283 if (res == -1) {
17284 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17285 }
17286 }
17287 if (bfminexc) {
17288 /* maxInclusive > BASE minExclusive */
17289 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17290 if (res == -2)
17291 goto internal_error;
17292 if (res != 1) {
17293 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17294 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017295 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017296 }
17297 if (fmaxexc) {
17298 /*
17299 * "maxExclusive >= minExclusive"
17300 */
17301 if (fminexc) {
17302 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17303 if (res == -2)
17304 goto internal_error;
17305 if (res == -1) {
17306 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17307 }
17308 }
17309 /*
17310 * "maxExclusive valid restriction"
17311 */
17312 if (bfmaxexc) {
17313 /* maxExclusive <= BASE maxExclusive */
17314 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17315 if (res == -2)
17316 goto internal_error;
17317 if (res == 1) {
17318 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17319 }
17320 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017321 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017322 }
17323 }
17324 if (bfmaxinc) {
17325 /* maxExclusive <= BASE maxInclusive */
17326 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17327 if (res == -2)
17328 goto internal_error;
17329 if (res == 1) {
17330 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17331 }
17332 }
17333 if (bfmininc) {
17334 /* maxExclusive > BASE minInclusive */
17335 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17336 if (res == -2)
17337 goto internal_error;
17338 if (res != 1) {
17339 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17340 }
17341 }
17342 if (bfminexc) {
17343 /* maxExclusive > BASE minExclusive */
17344 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17345 if (res == -2)
17346 goto internal_error;
17347 if (res != 1) {
17348 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17349 }
17350 }
17351 }
17352 if (fminexc) {
17353 /*
17354 * "minExclusive < maxInclusive"
17355 */
17356 if (fmaxinc) {
17357 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17358 if (res == -2)
17359 goto internal_error;
17360 if (res != -1) {
17361 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17362 }
17363 }
17364 /*
17365 * "minExclusive valid restriction"
17366 */
17367 if (bfminexc) {
17368 /* minExclusive >= BASE minExclusive */
17369 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17370 if (res == -2)
17371 goto internal_error;
17372 if (res == -1) {
17373 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17374 }
17375 if ((res != 0) && (bfminexc->fixed)) {
17376 FACET_RESTR_FIXED_ERR(fminexc)
17377 }
17378 }
17379 if (bfmaxinc) {
17380 /* minExclusive <= BASE maxInclusive */
17381 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17382 if (res == -2)
17383 goto internal_error;
17384 if (res == 1) {
17385 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17386 }
17387 }
17388 if (bfmininc) {
17389 /* minExclusive >= BASE minInclusive */
17390 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17391 if (res == -2)
17392 goto internal_error;
17393 if (res == -1) {
17394 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17395 }
17396 }
17397 if (bfmaxexc) {
17398 /* minExclusive < BASE maxExclusive */
17399 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17400 if (res == -2)
17401 goto internal_error;
17402 if (res != -1) {
17403 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17404 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017405 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017406 }
17407 if (fmininc) {
17408 /*
17409 * "minInclusive < maxExclusive"
17410 */
17411 if (fmaxexc) {
17412 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17413 if (res == -2)
17414 goto internal_error;
17415 if (res != -1) {
17416 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17417 }
17418 }
17419 /*
17420 * "minExclusive valid restriction"
17421 */
17422 if (bfmininc) {
17423 /* minInclusive >= BASE minInclusive */
17424 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17425 if (res == -2)
17426 goto internal_error;
17427 if (res == -1) {
17428 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17429 }
17430 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017431 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017432 }
17433 }
17434 if (bfmaxinc) {
17435 /* minInclusive <= BASE maxInclusive */
17436 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17437 if (res == -2)
17438 goto internal_error;
Daniel Veillard0a119eb2005-07-20 13:46:00 +000017439 if (res == 1) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017440 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17441 }
17442 }
17443 if (bfminexc) {
17444 /* minInclusive > BASE minExclusive */
17445 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17446 if (res == -2)
17447 goto internal_error;
17448 if (res != 1)
17449 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17450 }
17451 if (bfmaxexc) {
17452 /* minInclusive < BASE maxExclusive */
17453 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17454 if (res == -2)
17455 goto internal_error;
17456 if (res != -1)
17457 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17458 }
17459 }
17460 if (ftotdig && bftotdig) {
17461 /*
17462 * SCC " totalDigits valid restriction"
17463 * totalDigits <= BASE totalDigits
17464 */
17465 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17466 if (res == -2)
17467 goto internal_error;
17468 if (res == 1)
17469 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17470 -1, 1, 1);
17471 if ((res != 0) && (bftotdig->fixed)) {
17472 FACET_RESTR_FIXED_ERR(ftotdig)
17473 }
17474 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017475 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017476 /*
17477 * SCC "fractionDigits valid restriction"
17478 * fractionDigits <= BASE fractionDigits
17479 */
17480 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17481 if (res == -2)
17482 goto internal_error;
17483 if (res == 1)
17484 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17485 -1, 1, 1);
17486 if ((res != 0) && (bffracdig->fixed)) {
17487 FACET_RESTR_FIXED_ERR(ffracdig)
17488 }
17489 }
17490 /*
17491 * SCC "fractionDigits less than or equal to totalDigits"
17492 */
17493 if (! ftotdig)
17494 ftotdig = bftotdig;
17495 if (! ffracdig)
17496 ffracdig = bffracdig;
17497 if (ftotdig && ffracdig) {
17498 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17499 if (res == -2)
17500 goto internal_error;
17501 if (res == 1)
17502 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17503 -1, 1, 0);
17504 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017505 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017506 * *Enumerations* won' be added here, since only the first set
17507 * of enumerations in the ancestor-or-self axis is used
17508 * for validation, plus we need to use the base type of those
17509 * enumerations for whitespace.
17510 *
17511 * *Patterns*: won't be add here, since they are ORed at
17512 * type level and ANDed at ancestor level. This will
17513 * happed during validation by walking the base axis
17514 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017515 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017516 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17517 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017518 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017519 * Special handling of enumerations and patterns.
17520 * TODO: hmm, they should not appear in the set, so remove this.
17521 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017522 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017523 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017524 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017525 /*
17526 * Search for a duplicate facet in the current type.
17527 */
17528 link = type->facetSet;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000017529 /* err = 0; */
17530 /* fixedErr = 0; */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017531 while (link != NULL) {
17532 facet = link->facet;
17533 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017534 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017535 case XML_SCHEMA_FACET_WHITESPACE:
17536 /*
17537 * The whitespace must be stronger.
17538 */
17539 if (facet->whitespace < bfacet->whitespace) {
17540 FACET_RESTR_ERR(flength,
17541 "The 'whitespace' value has to be equal to "
17542 "or stronger than the 'whitespace' value of "
17543 "the base type")
17544 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017545 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017546 (facet->whitespace != bfacet->whitespace)) {
17547 FACET_RESTR_FIXED_ERR(facet)
17548 }
17549 break;
17550 default:
17551 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017552 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017553 /* Duplicate found. */
17554 break;
17555 }
17556 link = link->next;
17557 }
17558 /*
17559 * If no duplicate was found: add the base types's facet
17560 * to the set.
17561 */
17562 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017563 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017564 xmlMalloc(sizeof(xmlSchemaFacetLink));
17565 if (link == NULL) {
17566 xmlSchemaPErrMemory(pctxt,
17567 "deriving facets, creating a facet link", NULL);
17568 return (-1);
17569 }
17570 link->facet = cur->facet;
17571 link->next = NULL;
17572 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017573 type->facetSet = link;
17574 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017575 last->next = link;
17576 last = link;
17577 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017578
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017579 }
17580
17581 return (0);
17582internal_error:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017583 PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17584 "an error occured");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017585 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017586}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017587
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017588static int
17589xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17590 xmlSchemaTypePtr type)
17591{
17592 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17593 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017594 * The actual value is then formed by replacing any union type
17595 * definition in the ·explicit members· with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017596 * {member type definitions}, in order.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017597 *
17598 * TODO: There's a bug entry at
17599 * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17600 * which indicates that we'll keep the union types the future.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017601 */
17602 link = type->memberTypes;
17603 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017604
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017605 if (WXS_IS_TYPE_NOT_FIXED(link->type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017606 xmlSchemaTypeFixup(link->type, pctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017607
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017608 if (WXS_IS_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017609 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017610 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017611 link->type = subLink->type;
17612 if (subLink->next != NULL) {
17613 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017614 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017615 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017616 while (subLink != NULL) {
17617 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017618 xmlMalloc(sizeof(xmlSchemaTypeLink));
17619 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017620 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017621 NULL);
17622 return (-1);
17623 }
17624 newLink->type = subLink->type;
17625 prevLink->next = newLink;
17626 prevLink = newLink;
17627 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017628
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017629 subLink = subLink->next;
17630 }
17631 }
17632 }
17633 }
17634 link = link->next;
17635 }
17636 return (0);
17637}
17638
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017639static void
17640xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17641{
17642 int has = 0, needVal = 0, normVal = 0;
17643
17644 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17645 if (has) {
17646 needVal = (type->baseType->flags &
17647 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17648 normVal = (type->baseType->flags &
17649 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17650 }
17651 if (type->facets != NULL) {
17652 xmlSchemaFacetPtr fac;
17653
17654 for (fac = type->facets; fac != NULL; fac = fac->next) {
17655 switch (fac->type) {
17656 case XML_SCHEMA_FACET_WHITESPACE:
17657 break;
17658 case XML_SCHEMA_FACET_PATTERN:
17659 normVal = 1;
17660 has = 1;
17661 break;
17662 case XML_SCHEMA_FACET_ENUMERATION:
17663 needVal = 1;
17664 normVal = 1;
17665 has = 1;
17666 break;
17667 default:
17668 has = 1;
17669 break;
17670 }
17671 }
17672 }
17673 if (normVal)
17674 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17675 if (needVal)
17676 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17677 if (has)
17678 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17679
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017680 if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017681 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17682 /*
17683 * OPTIMIZE VAL TODO: Some facets need a computed value.
17684 */
17685 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17686 (prim->builtInType != XML_SCHEMAS_STRING)) {
17687 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17688 }
17689 }
17690}
17691
17692static int
17693xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17694{
17695
17696
17697 /*
17698 * Evaluate the whitespace-facet value.
17699 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017700 if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017701 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17702 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017703 } else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017704 return (0);
17705
17706 if (type->facetSet != NULL) {
17707 xmlSchemaFacetLinkPtr lin;
17708
17709 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17710 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17711 switch (lin->facet->whitespace) {
17712 case XML_SCHEMAS_FACET_PRESERVE:
17713 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17714 break;
17715 case XML_SCHEMAS_FACET_REPLACE:
17716 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17717 break;
17718 case XML_SCHEMAS_FACET_COLLAPSE:
17719 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17720 break;
17721 default:
17722 return (-1);
17723 }
17724 return (0);
17725 }
17726 }
17727 }
17728 /*
17729 * For all ·atomic· datatypes other than string (and types ·derived·
17730 * by ·restriction· from it) the value of whiteSpace is fixed to
17731 * collapse
17732 */
17733 {
17734 xmlSchemaTypePtr anc;
17735
17736 for (anc = type->baseType; anc != NULL &&
17737 anc->builtInType != XML_SCHEMAS_ANYTYPE;
17738 anc = anc->baseType) {
17739
17740 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17741 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17742 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17743
17744 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17745 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17746 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17747
17748 } else
17749 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17750 break;
17751 }
17752 }
17753 return (0);
17754 }
17755 return (0);
17756}
17757
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017758static int
17759xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17760 xmlSchemaTypePtr type)
Daniel Veillard4255d502002-04-16 15:50:10 +000017761{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017762 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17763 return(0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017764 if (! WXS_IS_TYPE_NOT_FIXED_1(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017765 return(0);
17766 type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017767
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017768 if (WXS_IS_LIST(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017769 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017770 * Corresponds to <simpleType><list>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017771 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017772 if (type->subtypes == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017773 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017774 * This one is really needed, so get out.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017775 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017776 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017777 "list type has no item-type assigned");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017778 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017779 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017780 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017781 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017782 * Corresponds to <simpleType><union>...
17783 */
17784 if (type->memberTypes == NULL) {
17785 /*
17786 * This one is really needed, so get out.
17787 */
17788 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17789 "union type has no member-types assigned");
17790 return(-1);
17791 }
17792 } else {
17793 /*
17794 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017795 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017796 if (type->baseType == NULL) {
17797 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17798 "type has no base-type assigned");
17799 return(-1);
17800 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017801 if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017802 if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17803 return(-1);
17804 /*
17805 * Variety
17806 * If the <restriction> alternative is chosen, then the
17807 * {variety} of the {base type definition}.
17808 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017809 if (WXS_IS_ATOMIC(type->baseType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017810 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017811 else if (WXS_IS_LIST(type->baseType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017812 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017813 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017814 * Inherit the itemType.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017815 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017816 type->subtypes = type->baseType->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017817 } else if (WXS_IS_UNION(type->baseType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017818 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017819 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017820 * NOTE that we won't assign the memberTypes of the base,
17821 * since this will make trouble when freeing them; we will
17822 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017823 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017824 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017825 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017826 return(0);
17827}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017828
Daniel Veillard8651f532002-04-17 09:06:27 +000017829#ifdef DEBUG_TYPE
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017830xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
17831 xmlSchemaTypePtr type)
17832{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017833 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017834 xmlGenericError(xmlGenericErrorContext,
17835 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017836 type->node->doc->URL,
17837 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000017838 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017839 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000017840 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017841 if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017842 switch (type->contentType) {
17843 case XML_SCHEMA_CONTENT_SIMPLE:
17844 xmlGenericError(xmlGenericErrorContext, "simple\n");
17845 break;
17846 case XML_SCHEMA_CONTENT_ELEMENTS:
17847 xmlGenericError(xmlGenericErrorContext, "elements\n");
17848 break;
17849 case XML_SCHEMA_CONTENT_UNKNOWN:
17850 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
17851 break;
17852 case XML_SCHEMA_CONTENT_EMPTY:
17853 xmlGenericError(xmlGenericErrorContext, "empty\n");
17854 break;
17855 case XML_SCHEMA_CONTENT_MIXED:
17856 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017857 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017858 xmlGenericError(xmlGenericErrorContext,
17859 "mixed as emptiable particle\n");
17860 else
17861 xmlGenericError(xmlGenericErrorContext, "mixed\n");
17862 break;
17863 /* Removed, since not used. */
17864 /*
17865 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
17866 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
17867 break;
17868 */
17869 case XML_SCHEMA_CONTENT_BASIC:
17870 xmlGenericError(xmlGenericErrorContext, "basic\n");
17871 break;
17872 default:
17873 xmlGenericError(xmlGenericErrorContext,
17874 "not registered !!!\n");
17875 break;
17876 }
Daniel Veillard8651f532002-04-17 09:06:27 +000017877 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017878}
Daniel Veillard8651f532002-04-17 09:06:27 +000017879#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017880
17881/*
17882* 3.14.6 Constraints on Simple Type Definition Schema Components
17883*/
17884static int
17885xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
17886 xmlSchemaTypePtr type)
17887{
17888 int res, olderrs = pctxt->nberrors;
17889
17890 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17891 return(-1);
17892
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017893 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017894 return(0);
17895
17896 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
17897 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
17898
17899 if (type->baseType == NULL) {
17900 PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
17901 "missing baseType");
17902 goto exit_failure;
17903 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017904 if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017905 xmlSchemaTypeFixup(type->baseType, pctxt);
17906 /*
17907 * If a member type of a union is a union itself, we need to substitute
17908 * that member type for its member types.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017909 * NOTE that this might change in WXS 1.1; i.e. we will keep the union
17910 * types in WXS 1.1.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017911 */
17912 if ((type->memberTypes != NULL) &&
17913 (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
17914 return(-1);
17915 /*
17916 * SPEC src-simple-type 1
17917 * "The corresponding simple type definition, if any, must satisfy
17918 * the conditions set out in Constraints on Simple Type Definition
17919 * Schema Components (§3.14.6)."
17920 */
17921 /*
17922 * Schema Component Constraint: Simple Type Definition Properties Correct
17923 * (st-props-correct)
17924 */
17925 res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
17926 HFAILURE HERROR
17927 /*
17928 * Schema Component Constraint: Derivation Valid (Restriction, Simple)
17929 * (cos-st-restricts)
17930 */
17931 res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
17932 HFAILURE HERROR
17933 /*
17934 * TODO: Removed the error report, since it got annoying to get an
17935 * extra error report, if anything failed until now.
17936 * Enable this if needed.
17937 *
17938 * xmlSchemaPErr(ctxt, type->node,
17939 * XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
17940 * "Simple type '%s' does not satisfy the constraints "
17941 * "on simple type definitions.\n",
17942 * type->name, NULL);
17943 */
17944 /*
17945 * Schema Component Constraint: Simple Type Restriction (Facets)
17946 * (st-restrict-facets)
17947 */
17948 res = xmlSchemaCheckFacetValues(type, pctxt);
17949 HFAILURE HERROR
17950 if ((type->facetSet != NULL) ||
17951 (type->baseType->facetSet != NULL)) {
17952 res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
17953 HFAILURE HERROR
17954 }
17955 /*
17956 * Whitespace value.
17957 */
17958 res = xmlSchemaTypeFixupWhitespace(type);
17959 HFAILURE HERROR
17960 xmlSchemaTypeFixupOptimFacets(type);
17961
17962exit_error:
17963#ifdef DEBUG_TYPE
17964 xmlSchemaDebugFixedType(pctxt, type);
17965#endif
17966 if (olderrs != pctxt->nberrors)
17967 return(pctxt->err);
17968 return(0);
17969
17970exit_failure:
17971#ifdef DEBUG_TYPE
17972 xmlSchemaDebugFixedType(pctxt, type);
17973#endif
17974 return(-1);
17975}
17976
17977static int
17978xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
17979 xmlSchemaTypePtr type)
17980{
17981 int res = 0, olderrs = pctxt->nberrors;
17982 xmlSchemaTypePtr baseType = type->baseType;
17983
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017984 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017985 return(0);
17986 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
17987 if (baseType == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017988 PERROR_INT("xmlSchemaFixupComplexType",
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017989 "missing baseType");
17990 goto exit_failure;
17991 }
17992 /*
17993 * Fixup the base type.
17994 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017995 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017996 xmlSchemaTypeFixup(baseType, pctxt);
17997 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
17998 /*
17999 * Skip fixup if the base type is invalid.
18000 * TODO: Generate a warning!
18001 */
18002 return(0);
18003 }
18004 /*
18005 * This basically checks if the base type can be derived.
18006 */
18007 res = xmlSchemaCheckSRCCT(pctxt, type);
18008 HFAILURE HERROR
18009 /*
18010 * Fixup the content type.
18011 */
18012 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18013 /*
18014 * Corresponds to <complexType><simpleContent>...
18015 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018016 if ((WXS_IS_COMPLEX(baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018017 (baseType->contentTypeDef != NULL) &&
18018 (WXS_IS_RESTRICTION(type))) {
18019 xmlSchemaTypePtr contentBase, content;
18020#ifdef ENABLE_NAMED_LOCALS
18021 char buf[30];
18022 const xmlChar *tmpname;
18023#endif
18024 /*
18025 * SPEC (1) If <restriction> + base type is <complexType>,
18026 * "whose own {content type} is a simple type..."
18027 */
18028 if (type->contentTypeDef != NULL) {
18029 /*
18030 * SPEC (1.1) "the simple type definition corresponding to the
18031 * <simpleType> among the [children] of <restriction> if there
18032 * is one;"
18033 * Note that this "<simpleType> among the [children]" was put
18034 * into ->contentTypeDef during parsing.
18035 */
18036 contentBase = type->contentTypeDef;
18037 type->contentTypeDef = NULL;
18038 } else {
18039 /*
18040 * (1.2) "...otherwise (<restriction> has no <simpleType>
18041 * among its [children]), the simple type definition which
18042 * is the {content type} of the ... base type."
18043 */
18044 contentBase = baseType->contentTypeDef;
18045 }
18046 /*
18047 * SPEC
18048 * "... a simple type definition which restricts the simple
18049 * type definition identified in clause 1.1 or clause 1.2
18050 * with a set of facet components"
18051 *
18052 * Create the anonymous simple type, which will be the content
18053 * type of the complex type.
18054 */
18055#ifdef ENABLE_NAMED_LOCALS
18056 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18057 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018058 content = xmlSchemaAddType(pctxt, pctxt->schema,
18059 XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018060 type->node, 0);
18061#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018062 content = xmlSchemaAddType(pctxt, pctxt->schema,
18063 XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018064 type->node, 0);
18065#endif
18066 if (content == NULL)
18067 goto exit_failure;
18068 /*
18069 * We will use the same node as for the <complexType>
18070 * to have it somehow anchored in the schema doc.
18071 */
18072 content->type = XML_SCHEMA_TYPE_SIMPLE;
18073 content->baseType = contentBase;
18074 /*
18075 * Move the facets, previously anchored on the
18076 * complexType during parsing.
18077 */
18078 content->facets = type->facets;
18079 type->facets = NULL;
18080 content->facetSet = type->facetSet;
18081 type->facetSet = NULL;
18082
18083 type->contentTypeDef = content;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018084 if (WXS_IS_TYPE_NOT_FIXED(contentBase))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018085 xmlSchemaTypeFixup(contentBase, pctxt);
18086 /*
18087 * Fixup the newly created type. We don't need to check
18088 * for circularity here.
18089 */
18090 res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18091 HFAILURE HERROR
18092 res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18093 HFAILURE HERROR
18094
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018095 } else if ((WXS_IS_COMPLEX(baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018096 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18097 (WXS_IS_RESTRICTION(type))) {
18098 /*
18099 * SPEC (2) If <restriction> + base is a mixed <complexType> with
18100 * an emptiable particle, then a simple type definition which
18101 * restricts the <restriction>'s <simpleType> child.
18102 */
18103 if ((type->contentTypeDef == NULL) ||
18104 (type->contentTypeDef->baseType == NULL)) {
18105 /*
18106 * TODO: Check if this ever happens.
18107 */
18108 xmlSchemaPCustomErr(pctxt,
18109 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018110 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018111 "Internal error: xmlSchemaTypeFixup, "
18112 "complex type '%s': the <simpleContent><restriction> "
18113 "is missing a <simpleType> child, but was not catched "
18114 "by xmlSchemaCheckSRCCT()", type->name);
18115 goto exit_failure;
18116 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018117 } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018118 /*
18119 * SPEC (3) If <extension> + base is <complexType> with
18120 * <simpleType> content, "...then the {content type} of that
18121 * complex type definition"
18122 */
18123 if (baseType->contentTypeDef == NULL) {
18124 /*
18125 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18126 * should have catched this already.
18127 */
18128 xmlSchemaPCustomErr(pctxt,
18129 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018130 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018131 "Internal error: xmlSchemaTypeFixup, "
18132 "complex type '%s': the <extension>ed base type is "
18133 "a complex type with no simple content type",
18134 type->name);
18135 goto exit_failure;
18136 }
18137 type->contentTypeDef = baseType->contentTypeDef;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018138 } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018139 /*
18140 * SPEC (4) <extension> + base is <simpleType>
18141 * "... then that simple type definition"
18142 */
18143 type->contentTypeDef = baseType;
18144 } else {
18145 /*
18146 * TODO: Check if this ever happens.
18147 */
18148 xmlSchemaPCustomErr(pctxt,
18149 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018150 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018151 "Internal error: xmlSchemaTypeFixup, "
18152 "complex type '%s' with <simpleContent>: unhandled "
18153 "derivation case", type->name);
18154 goto exit_failure;
18155 }
18156 } else {
18157 int dummySequence = 0;
18158 xmlSchemaParticlePtr particle =
18159 (xmlSchemaParticlePtr) type->subtypes;
18160 /*
18161 * Corresponds to <complexType><complexContent>...
18162 *
18163 * NOTE that the effective mixed was already set during parsing of
18164 * <complexType> and <complexContent>; its flag value is
18165 * XML_SCHEMAS_TYPE_MIXED.
18166 *
18167 * Compute the "effective content":
18168 * (2.1.1) + (2.1.2) + (2.1.3)
18169 */
18170 if ((particle == NULL) ||
18171 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18172 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18173 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18174 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18175 (particle->minOccurs == 0))) &&
18176 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18177 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18178 /*
18179 * SPEC (2.1.4) "If the ·effective mixed· is true, then
18180 * a particle whose properties are as follows:..."
18181 *
18182 * Empty sequence model group with
18183 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18184 * NOTE that we sill assign it the <complexType> node to
18185 * somehow anchor it in the doc.
18186 */
18187 if ((particle == NULL) ||
18188 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18189 /*
18190 * Create the particle.
18191 */
18192 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
18193 type->node, 1, 1);
18194 if (particle == NULL)
18195 goto exit_failure;
18196 /*
18197 * Create the model group.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018198 */ /* URGENT TODO: avoid adding to pending items. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018199 particle->children = (xmlSchemaTreeItemPtr)
18200 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18201 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18202 if (particle->children == NULL)
18203 goto exit_failure;
18204
18205 type->subtypes = (xmlSchemaTypePtr) particle;
18206 }
18207 dummySequence = 1;
18208 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18209 } else {
18210 /*
18211 * SPEC (2.1.5) "otherwise empty"
18212 */
18213 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18214 }
18215 } else {
18216 /*
18217 * SPEC (2.2) "otherwise the particle corresponding to the
18218 * <all>, <choice>, <group> or <sequence> among the
18219 * [children]."
18220 */
18221 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18222 }
18223 /*
18224 * Compute the "content type".
18225 */
18226 if (WXS_IS_RESTRICTION(type)) {
18227 /*
18228 * SPEC (3.1) "If <restriction>..."
18229 * (3.1.1) + (3.1.2) */
18230 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18231 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18232 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18233 }
18234 } else {
18235 /*
18236 * SPEC (3.2) "If <extension>..."
18237 */
18238 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18239 /*
18240 * SPEC (3.2.1)
18241 */
18242 type->contentType = baseType->contentType;
18243 type->subtypes = baseType->subtypes;
18244 /*
18245 * NOTE that the effective mixed is ignored here.
18246 */
18247 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18248 /*
18249 * SPEC (3.2.2)
18250 */
18251 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18252 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18253 } else {
18254 /*
18255 * SPEC (3.2.3)
18256 */
18257 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18258 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18259 /*
18260 * "A model group whose {compositor} is sequence and whose
18261 * {particles} are..."
18262 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018263 if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18264 (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18265 ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18266 XML_SCHEMA_TYPE_ALL))
18267 {
18268 /*
18269 * SPEC cos-all-limited (1)
18270 */
18271 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18272 /* TODO: error code */
18273 XML_SCHEMAP_COS_ALL_LIMITED,
18274 WXS_ITEM_NODE(type), NULL,
18275 "The type has an 'all' model group in its "
18276 "{content type} and thus cannot be derived from "
18277 "a non-empty type, since this would produce a "
18278 "'sequence' model group containing the 'all' "
18279 "model group; 'all' model groups are not "
18280 "allowed to appear inside other model groups",
18281 NULL, NULL);
18282
18283 } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18284 (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18285 ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18286 XML_SCHEMA_TYPE_ALL))
18287 {
18288 /*
18289 * SPEC cos-all-limited (1)
18290 */
18291 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18292 /* TODO: error code */
18293 XML_SCHEMAP_COS_ALL_LIMITED,
18294 WXS_ITEM_NODE(type), NULL,
18295 "A type cannot be derived by extension from a type "
18296 "which has an 'all' model group in its "
18297 "{content type}, since this would produce a "
18298 "'sequence' model group containing the 'all' "
18299 "model group; 'all' model groups are not "
18300 "allowed to appear inside other model groups",
18301 NULL, NULL);
18302
18303 } else if (! dummySequence) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018304 xmlSchemaTreeItemPtr effectiveContent =
18305 (xmlSchemaTreeItemPtr) type->subtypes;
18306 /*
18307 * Create the particle.
18308 */
18309 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
18310 type->node, 1, 1);
18311 if (particle == NULL)
18312 goto exit_failure;
18313 /*
18314 * Create the "sequence" model group.
18315 */
18316 particle->children = (xmlSchemaTreeItemPtr)
18317 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18318 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18319 if (particle->children == NULL)
18320 goto exit_failure;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018321 WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018322 /*
18323 * SPEC "the particle of the {content type} of
18324 * the ... base ..."
18325 * Create a duplicate of the base type's particle
18326 * and assign its "term" to it.
18327 */
18328 particle->children->children =
18329 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18330 pctxt->schema, type->node,
18331 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
18332 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
18333 if (particle->children->children == NULL)
18334 goto exit_failure;
18335 particle = (xmlSchemaParticlePtr)
18336 particle->children->children;
18337 particle->children =
18338 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
18339 /*
18340 * SPEC "followed by the ·effective content·."
18341 */
18342 particle->next = effectiveContent;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018343 /*
18344 * This all will result in:
18345 * new-particle
18346 * --> new-sequence(
18347 * new-particle
18348 * --> base-model,
18349 * this-particle
18350 * --> this-model
18351 * )
18352 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018353 } else {
18354 /*
18355 * This is the case when there is already an empty
18356 * <sequence> with minOccurs==maxOccurs==1.
18357 * Just add the base types's content type.
18358 * NOTE that, although we miss to add an intermediate
18359 * <sequence>, this should produce no difference to
18360 * neither the regex compilation of the content model,
18361 * nor to the complex type contraints.
18362 */
18363 particle->children->children =
18364 (xmlSchemaTreeItemPtr) baseType->subtypes;
18365 }
18366 }
18367 }
18368 }
18369 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018370 * Now fixup attribute uses:
18371 * - expand attr. group references
18372 * - intersect attribute wildcards
18373 * - inherit attribute uses of the base type
18374 * - inherit or union attr. wildcards if extending
18375 * - apply attr. use prohibitions if restricting
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018376 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018377 res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018378 HFAILURE HERROR
18379 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018380 * Apply the complex type component constraints; this will not
18381 * check attributes, since this is done in
18382 * xmlSchemaFixupTypeAttributeUses().
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018383 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018384 res = xmlSchemaCheckCTComponent(pctxt, type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018385 HFAILURE HERROR
18386
18387#ifdef DEBUG_TYPE
18388 xmlSchemaDebugFixedType(pctxt, type);
18389#endif
18390 if (olderrs != pctxt->nberrors)
18391 return(pctxt->err);
18392 else
18393 return(0);
18394
18395exit_error:
18396 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18397#ifdef DEBUG_TYPE
18398 xmlSchemaDebugFixedType(pctxt, type);
18399#endif
18400 return(pctxt->err);
18401
18402exit_failure:
18403 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18404#ifdef DEBUG_TYPE
18405 xmlSchemaDebugFixedType(pctxt, type);
18406#endif
18407 return(-1);
18408}
18409
18410
18411/**
18412 * xmlSchemaTypeFixup:
18413 * @typeDecl: the schema type definition
18414 * @ctxt: the schema parser context
18415 *
18416 * Fixes the content model of the type.
18417 * URGENT TODO: We need an int result!
18418 */
18419static int
18420xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18421 xmlSchemaParserCtxtPtr pctxt)
18422{
18423 if (type == NULL)
18424 return(0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018425 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018426 return(0);
18427 if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18428 return(xmlSchemaFixupComplexType(pctxt, type));
18429 else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18430 return(xmlSchemaFixupSimpleTypeStageTwo(pctxt, type));
18431 return(0);
Daniel Veillard4255d502002-04-16 15:50:10 +000018432}
18433
18434/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018435 * xmlSchemaCheckFacet:
18436 * @facet: the facet
18437 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000018438 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018439 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018440 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018441 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018442 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018443 * Returns 0 if valid, a positive error code if not valid and
18444 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018445 */
18446int
18447xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018448 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018449 xmlSchemaParserCtxtPtr pctxt,
18450 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018451{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018452 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018453
Daniel Veillardce682bc2004-11-05 17:22:25 +000018454 if ((facet == NULL) || (typeDecl == NULL))
18455 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018456 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018457 * TODO: will the parser context be given if used from
18458 * the relaxNG module?
18459 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018460 if (pctxt == NULL)
18461 ctxtGiven = 0;
18462 else
18463 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018464
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018465 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018466 case XML_SCHEMA_FACET_MININCLUSIVE:
18467 case XML_SCHEMA_FACET_MINEXCLUSIVE:
18468 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018469 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18470 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018471 /*
18472 * Okay we need to validate the value
18473 * at that point.
18474 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018475 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018476
18477 /* 4.3.5.5 Constraints on enumeration Schema Components
18478 * Schema Component Constraint: enumeration valid restriction
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018479 * It is an ·error· if any member of {value} is not in the
18480 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018481 *
18482 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018483 * The value ·must· be in the
18484 * ·value space· of the ·base type·.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018485 */
18486 /*
18487 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018488 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018489 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018490 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018491 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018492 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018493 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018494 */
18495 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18496 base = typeDecl->baseType;
18497 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018498 PERROR_INT("xmlSchemaCheckFacet",
18499 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018500 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018501 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018502 } else
18503 base = typeDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018504
18505 if (! ctxtGiven) {
18506 /*
18507 * A context is needed if called from RelaxNG.
18508 */
18509 pctxt = xmlSchemaNewParserCtxt("*");
18510 if (pctxt == NULL)
18511 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018512 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018513 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018514 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018515 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018516 * facet->node is just the node holding the facet
18517 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018518 * of the facet.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018519 */
18520 ret = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018521 ACTXT_CAST pctxt, facet->node, base,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018522 facet->value, &(facet->val), 1, 1, 0);
18523 if (ret != 0) {
18524 if (ret < 0) {
18525 /* No error message for RelaxNG. */
18526 if (ctxtGiven) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018527 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018528 XML_SCHEMAP_INTERNAL, facet->node, NULL,
18529 "Internal error: xmlSchemaCheckFacet, "
18530 "failed to validate the value '%s' of the "
18531 "facet '%s' against the base type",
18532 facet->value, xmlSchemaFacetTypeToString(facet->type));
18533 }
18534 goto internal_error;
18535 }
18536 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18537 /* No error message for RelaxNG. */
18538 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018539 xmlChar *str = NULL;
18540
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018541 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018542 ret, facet->node, WXS_BASIC_CAST facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018543 "The value '%s' of the facet does not validate "
18544 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018545 facet->value,
18546 xmlSchemaFormatQName(&str,
18547 base->targetNamespace, base->name));
18548 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018549 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018550 goto exit;
18551 } else if (facet->val == NULL) {
18552 if (ctxtGiven) {
18553 PERROR_INT("xmlSchemaCheckFacet",
18554 "value was not computed");
18555 }
18556 TODO
18557 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018558 break;
18559 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018560 case XML_SCHEMA_FACET_PATTERN:
18561 facet->regexp = xmlRegexpCompile(facet->value);
18562 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018563 ret = XML_SCHEMAP_REGEXP_INVALID;
18564 /* No error message for RelaxNG. */
18565 if (ctxtGiven) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018566 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018567 ret, facet->node, WXS_BASIC_CAST typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018568 "The value '%s' of the facet 'pattern' is not a "
18569 "valid regular expression",
18570 facet->value, NULL);
18571 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018572 }
18573 break;
18574 case XML_SCHEMA_FACET_TOTALDIGITS:
18575 case XML_SCHEMA_FACET_FRACTIONDIGITS:
18576 case XML_SCHEMA_FACET_LENGTH:
18577 case XML_SCHEMA_FACET_MAXLENGTH:
18578 case XML_SCHEMA_FACET_MINLENGTH:{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018579 ret = xmlSchemaValidatePredefinedType(
18580 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18581 facet->value, &(facet->val));
18582 if (ret != 0) {
18583 if (ret < 0) {
18584 /* No error message for RelaxNG. */
18585 if (ctxtGiven) {
18586 PERROR_INT("xmlSchemaCheckFacet",
18587 "validating facet value");
18588 }
18589 goto internal_error;
18590 }
18591 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18592 /* No error message for RelaxNG. */
18593 if (ctxtGiven) {
18594 /* error code */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018595 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018596 ret, facet->node, WXS_BASIC_CAST typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018597 "The value '%s' of the facet '%s' is not a valid "
18598 "'nonNegativeInteger'",
18599 facet->value,
18600 xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018601 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018602 }
18603 break;
18604 }
18605 case XML_SCHEMA_FACET_WHITESPACE:{
18606 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18607 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18608 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18609 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18610 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18611 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18612 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018613 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18614 /* No error message for RelaxNG. */
18615 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018616 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018617 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018618 ret, facet->node, WXS_BASIC_CAST typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018619 "The value '%s' of the facet 'whitespace' is not "
18620 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018621 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018622 }
18623 }
18624 default:
18625 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018626 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018627exit:
18628 if ((! ctxtGiven) && (pctxt != NULL))
18629 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018630 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018631internal_error:
18632 if ((! ctxtGiven) && (pctxt != NULL))
18633 xmlSchemaFreeParserCtxt(pctxt);
18634 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018635}
18636
18637/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018638 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000018639 * @typeDecl: the schema type definition
18640 * @ctxt: the schema parser context
18641 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018642 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000018643 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018644static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018645xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018646 xmlSchemaParserCtxtPtr pctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000018647{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018648 int res, olderrs = pctxt->nberrors;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018649 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018650 /*
18651 * NOTE: It is intended to use the facets list, instead
18652 * of facetSet.
18653 */
18654 if (typeDecl->facets != NULL) {
18655 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018656
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018657 /*
18658 * Temporarily assign the "schema" to the validation context
18659 * of the parser context. This is needed for NOTATION validation.
18660 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018661 if (pctxt->vctxt == NULL) {
18662 if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18663 return(-1);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018664 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018665 pctxt->vctxt->schema = pctxt->schema;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018666 while (facet != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018667 res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18668 HFAILURE
Daniel Veillard01fa6152004-06-29 17:04:39 +000018669 facet = facet->next;
18670 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018671 pctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018672 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018673 if (olderrs != pctxt->nberrors)
18674 return(pctxt->err);
18675 return(0);
18676exit_failure:
18677 return(-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018678}
18679
18680/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018681 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018682 * @ctxtMGroup: the searched model group
18683 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018684 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018685 *
18686 * This one is intended to be used by
18687 * xmlSchemaCheckGroupDefCircular only.
18688 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018689 * Returns the particle with the circular model group definition reference,
18690 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018691 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018692static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018693xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018694 xmlSchemaTreeItemPtr particle)
18695{
18696 xmlSchemaTreeItemPtr circ = NULL;
18697 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018698 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018699
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018700 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018701 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018702 if (term == NULL)
18703 continue;
18704 switch (term->type) {
18705 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018706 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018707 if (gdef == groupDef)
18708 return (particle);
18709 /*
18710 * Mark this model group definition to avoid infinite
18711 * recursion on circular references not yet examined.
18712 */
18713 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18714 continue;
18715 if (gdef->children != NULL) {
18716 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18717 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18718 gdef->children->children);
18719 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18720 if (circ != NULL)
18721 return (circ);
18722 }
18723 break;
18724 case XML_SCHEMA_TYPE_SEQUENCE:
18725 case XML_SCHEMA_TYPE_CHOICE:
18726 case XML_SCHEMA_TYPE_ALL:
18727 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18728 if (circ != NULL)
18729 return (circ);
18730 break;
18731 default:
18732 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018733 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018734 }
18735 return (NULL);
18736}
18737
18738/**
18739 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018740 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018741 * @ctxt: the parser context
18742 * @name: the name
18743 *
18744 * Checks for circular references to model group definitions.
18745 */
18746static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018747xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018748 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018749{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018750 /*
18751 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018752 * 2 Circular groups are disallowed. That is, within the {particles}
18753 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018754 * is the group itself.
18755 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018756 if ((item == NULL) ||
18757 (item->type != XML_SCHEMA_TYPE_GROUP) ||
18758 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018759 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018760 {
18761 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018762
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018763 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018764 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018765 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018766 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018767 * TODO: The error report is not adequate: this constraint
18768 * is defined for model groups but not definitions, but since
18769 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018770 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018771 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018772 */
18773 xmlSchemaPCustomErr(ctxt,
18774 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018775 NULL, WXS_ITEM_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018776 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018777 "defined", xmlSchemaFormatQName(&str,
18778 item->targetNamespace, item->name));
18779 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018780 /*
18781 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018782 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018783 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018784 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018785 }
18786 }
18787}
18788
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018789/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018790 * xmlSchemaModelGroupToModelGroupDefFixup:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018791 * @ctxt: the parser context
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018792 * @mg: the model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018793 *
18794 * Assigns the model group of model group definitions to the "term"
18795 * of the referencing particle.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018796 * In xmlSchemaResolveModelGroupParticleReferences the model group
18797 * definitions were assigned to the "term", since needed for the
18798 * circularity check.
18799 *
18800 * Schema Component Constraint:
18801 * All Group Limited (cos-all-limited) (1.2)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018802 */
18803static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018804xmlSchemaModelGroupToModelGroupDefFixup(
18805 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18806 xmlSchemaModelGroupPtr mg)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018807{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018808 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
18809
18810 while (particle != NULL) {
18811 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
18812 ((WXS_PARTICLE_TERM(particle))->type !=
18813 XML_SCHEMA_TYPE_GROUP))
18814 {
18815 particle = WXS_PTC_CAST particle->next;
18816 continue;
18817 }
18818 if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
18819 /*
18820 * TODO: Remove the particle.
18821 */
18822 WXS_PARTICLE_TERM(particle) = NULL;
18823 particle = WXS_PTC_CAST particle->next;
18824 continue;
18825 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018826 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018827 * Assign the model group to the {term} of the particle.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018828 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018829 WXS_PARTICLE_TERM(particle) =
18830 WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
18831
18832 particle = WXS_PTC_CAST particle->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018833 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018834}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018835
18836/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018837 * xmlSchemaCheckAttrGroupCircularRecur:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018838 * @ctxtGr: the searched attribute group
18839 * @attr: the current attribute list to be processed
18840 *
18841 * This one is intended to be used by
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018842 * xmlSchemaCheckAttrGroupCircular only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018843 *
18844 * Returns the circular attribute grou reference, otherwise NULL.
18845 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018846static xmlSchemaQNameRefPtr
18847xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
18848 xmlSchemaItemListPtr list)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018849{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018850 xmlSchemaAttributeGroupPtr gr;
18851 xmlSchemaQNameRefPtr ref, circ;
18852 int i;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018853 /*
18854 * We will search for an attribute group reference which
18855 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018856 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018857 for (i = 0; i < list->nbItems; i++) {
18858 ref = list->items[i];
18859 if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
18860 (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
18861 (ref->item != NULL))
18862 {
18863 gr = WXS_ATTR_GROUP_CAST ref->item;
18864 if (gr == ctxtGr)
18865 return(ref);
18866 if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
18867 continue;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018868 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018869 * Mark as visited to avoid infinite recursion on
18870 * circular references not yet examined.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018871 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018872 if ((gr->attrUses) &&
18873 (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
18874 {
18875 gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
18876 circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
18877 (xmlSchemaItemListPtr) gr->attrUses);
18878 gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
18879 if (circ != NULL)
18880 return (circ);
18881 }
18882
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018883 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018884 }
18885 return (NULL);
18886}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018887
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018888/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018889 * xmlSchemaCheckAttrGroupCircular:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018890 * attrGr: the attribute group definition
18891 * @ctxt: the parser context
18892 * @name: the name
18893 *
18894 * Checks for circular references of attribute groups.
18895 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018896static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018897xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018898 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018899{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018900 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018901 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018902 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018903 * 3 Circular group reference is disallowed outside <redefine>.
18904 * That is, unless this element information item's parent is
18905 * <redefine>, then among the [children], if any, there must
18906 * not be an <attributeGroup> with ref [attribute] which resolves
18907 * to the component corresponding to this <attributeGroup>. Indirect
18908 * circularity is also ruled out. That is, when QName resolution
18909 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
18910 * any <attributeGroup>s with a ref [attribute] among the [children],
18911 * it must not be the case that a ·QName· is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018912 * which resolves to the component corresponding to this <attributeGroup>.
18913 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018914 if (attrGr->attrUses == NULL)
18915 return(0);
18916 else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
18917 return(0);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018918 else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018919 xmlSchemaQNameRefPtr circ;
18920
18921 circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
18922 (xmlSchemaItemListPtr) attrGr->attrUses);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018923 if (circ != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018924 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018925 /*
18926 * TODO: Report the referenced attr group as QName.
18927 */
18928 xmlSchemaPCustomErr(ctxt,
18929 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018930 NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018931 "Circular reference to the attribute group '%s' "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018932 "defined", xmlSchemaGetComponentQName(&str, attrGr));
18933 FREE_AND_NULL(str);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018934 /*
18935 * NOTE: We will cut the reference to avoid further
18936 * confusion of the processor.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018937 * BADSPEC TODO: The spec should define how to process in this case.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018938 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018939 circ->item = NULL;
18940 return(ctxt->err);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018941 }
18942 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018943 return(0);
18944}
18945
18946static int
18947xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
18948 xmlSchemaAttributeGroupPtr attrGr);
18949
18950/**
18951 * xmlSchemaExpandAttributeGroupRefs:
18952 * @pctxt: the parser context
18953 * @node: the node of the component holding the attribute uses
18954 * @completeWild: the intersected wildcard to be returned
18955 * @list: the attribute uses
18956 *
18957 * Substitutes contained attribute group references
18958 * for their attribute uses. Wilcards are intersected.
18959 * Attribute use prohibitions are removed from the list
18960 * and returned via the @prohibs list.
18961 * Pointlessness of attr. prohibs, if a matching attr. decl
18962 * is existent a well, are checked.
18963 */
18964static int
18965xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
18966 xmlSchemaBasicItemPtr item,
18967 xmlSchemaWildcardPtr *completeWild,
18968 xmlSchemaItemListPtr list,
18969 xmlSchemaItemListPtr prohibs)
18970{
18971 xmlSchemaAttributeGroupPtr gr;
18972 xmlSchemaAttributeUsePtr use;
18973 xmlSchemaItemListPtr sublist;
18974 int i, j;
18975 int created = (*completeWild == NULL) ? 0 : 1;
18976
18977 if (prohibs)
18978 prohibs->nbItems = 0;
18979
18980 for (i = 0; i < list->nbItems; i++) {
18981 use = list->items[i];
18982
18983 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
18984 if (prohibs == NULL) {
18985 PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
18986 "unexpected attr prohibition found");
18987 return(-1);
18988 }
18989 /*
18990 * Remove from attribute uses.
18991 */
18992 if (xmlSchemaItemListRemove(list, i) == -1)
18993 return(-1);
18994 i--;
18995 /*
18996 * Note that duplicate prohibitions were already
18997 * handled at parsing time.
18998 */
18999 /*
19000 * Add to list of prohibitions.
19001 */
19002 xmlSchemaItemListAddSize(prohibs, 2, use);
19003 continue;
19004 }
19005 if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19006 ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19007 {
19008 if ((WXS_QNAME_CAST use)->item == NULL)
19009 return(-1);
19010 gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19011 /*
19012 * Expand the referenced attr. group.
19013 * TODO: remove this, this is done in a previous step, so
19014 * already done here.
19015 */
19016 if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19017 if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19018 return(-1);
19019 }
19020 /*
19021 * Build the 'complete' wildcard; i.e. intersect multiple
19022 * wildcards.
19023 */
19024 if (gr->attributeWildcard != NULL) {
19025 if (*completeWild == NULL) {
19026 *completeWild = gr->attributeWildcard;
19027 } else {
19028 if (! created) {
19029 xmlSchemaWildcardPtr tmpWild;
19030
19031 /*
19032 * Copy the first encountered wildcard as context,
19033 * except for the annotation.
19034 *
19035 * Although the complete wildcard might not correspond
19036 * to any node in the schema, we will anchor it on
19037 * the node of the owner component.
19038 */
19039 tmpWild = xmlSchemaAddWildcard(pctxt, pctxt->schema,
19040 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19041 WXS_ITEM_NODE(item));
19042 if (tmpWild == NULL)
19043 return(-1);
19044 if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19045 tmpWild, *completeWild) == -1)
19046 return (-1);
19047 tmpWild->processContents = (*completeWild)->processContents;
19048 *completeWild = tmpWild;
19049 created = 1;
19050 }
19051
19052 if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19053 gr->attributeWildcard) == -1)
19054 return(-1);
19055 }
19056 }
19057 /*
19058 * Just remove the reference if the referenced group does not
19059 * contain any attribute uses.
19060 */
19061 if (gr->attrUses == NULL) {
19062 if (xmlSchemaItemListRemove(list, i) == -1)
19063 return(-1);
19064 i--;
19065 continue;
19066 }
19067 /*
19068 * Add the attribute uses.
19069 */
19070 sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19071 if (sublist->nbItems != 0) {
19072 list->items[i] = sublist->items[0];
19073 if (sublist->nbItems != 1) {
19074 for (j = 1; j < sublist->nbItems; j++) {
19075 i++;
19076 if (xmlSchemaItemListInsert(list,
19077 sublist->items[j], i) == -1)
19078 return(-1);
19079 }
19080 }
19081 }
19082 }
19083
19084 }
19085 /*
19086 * Handle pointless prohibitions of declared attributes.
19087 */
19088 if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19089 xmlSchemaAttributeUseProhibPtr prohib;
19090
19091 for (i = prohibs->nbItems -1; i >= 0; i--) {
19092 prohib = prohibs->items[i];
19093 for (j = 0; j < list->nbItems; j++) {
19094 use = list->items[j];
19095
19096 if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19097 (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19098 {
19099 xmlChar *str = NULL;
19100
19101 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19102 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19103 prohib->node, NULL,
19104 "Skipping pointless attribute use prohibition "
19105 "'%s', since a corresponding attribute use "
19106 "exists already in the type definition",
19107 xmlSchemaFormatQName(&str,
19108 prohib->targetNamespace, prohib->name),
19109 NULL, NULL);
19110 FREE_AND_NULL(str);
19111 /*
19112 * Remove the prohibition.
19113 */
19114 if (xmlSchemaItemListRemove(prohibs, i) == -1)
19115 return(-1);
19116 break;
19117 }
19118 }
19119 }
19120 }
19121 return(0);
19122}
19123
19124/**
19125 * xmlSchemaAttributeGroupExpandRefs:
19126 * @pctxt: the parser context
19127 * @attrGr: the attribute group definition
19128 *
19129 * Computation of:
19130 * {attribute uses} property
19131 * {attribute wildcard} property
19132 *
19133 * Substitutes contained attribute group references
19134 * for their attribute uses. Wilcards are intersected.
19135 */
19136static int
19137xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19138 xmlSchemaAttributeGroupPtr attrGr)
19139{
19140 if ((attrGr->attrUses == NULL) ||
19141 (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19142 return(0);
19143
19144 attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19145 if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19146 &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19147 return(-1);
19148 return(0);
19149}
19150
19151/**
19152 * xmlSchemaAttributeGroupExpandRefs:
19153 * @pctxt: the parser context
19154 * @attrGr: the attribute group definition
19155 *
19156 * Substitutes contained attribute group references
19157 * for their attribute uses. Wilcards are intersected.
19158 *
19159 * Schema Component Constraint:
19160 * Attribute Group Definition Properties Correct (ag-props-correct)
19161 */
19162static int
19163xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19164 xmlSchemaAttributeGroupPtr attrGr)
19165{
19166 /*
19167 * SPEC ag-props-correct
19168 * (1) "The values of the properties of an attribute group definition
19169 * must be as described in the property tableau in The Attribute
19170 * Group Definition Schema Component (§3.6.1), modulo the impact of
19171 * Missing Sub-components (§5.3);"
19172 */
19173
19174 if ((attrGr->attrUses != NULL) &&
19175 (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19176 {
19177 xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19178 xmlSchemaAttributeUsePtr use, tmp;
19179 int i, j, hasId = 0;
19180
19181 for (i = uses->nbItems -1; i >= 0; i--) {
19182 use = uses->items[i];
19183 /*
19184 * SPEC ag-props-correct
19185 * (2) "Two distinct members of the {attribute uses} must not have
19186 * {attribute declaration}s both of whose {name}s match and whose
19187 * {target namespace}s are identical."
19188 */
19189 if (i > 0) {
19190 for (j = i -1; j >= 0; j--) {
19191 tmp = uses->items[j];
19192 if ((WXS_ATTRUSE_DECL_NAME(use) ==
19193 WXS_ATTRUSE_DECL_NAME(tmp)) &&
19194 (WXS_ATTRUSE_DECL_TNS(use) ==
19195 WXS_ATTRUSE_DECL_TNS(tmp)))
19196 {
19197 xmlChar *str = NULL;
19198
19199 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19200 XML_SCHEMAP_AG_PROPS_CORRECT,
19201 attrGr->node, WXS_BASIC_CAST attrGr,
19202 "Duplicate %s",
19203 xmlSchemaGetComponentDesignation(&str, use),
19204 NULL);
19205 FREE_AND_NULL(str);
19206 /*
19207 * Remove the duplicate.
19208 */
19209 if (xmlSchemaItemListRemove(uses, i) == -1)
19210 return(-1);
19211 goto next_use;
19212 }
19213 }
19214 }
19215 /*
19216 * SPEC ag-props-correct
19217 * (3) "Two distinct members of the {attribute uses} must not have
19218 * {attribute declaration}s both of whose {type definition}s are or
19219 * are derived from ID."
19220 * TODO: Does 'derived' include member-types of unions?
19221 */
19222 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19223 if (xmlSchemaIsDerivedFromBuiltInType(
19224 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19225 {
19226 if (hasId) {
19227 xmlChar *str = NULL;
19228
19229 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19230 XML_SCHEMAP_AG_PROPS_CORRECT,
19231 attrGr->node, WXS_BASIC_CAST attrGr,
19232 "There must not exist more than one attribute "
19233 "declaration of type 'xs:ID' "
19234 "(or derived from 'xs:ID'). The %s violates this "
19235 "constraint",
19236 xmlSchemaGetComponentDesignation(&str, use),
19237 NULL);
19238 FREE_AND_NULL(str);
19239 if (xmlSchemaItemListRemove(uses, i) == -1)
19240 return(-1);
19241 }
19242 hasId = 1;
19243 }
19244 }
19245next_use: {}
19246 }
19247 }
19248 return(0);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019249}
19250
19251/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019252 * xmlSchemaResolveAttrGroupReferences:
Daniel Veillard13e04c62002-04-23 17:51:29 +000019253 * @attrgrpDecl: the schema attribute definition
19254 * @ctxt: the schema parser context
19255 * @name: the attribute name
19256 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019257 * Resolves references to attribute group definitions.
Daniel Veillard13e04c62002-04-23 17:51:29 +000019258 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019259static int
19260xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19261 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard13e04c62002-04-23 17:51:29 +000019262{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019263 xmlSchemaAttributeGroupPtr group;
Daniel Veillard13e04c62002-04-23 17:51:29 +000019264
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019265 if (ref->item != NULL)
19266 return(0);
19267 group = xmlSchemaGetAttributeGroup(ctxt->schema,
19268 ref->name,
19269 ref->targetNamespace);
19270 if (group == NULL) {
19271 xmlSchemaPResCompAttrErr(ctxt,
19272 XML_SCHEMAP_SRC_RESOLVE,
19273 NULL, ref->node,
19274 "ref", ref->name, ref->targetNamespace,
19275 ref->itemType, NULL);
19276 return(ctxt->err);
Daniel Veillard3646d642004-06-02 19:19:14 +000019277 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019278 ref->item = WXS_BASIC_CAST group;
19279 return(0);
Daniel Veillard13e04c62002-04-23 17:51:29 +000019280}
19281
19282/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019283 * xmlSchemaCheckAttrPropsCorrect:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019284 * @item: an schema attribute declaration/use
19285 * @ctxt: a schema parser context
19286 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019287 *
19288 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019289 * Schema Component Constraint:
19290 * Attribute Declaration Properties Correct (a-props-correct)
Daniel Veillard4255d502002-04-16 15:50:10 +000019291 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019292 * Validates the value constraints of an attribute declaration/use.
19293 * NOTE that this needs the simle type definitions to be already
19294 * builded and checked.
Daniel Veillard4255d502002-04-16 15:50:10 +000019295 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019296static int
19297xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19298 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019299{
19300
19301 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019302 * SPEC a-props-correct (1)
19303 * "The values of the properties of an attribute declaration must
19304 * be as described in the property tableau in The Attribute
19305 * Declaration Schema Component (§3.2.1), modulo the impact of
19306 * Missing Sub-components (§5.3)."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019307 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019308
19309 if (WXS_ATTR_TYPEDEF(attr) == NULL)
19310 return(0);
19311
19312 if (attr->defValue != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019313 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019314
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019315 /*
19316 * SPEC a-props-correct (3)
19317 * "If the {type definition} is or is derived from ID then there
19318 * must not be a {value constraint}."
19319 */
19320 if (xmlSchemaIsDerivedFromBuiltInType(
19321 WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19322 {
19323 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19324 XML_SCHEMAP_A_PROPS_CORRECT_3,
19325 NULL, WXS_BASIC_CAST attr,
19326 "Value constraints are not allowed if the type definition "
19327 "is or is derived from xs:ID",
19328 NULL, NULL);
19329 return(pctxt->err);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019330 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019331 /*
19332 * SPEC a-props-correct (2)
19333 * "if there is a {value constraint}, the canonical lexical
19334 * representation of its value must be ·valid· with respect
19335 * to the {type definition} as defined in String Valid (§3.14.4)."
19336 * TODO: Don't care about the *cononical* stuff here, this requirement
19337 * will be removed in WXS 1.1 anyway.
19338 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019339 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019340 attr->node, WXS_ATTR_TYPEDEF(attr),
19341 attr->defValue, &(attr->defVal),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019342 1, 1, 0);
19343 if (ret != 0) {
19344 if (ret < 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019345 PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019346 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019347 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019348 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019349 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019350 XML_SCHEMAP_A_PROPS_CORRECT_2,
19351 NULL, WXS_BASIC_CAST attr,
19352 "The value of the value constraint is not valid",
19353 NULL, NULL);
19354 return(pctxt->err);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019355 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019356 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019357
19358 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019359}
19360
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019361static xmlSchemaElementPtr
19362xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19363 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019364{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019365 xmlSchemaElementPtr ret;
19366
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019367 if (WXS_SUBST_HEAD(ancestor) == NULL)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019368 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019369 if (WXS_SUBST_HEAD(ancestor) == elemDecl)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019370 return (ancestor);
19371
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019372 if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019373 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019374 WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019375 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019376 WXS_SUBST_HEAD(ancestor));
19377 WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019378
19379 return (ret);
19380}
19381
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019382/**
19383 * xmlSchemaCheckElemPropsCorrect:
19384 * @ctxt: a schema parser context
19385 * @decl: the element declaration
19386 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019387 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019388 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019389 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019390 *
19391 * STATUS:
19392 * missing: (6)
19393 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019394static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019395xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19396 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019397{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019398 int ret = 0;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019399 xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019400 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019401 * SPEC (1) "The values of the properties of an element declaration
19402 * must be as described in the property tableau in The Element
19403 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
19404 * Sub-components (§5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019405 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019406 if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19407 xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019408
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019409 xmlSchemaCheckElementDeclComponent(head, pctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019410 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019411 * SPEC (3) "If there is a non-·absent· {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019412 * affiliation}, then {scope} must be global."
19413 */
19414 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19415 xmlSchemaPCustomErr(pctxt,
19416 XML_SCHEMAP_E_PROPS_CORRECT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019417 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019418 "Only global element declarations can have a "
19419 "substitution group affiliation", NULL);
19420 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019421 }
19422 /*
19423 * TODO: SPEC (6) "Circular substitution groups are disallowed.
19424 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019425 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019426 * property."
19427 */
19428 if (head == elemDecl)
19429 circ = head;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019430 else if (WXS_SUBST_HEAD(head) != NULL)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019431 circ = xmlSchemaCheckSubstGroupCircular(head, head);
19432 else
19433 circ = NULL;
19434 if (circ != NULL) {
19435 xmlChar *strA = NULL, *strB = NULL;
19436
19437 xmlSchemaPCustomErrExt(pctxt,
19438 XML_SCHEMAP_E_PROPS_CORRECT_6,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019439 WXS_BASIC_CAST circ, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019440 "The element declaration '%s' defines a circular "
19441 "substitution group to element declaration '%s'",
19442 xmlSchemaGetComponentQName(&strA, circ),
19443 xmlSchemaGetComponentQName(&strB, head),
19444 NULL);
19445 FREE_AND_NULL(strA)
19446 FREE_AND_NULL(strB)
19447 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19448 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019449 /*
19450 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019451 * the {type definition}
19452 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019453 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019454 * of the {substitution group exclusions} of the {substitution group
19455 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
19456 * (if the {type definition} is complex) or as defined in
19457 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019458 * simple)."
19459 *
19460 * NOTE: {substitution group exclusions} means the values of the
19461 * attribute "final".
19462 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019463
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019464 if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019465 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019466
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019467 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19468 set |= SUBSET_EXTENSION;
19469 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19470 set |= SUBSET_RESTRICTION;
19471
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019472 if (xmlSchemaCheckCOSDerivedOK(pctxt, typeDef,
19473 WXS_ELEM_TYPEDEF(head), set) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019474 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19475
19476 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019477 xmlSchemaPCustomErrExt(pctxt,
19478 XML_SCHEMAP_E_PROPS_CORRECT_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019479 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019480 "The type definition '%s' was "
19481 "either rejected by the substitution group "
19482 "affiliation '%s', or not validly derived from its type "
19483 "definition '%s'",
19484 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019485 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019486 xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019487 FREE_AND_NULL(strA)
19488 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019489 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019490 }
19491 }
19492 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019493 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019494 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019495 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019496 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019497 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019498 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019499 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019500 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019501 ((WXS_IS_SIMPLE(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019502 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019503 (WXS_IS_COMPLEX(typeDef) &&
19504 WXS_HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019505 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19506 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019507
19508 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19509 xmlSchemaPCustomErr(pctxt,
19510 XML_SCHEMAP_E_PROPS_CORRECT_5,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019511 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019512 "The type definition (or type definition's content type) is or "
19513 "is derived from ID; value constraints are not allowed in "
19514 "conjunction with such a type definition", NULL);
19515 } else if (elemDecl->value != NULL) {
19516 int vcret;
19517 xmlNodePtr node = NULL;
19518
19519 /*
19520 * SPEC (2) "If there is a {value constraint}, the canonical lexical
19521 * representation of its value must be ·valid· with respect to the
19522 * {type definition} as defined in Element Default Valid (Immediate)
19523 * (§3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019524 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019525 if (typeDef == NULL) {
19526 xmlSchemaPErr(pctxt, elemDecl->node,
19527 XML_SCHEMAP_INTERNAL,
19528 "Internal error: xmlSchemaCheckElemPropsCorrect, "
19529 "type is missing... skipping validation of "
19530 "the value constraint", NULL, NULL);
19531 return (-1);
19532 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019533 if (elemDecl->node != NULL) {
19534 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19535 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19536 BAD_CAST "fixed");
19537 else
19538 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19539 BAD_CAST "default");
19540 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019541 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19542 typeDef, elemDecl->value, &(elemDecl->defVal));
19543 if (vcret != 0) {
19544 if (vcret < 0) {
19545 PERROR_INT("xmlSchemaElemCheckValConstr",
19546 "failed to validate the value constraint of an "
19547 "element declaration");
19548 return (-1);
19549 }
19550 return (vcret);
19551 }
19552 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019553
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019554 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019555}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019556
19557/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019558 * xmlSchemaCheckElemSubstGroup:
19559 * @ctxt: a schema parser context
19560 * @decl: the element declaration
19561 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019562 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019563 * Schema Component Constraint:
19564 * Substitution Group (cos-equiv-class)
19565 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019566 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019567 * a list will be built for each subst. group head, holding all direct
19568 * referents to this head.
19569 * NOTE that this function needs:
19570 * 1. circular subst. groups to be checked beforehand
19571 * 2. the declaration's type to be derived from the head's type
19572 *
19573 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019574 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019575 */
19576static void
19577xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19578 xmlSchemaElementPtr elemDecl)
19579{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019580 if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019581 /* SPEC (1) "Its {abstract} is false." */
19582 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19583 return;
19584 {
19585 xmlSchemaElementPtr head;
19586 xmlSchemaTypePtr headType, type;
19587 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019588 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019589 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19590 * {disallowed substitutions} as the blocking constraint, as defined in
19591 * Substitution Group OK (Transitive) (§3.3.6)."
19592 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019593 for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19594 head = WXS_SUBST_HEAD(head)) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019595 set = 0;
19596 methSet = 0;
19597 /*
19598 * The blocking constraints.
19599 */
19600 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19601 continue;
19602 headType = head->subtypes;
19603 type = elemDecl->subtypes;
19604 if (headType == type)
19605 goto add_member;
19606 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19607 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19608 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19609 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19610 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019611 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019612 * "The set of all {derivation method}s involved in the
19613 * derivation of D's {type definition} from C's {type definition}
19614 * does not intersect with the union of the blocking constraint,
19615 * C's {prohibited substitutions} (if C is complex, otherwise the
19616 * empty set) and the {prohibited substitutions} (respectively the
19617 * empty set) of any intermediate {type definition}s in the
19618 * derivation of D's {type definition} from C's {type definition}."
19619 */
19620 /*
19621 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19622 * subst.head axis, the methSet does not need to be computed for
19623 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019624 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019625 /*
19626 * The set of all {derivation method}s involved in the derivation
19627 */
19628 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019629 if ((WXS_IS_EXTENSION(type)) &&
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019630 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19631 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019632
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019633 if (WXS_IS_RESTRICTION(type) &&
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019634 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19635 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19636
19637 type = type->baseType;
19638 }
19639 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019640 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019641 * the head's type.
19642 */
19643 type = elemDecl->subtypes->baseType;
19644 while (type != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019645 if (WXS_IS_COMPLEX(type)) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019646 if ((type->flags &
19647 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19648 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19649 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19650 if ((type->flags &
19651 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19652 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19653 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19654 } else
19655 break;
19656 if (type == headType)
19657 break;
19658 type = type->baseType;
19659 }
19660 if ((set != 0) &&
19661 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19662 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19663 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19664 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19665 continue;
19666 }
19667add_member:
19668 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19669 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19670 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19671 }
19672 }
19673}
19674
19675/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019676 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019677 * @item: an schema element declaration/particle
19678 * @ctxt: a schema parser context
19679 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019680 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019681 * Validates the value constraints of an element declaration.
19682 *
19683 * Fixes finish doing the computations on the element declarations.
19684 */
19685static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019686xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019687 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019688{
19689 if (elemDecl == NULL)
19690 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019691 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19692 return;
19693 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019694 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
19695 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019696}
19697
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019698/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019699 * xmlSchemaResolveModelGroupParticleReferences:
19700 * @particle: a particle component
19701 * @ctxt: a parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019702 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019703 * Resolves references of a model group's {particles} to
19704 * model group definitions and to element declarations.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019705 */
19706static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019707xmlSchemaResolveModelGroupParticleReferences(
19708 xmlSchemaParserCtxtPtr ctxt,
19709 xmlSchemaModelGroupPtr mg)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019710{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019711 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19712 xmlSchemaQNameRefPtr ref;
19713 xmlSchemaBasicItemPtr refItem;
19714
19715 /*
19716 * URGENT TODO: Test this.
19717 */
19718 while (particle != NULL) {
19719 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19720 ((WXS_PARTICLE_TERM(particle))->type !=
19721 XML_SCHEMA_EXTRA_QNAMEREF))
19722 {
19723 goto next_particle;
19724 }
19725 ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019726 /*
19727 * Resolve the reference.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019728 * NULL the {term} by default.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019729 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019730 particle->children = NULL;
19731
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019732 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
19733 ref->itemType, ref->name, ref->targetNamespace);
19734 if (refItem == NULL) {
19735 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019736 NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019737 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019738 /* TODO: remove the particle. */
19739 goto next_particle;
19740 }
19741 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
19742 if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
19743 /* TODO: remove the particle. */
19744 goto next_particle;
19745 /*
19746 * NOTE that we will assign the model group definition
19747 * itself to the "term" of the particle. This will ease
19748 * the check for circular model group definitions. After
19749 * that the "term" will be assigned the model group of the
19750 * model group definition.
19751 */
19752 if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
19753 XML_SCHEMA_TYPE_ALL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019754 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019755 * SPEC cos-all-limited (1)
19756 * SPEC cos-all-limited (1.2)
19757 * "It appears only as the value of one or both of the
19758 * following properties:"
19759 * (1.1) "the {model group} property of a model group
19760 * definition."
19761 * (1.2) "the {term} property of a particle [... of] the "
19762 * {content type} of a complex type definition."
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019763 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019764 xmlSchemaCustomErr(ACTXT_CAST ctxt,
19765 /* TODO: error code */
19766 XML_SCHEMAP_COS_ALL_LIMITED,
19767 WXS_ITEM_NODE(particle), NULL,
19768 "A model group definition is referenced, but "
19769 "it contains an 'all' model group, which "
19770 "cannot be contained by model groups",
19771 NULL, NULL);
19772 /* TODO: remove the particle. */
19773 goto next_particle;
19774 }
19775 particle->children = (xmlSchemaTreeItemPtr) refItem;
19776 } else {
19777 /*
19778 * TODO: Are referenced element declarations the only
19779 * other components we expect here?
19780 */
19781 particle->children = (xmlSchemaTreeItemPtr) refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019782 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019783next_particle:
19784 particle = WXS_PTC_CAST particle->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019785 }
19786}
19787
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019788static int
19789xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
19790 xmlSchemaValPtr y)
19791{
19792 xmlSchemaTypePtr tx, ty, ptx, pty;
19793 int ret;
19794
19795 while (x != NULL) {
19796 /* Same types. */
19797 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
19798 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
19799 ptx = xmlSchemaGetPrimitiveType(tx);
19800 pty = xmlSchemaGetPrimitiveType(ty);
19801 /*
19802 * (1) if a datatype T' is ·derived· by ·restriction· from an
19803 * atomic datatype T then the ·value space· of T' is a subset of
19804 * the ·value space· of T. */
19805 /*
19806 * (2) if datatypes T' and T'' are ·derived· by ·restriction·
19807 * from a common atomic ancestor T then the ·value space·s of T'
19808 * and T'' may overlap.
19809 */
19810 if (ptx != pty)
19811 return(0);
19812 /*
19813 * We assume computed values to be normalized, so do a fast
19814 * string comparison for string based types.
19815 */
19816 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019817 WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019818 if (! xmlStrEqual(
19819 xmlSchemaValueGetAsString(x),
19820 xmlSchemaValueGetAsString(y)))
19821 return (0);
19822 } else {
19823 ret = xmlSchemaCompareValuesWhtsp(
19824 x, XML_SCHEMA_WHITESPACE_PRESERVE,
19825 y, XML_SCHEMA_WHITESPACE_PRESERVE);
19826 if (ret == -2)
19827 return(-1);
19828 if (ret != 0)
19829 return(0);
19830 }
19831 /*
19832 * Lists.
19833 */
19834 x = xmlSchemaValueGetNext(x);
19835 if (x != NULL) {
19836 y = xmlSchemaValueGetNext(y);
19837 if (y == NULL)
19838 return (0);
19839 } else if (xmlSchemaValueGetNext(y) != NULL)
19840 return (0);
19841 else
19842 return (1);
19843 }
19844 return (0);
19845}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019846
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019847/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019848 * xmlSchemaResolveAttrUseReferences:
19849 * @item: an attribute use
19850 * @ctxt: a parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019851 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019852 * Resolves the referenced attribute declaration.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019853 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019854static int
19855xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
19856 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000019857{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019858 if ((ctxt == NULL) || (ause == NULL))
19859 return(-1);
19860 if ((ause->attrDecl == NULL) ||
19861 (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
19862 return(0);
19863
19864 {
19865 xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
19866
19867 /*
19868 * TODO: Evaluate, what errors could occur if the declaration is not
19869 * found.
19870 */
19871 ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
19872 ref->name, ref->targetNamespace);
19873 if (ause->attrDecl == NULL) {
19874 xmlSchemaPResCompAttrErr(ctxt,
19875 XML_SCHEMAP_SRC_RESOLVE,
19876 WXS_BASIC_CAST ause, ause->node,
19877 "ref", ref->name, ref->targetNamespace,
19878 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
19879 return(ctxt->err);;
19880 }
19881 }
19882 return(0);
19883}
19884
19885/**
19886 * xmlSchemaCheckAttrUsePropsCorrect:
19887 * @ctxt: a parser context
19888 * @use: an attribute use
19889 *
19890 * Schema Component Constraint:
19891 * Attribute Use Correct (au-props-correct)
19892 *
19893 */
19894static int
19895xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
19896 xmlSchemaAttributeUsePtr use)
19897{
19898 if ((ctxt == NULL) || (use == NULL))
19899 return(-1);
19900 if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
19901 ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
19902 return(0);
19903
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019904 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019905 * SPEC au-props-correct (1)
19906 * "The values of the properties of an attribute use must be as
19907 * described in the property tableau in The Attribute Use Schema
19908 * Component (§3.5.1), modulo the impact of Missing
19909 * Sub-components (§5.3)."
Daniel Veillardc0826a72004-08-10 14:17:33 +000019910 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019911
19912 if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
19913 ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
19914 ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
19915 {
19916 xmlSchemaPCustomErr(ctxt,
19917 XML_SCHEMAP_AU_PROPS_CORRECT_2,
19918 WXS_BASIC_CAST use, NULL,
19919 "The attribute declaration has a 'fixed' value constraint "
19920 ", thus the attribute use must also have a 'fixed' value "
19921 "constraint",
19922 NULL);
19923 return(ctxt->err);
19924 }
19925 /*
19926 * Compute and check the value constraint's value.
19927 */
19928 if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
19929 int ret;
19930 /*
19931 * TODO: The spec seems to be missing a check of the
19932 * value constraint of the attribute use. We will do it here.
19933 */
19934 /*
19935 * SPEC a-props-correct (3)
19936 */
19937 if (xmlSchemaIsDerivedFromBuiltInType(
19938 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19939 {
19940 xmlSchemaCustomErr(ACTXT_CAST ctxt,
19941 XML_SCHEMAP_AU_PROPS_CORRECT,
19942 NULL, WXS_BASIC_CAST use,
19943 "Value constraints are not allowed if the type definition "
19944 "is or is derived from xs:ID",
19945 NULL, NULL);
19946 return(ctxt->err);
19947 }
19948
19949 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
19950 use->node, WXS_ATTRUSE_TYPEDEF(use),
19951 use->defValue, &(use->defVal),
19952 1, 1, 0);
19953 if (ret != 0) {
19954 if (ret < 0) {
19955 PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
19956 "calling xmlSchemaVCheckCVCSimpleType()");
19957 return(-1);
19958 }
19959 xmlSchemaCustomErr(ACTXT_CAST ctxt,
19960 XML_SCHEMAP_AU_PROPS_CORRECT,
19961 NULL, WXS_BASIC_CAST use,
19962 "The value of the value constraint is not valid",
19963 NULL, NULL);
19964 return(ctxt->err);
19965 }
19966 }
19967 /*
19968 * SPEC au-props-correct (2)
19969 * "If the {attribute declaration} has a fixed
19970 * {value constraint}, then if the attribute use itself has a
19971 * {value constraint}, it must also be fixed and its value must match
19972 * that of the {attribute declaration}'s {value constraint}."
19973 */
19974 if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
19975 (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
19976 {
19977 if (! xmlSchemaAreValuesEqual(use->defVal,
19978 (WXS_ATTRUSE_DECL(use))->defVal))
19979 {
19980 xmlSchemaPCustomErr(ctxt,
19981 XML_SCHEMAP_AU_PROPS_CORRECT_2,
19982 WXS_BASIC_CAST use, NULL,
19983 "The 'fixed' value constraint of the attribute use "
19984 "must match the attribute declaration's value "
19985 "constraint '%s'",
19986 (WXS_ATTRUSE_DECL(use))->defValue);
19987 }
19988 return(ctxt->err);
19989 }
19990 return(0);
19991}
19992
19993
19994
19995
19996/**
19997 * xmlSchemaResolveAttrTypeReferences:
19998 * @item: an attribute declaration
19999 * @ctxt: a parser context
20000 *
20001 * Resolves the referenced type definition component.
20002 */
20003static int
20004xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20005 xmlSchemaParserCtxtPtr ctxt)
20006{
Daniel Veillard01fa6152004-06-29 17:04:39 +000020007 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020008 * The simple type definition corresponding to the <simpleType> element
20009 * information item in the [children], if present, otherwise the simple
20010 * type definition ·resolved· to by the ·actual value· of the type
Daniel Veillard01fa6152004-06-29 17:04:39 +000020011 * [attribute], if present, otherwise the ·simple ur-type definition·.
20012 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020013 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020014 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020015 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20016 if (item->subtypes != NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020017 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020018 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020019 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000020020
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020021 type = xmlSchemaGetType(ctxt->schema, item->typeName,
20022 item->typeNs);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020023 if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000020024 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000020025 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020026 WXS_BASIC_CAST item, item->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020027 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020028 XML_SCHEMA_TYPE_SIMPLE, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020029 return(ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020030 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020031 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020032
Daniel Veillard3646d642004-06-02 19:19:14 +000020033 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020034 /*
20035 * The type defaults to the xs:anySimpleType.
20036 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020037 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20038 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020039 return(0);
Daniel Veillard4255d502002-04-16 15:50:10 +000020040}
20041
20042/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020043 * xmlSchemaResolveIDCKeyReferences:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020044 * @idc: the identity-constraint definition
20045 * @ctxt: the schema parser context
20046 * @name: the attribute name
20047 *
20048 * Resolve keyRef references to key/unique IDCs.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020049 * Schema Component Constraint:
20050 * Identity-constraint Definition Properties Correct (c-props-correct)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020051 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020052static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020053xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020054 xmlSchemaParserCtxtPtr pctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020055{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020056 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020057 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020058 if (idc->ref->name != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020059 idc->ref->item = (xmlSchemaBasicItemPtr)
20060 xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20061 idc->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020062 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020063 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020064 * TODO: It is actually not an error to fail to resolve
20065 * at this stage. BUT we need to be that strict!
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020066 */
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020067 xmlSchemaPResCompAttrErr(pctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020068 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020069 WXS_BASIC_CAST idc, idc->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020070 "refer", idc->ref->name,
20071 idc->ref->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020072 XML_SCHEMA_TYPE_IDC_KEY, NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020073 return(pctxt->err);
20074 } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20075 /*
20076 * SPEC c-props-correct (1)
20077 */
20078 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20079 XML_SCHEMAP_C_PROPS_CORRECT,
20080 NULL, WXS_BASIC_CAST idc,
20081 "The keyref references a keyref",
20082 NULL, NULL);
20083 idc->ref->item = NULL;
20084 return(pctxt->err);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020085 } else {
20086 if (idc->nbFields !=
20087 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20088 xmlChar *str = NULL;
20089 xmlSchemaIDCPtr refer;
20090
20091 refer = (xmlSchemaIDCPtr) idc->ref->item;
20092 /*
20093 * SPEC c-props-correct(2)
20094 * "If the {identity-constraint category} is keyref,
20095 * the cardinality of the {fields} must equal that of
20096 * the {fields} of the {referenced key}.
20097 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020098 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020099 XML_SCHEMAP_C_PROPS_CORRECT,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020100 NULL, WXS_BASIC_CAST idc,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020101 "The cardinality of the keyref differs from the "
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020102 "cardinality of the referenced key/unique '%s'",
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020103 xmlSchemaFormatQName(&str, refer->targetNamespace,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020104 refer->name),
20105 NULL);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020106 FREE_AND_NULL(str)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020107 return(pctxt->err);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020108 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020109 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020110 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020111 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020112}
20113
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020114static int
20115xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20116 xmlSchemaParserCtxtPtr pctxt)
20117{
20118 if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20119 prohib->targetNamespace) == NULL) {
20120
20121 xmlSchemaPResCompAttrErr(pctxt,
20122 XML_SCHEMAP_SRC_RESOLVE,
20123 NULL, prohib->node,
20124 "ref", prohib->name, prohib->targetNamespace,
20125 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20126 return(XML_SCHEMAP_SRC_RESOLVE);
20127 }
20128 return(0);
20129}
20130
20131#define WXS_REDEFINED_TYPE(c) \
20132(((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20133
20134#define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20135(((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20136
20137#define WXS_REDEFINED_ATTR_GROUP(c) \
20138(((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20139
20140static int
20141xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20142{
20143 int err = 0;
20144 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20145 xmlSchemaBasicItemPtr prev, item;
20146 int wasRedefined;
20147
20148 if (redef == NULL)
20149 return(0);
20150
20151 do {
20152 item = redef->item;
20153 /*
20154 * First try to locate the redefined component in the
20155 * schema graph starting with the redefined schema.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020156 * NOTE: According to this schema bug entry:
20157 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20158 * it's not clear if the referenced component needs to originate
20159 * from the <redefine>d schema _document_ or the schema; the latter
20160 * would include all imported and included sub-schemas of the
20161 * <redefine>d schema. Currenlty we latter approach is used.
20162 * SUPPLEMENT: It seems that the WG moves towards the latter
20163 * approach, so we are doing it right.
20164 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020165 */
20166 prev = xmlSchemaFindRedefCompInGraph(
20167 redef->targetBucket, item->type,
20168 redef->refName, redef->refTargetNs);
20169 if (prev == NULL) {
20170 xmlChar *str = NULL;
20171 xmlNodePtr node;
20172
20173 /*
20174 * SPEC src-redefine:
20175 * (6.2.1) "The ·actual value· of its own name attribute plus
20176 * target namespace must successfully ·resolve· to a model
20177 * group definition in I."
20178 * (7.2.1) "The ·actual value· of its own name attribute plus
20179 * target namespace must successfully ·resolve· to an attribute
20180 * group definition in I."
20181
20182 *
20183 * Note that, if we are redefining with the use of references
20184 * to components, the spec assumes the src-resolve to be used;
20185 * but this won't assure that we search only *inside* the
20186 * redefined schema.
20187 */
20188 if (redef->reference)
20189 node = WXS_ITEM_NODE(redef->reference);
20190 else
20191 node = WXS_ITEM_NODE(item);
20192 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20193 /*
20194 * TODO: error code.
20195 * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20196 * reference kind.
20197 */
20198 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20199 "The %s to be redefined could not be found in "
20200 "the redefined schema",
20201 WXS_ITEM_TYPE_NAME(item),
20202 xmlSchemaFormatQName(&str, redef->refTargetNs,
20203 redef->refName));
20204 FREE_AND_NULL(str);
20205 err = pctxt->err;
20206 redef = redef->next;
20207 continue;
20208 }
20209 /*
20210 * TODO: Obtaining and setting the redefinition state is really
20211 * clumsy.
20212 */
20213 wasRedefined = 0;
20214 switch (item->type) {
20215 case XML_SCHEMA_TYPE_COMPLEX:
20216 case XML_SCHEMA_TYPE_SIMPLE:
20217 if ((WXS_TYPE_CAST prev)->flags &
20218 XML_SCHEMAS_TYPE_REDEFINED)
20219 {
20220 wasRedefined = 1;
20221 break;
20222 }
20223 /* Mark it as redefined. */
20224 (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20225 /*
20226 * Assign the redefined type to the
20227 * base type of the redefining type.
20228 * TODO: How
20229 */
20230 ((xmlSchemaTypePtr) item)->baseType =
20231 (xmlSchemaTypePtr) prev;
20232 break;
20233 case XML_SCHEMA_TYPE_GROUP:
20234 if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20235 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20236 {
20237 wasRedefined = 1;
20238 break;
20239 }
20240 /* Mark it as redefined. */
20241 (WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20242 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20243 if (redef->reference != NULL) {
20244 /*
20245 * Overwrite the QName-reference with the
20246 * referenced model group def.
20247 */
20248 (WXS_PTC_CAST redef->reference)->children =
20249 WXS_TREE_CAST prev;
20250 }
20251 redef->target = prev;
20252 break;
20253 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20254 if ((WXS_ATTR_GROUP_CAST prev)->flags &
20255 XML_SCHEMAS_ATTRGROUP_REDEFINED)
20256 {
20257 wasRedefined = 1;
20258 break;
20259 }
20260 (WXS_ATTR_GROUP_CAST prev)->flags |=
20261 XML_SCHEMAS_ATTRGROUP_REDEFINED;
20262 if (redef->reference != NULL) {
20263 /*
20264 * Assign the redefined attribute group to the
20265 * QName-reference component.
20266 * This is the easy case, since we will just
20267 * expand the redefined group.
20268 */
20269 (WXS_QNAME_CAST redef->reference)->item = prev;
20270 redef->target = NULL;
20271 } else {
20272 /*
20273 * This is the complicated case: we need
20274 * to apply src-redefine (7.2.2) at a later
20275 * stage, i.e. when attribute group references
20276 * have beed expanded and simple types have
20277 * beed fixed.
20278 */
20279 redef->target = prev;
20280 }
20281 break;
20282 default:
20283 PERROR_INT("xmlSchemaResolveRedefReferences",
20284 "Unexpected redefined component type");
20285 return(-1);
20286 }
20287 if (wasRedefined) {
20288 xmlChar *str = NULL;
20289 xmlNodePtr node;
20290
20291 if (redef->reference)
20292 node = WXS_ITEM_NODE(redef->reference);
20293 else
20294 node = WXS_ITEM_NODE(redef->item);
20295
20296 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20297 /* TODO: error code. */
20298 XML_SCHEMAP_SRC_REDEFINE,
20299 node, NULL,
20300 "The referenced %s was already redefined. Multiple "
20301 "redefinition of the same component is not supported",
20302 xmlSchemaGetComponentDesignation(&str, prev),
20303 NULL);
20304 FREE_AND_NULL(str)
20305 err = pctxt->err;
20306 redef = redef->next;
20307 continue;
20308 }
20309 redef = redef->next;
20310 } while (redef != NULL);
20311
20312 return(err);
20313}
20314
20315static int
20316xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20317{
20318 int err = 0;
20319 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20320 xmlSchemaBasicItemPtr item;
20321
20322 if (redef == NULL)
20323 return(0);
20324
20325 do {
20326 if (redef->target == NULL) {
20327 redef = redef->next;
20328 continue;
20329 }
20330 item = redef->item;
20331
20332 switch (item->type) {
20333 case XML_SCHEMA_TYPE_SIMPLE:
20334 case XML_SCHEMA_TYPE_COMPLEX:
20335 /*
20336 * Since the spec wants the {name} of the redefined
20337 * type to be 'absent', we'll NULL it.
20338 */
20339 (WXS_TYPE_CAST redef->target)->name = NULL;
20340
20341 /*
20342 * TODO: Seems like there's nothing more to do. The normal
20343 * inheritance mechanism is used. But not 100% sure.
20344 */
20345 break;
20346 case XML_SCHEMA_TYPE_GROUP:
20347 /*
20348 * URGENT TODO:
20349 * SPEC src-redefine:
20350 * (6.2.2) "The {model group} of the model group definition
20351 * which corresponds to it per XML Representation of Model
20352 * Group Definition Schema Components (§3.7.2) must be a
20353 * ·valid restriction· of the {model group} of that model
20354 * group definition in I, as defined in Particle Valid
20355 * (Restriction) (§3.9.6)."
20356 */
20357 break;
20358 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20359 /*
20360 * SPEC src-redefine:
20361 * (7.2.2) "The {attribute uses} and {attribute wildcard} of
20362 * the attribute group definition which corresponds to it
20363 * per XML Representation of Attribute Group Definition Schema
20364 * Components (§3.6.2) must be ·valid restrictions· of the
20365 * {attribute uses} and {attribute wildcard} of that attribute
20366 * group definition in I, as defined in clause 2, clause 3 and
20367 * clause 4 of Derivation Valid (Restriction, Complex)
20368 * (§3.4.6) (where references to the base type definition are
20369 * understood as references to the attribute group definition
20370 * in I)."
20371 */
20372 err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20373 XML_SCHEMA_ACTION_REDEFINE,
20374 item, redef->target,
20375 (WXS_ATTR_GROUP_CAST item)->attrUses,
20376 (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20377 (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20378 (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20379 if (err == -1)
20380 return(-1);
20381 break;
20382 default:
20383 break;
20384 }
20385 redef = redef->next;
20386 } while (redef != NULL);
20387 return(0);
20388}
20389
20390
20391static int
20392xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20393 xmlSchemaBucketPtr bucket)
20394{
20395 xmlSchemaBasicItemPtr item;
20396 int err;
20397 xmlHashTablePtr *table;
20398 const xmlChar *name;
20399 int i;
20400
20401#define WXS_GET_GLOBAL_HASH(c, s, slot) { \
20402 if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20403 table = &(WXS_IMPBUCKET((c))->schema->slot); \
20404 else \
20405 table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20406
20407 /*
20408 * Add global components to the schema's hash tables.
20409 * This is the place where duplicate components will be
20410 * detected.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020411 * TODO: I think normally we should support imports of the
20412 * same namespace from multiple locations. We don't do currently,
20413 * but if we do then according to:
20414 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20415 * we would need, if imported directly, to import redefined
20416 * components as well to be able to catch clashing components.
20417 * (I hope I'll still know what this means after some months :-()
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020418 */
20419 if (bucket == NULL)
20420 return(-1);
20421 if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20422 return(0);
20423 bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20424
20425 for (i = 0; i < bucket->globals->nbItems; i++) {
20426 item = bucket->globals->items[i];
20427 table = NULL;
20428 switch (item->type) {
20429 case XML_SCHEMA_TYPE_COMPLEX:
20430 case XML_SCHEMA_TYPE_SIMPLE:
20431 if (WXS_REDEFINED_TYPE(item))
20432 continue;
20433 name = (WXS_TYPE_CAST item)->name;
20434 WXS_GET_GLOBAL_HASH(bucket, schema, typeDecl)
20435 break;
20436 case XML_SCHEMA_TYPE_ELEMENT:
20437 name = (WXS_ELEM_CAST item)->name;
20438 WXS_GET_GLOBAL_HASH(bucket, schema, elemDecl)
20439 break;
20440 case XML_SCHEMA_TYPE_ATTRIBUTE:
20441 name = (WXS_ATTR_CAST item)->name;
20442 WXS_GET_GLOBAL_HASH(bucket, schema, attrDecl)
20443 break;
20444 case XML_SCHEMA_TYPE_GROUP:
20445 if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20446 continue;
20447 name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20448 WXS_GET_GLOBAL_HASH(bucket, schema, groupDecl)
20449 break;
20450 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20451 if (WXS_REDEFINED_ATTR_GROUP(item))
20452 continue;
20453 name = (WXS_ATTR_GROUP_CAST item)->name;
20454 WXS_GET_GLOBAL_HASH(bucket, schema, attrgrpDecl)
20455 break;
20456 case XML_SCHEMA_TYPE_IDC_KEY:
20457 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20458 case XML_SCHEMA_TYPE_IDC_KEYREF:
20459 name = (WXS_IDC_CAST item)->name;
20460 WXS_GET_GLOBAL_HASH(bucket, schema, idcDef)
20461 break;
20462 case XML_SCHEMA_TYPE_NOTATION:
20463 name = ((xmlSchemaNotationPtr) item)->name;
20464 WXS_GET_GLOBAL_HASH(bucket, schema, notaDecl)
20465 break;
20466 default:
20467 PERROR_INT("xmlSchemaAddComponents",
20468 "Unexpected global component type");
20469 continue;
20470 }
20471 if (*table == NULL) {
20472 *table = xmlHashCreateDict(10, pctxt->dict);
20473 if (*table == NULL) {
20474 PERROR_INT("xmlSchemaAddComponents",
20475 "failed to create a component hash table");
20476 return(-1);
20477 }
20478 }
20479 err = xmlHashAddEntry(*table, name, item);
20480 if (err != 0) {
20481 xmlChar *str = NULL;
20482
20483 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20484 XML_SCHEMAP_REDEFINED_TYPE,
20485 WXS_ITEM_NODE(item),
20486 WXS_BASIC_CAST item,
20487 "A global %s '%s' does already exist",
20488 WXS_ITEM_TYPE_NAME(item),
20489 xmlSchemaGetComponentQName(&str, item));
20490 FREE_AND_NULL(str);
20491 }
20492 }
20493 /*
20494 * Process imported/included schemas.
20495 */
20496 if (bucket->relations != NULL) {
20497 xmlSchemaSchemaRelationPtr rel = bucket->relations;
20498 do {
20499 if ((rel->bucket != NULL) &&
20500 ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20501 if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20502 return(-1);
20503 }
20504 rel = rel->next;
20505 } while (rel != NULL);
20506 }
20507 return(0);
20508}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020509
20510static int
20511xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt)
20512{
20513 xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20514 xmlSchemaTreeItemPtr item, *items;
20515 int nbItems, i;
20516
20517#define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20518
20519 if ((con->pending == NULL) ||
20520 (con->pending->nbItems == 0))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020521 return(0);
20522
20523 /* TODO:
20524 * SPEC (src-redefine):
20525 * (6.2) "If it has no such self-reference, then all of the
20526 * following must be true:"
20527
20528 * (6.2.2) The {model group} of the model group definition which
20529 * corresponds to it per XML Representation of Model Group
20530 * Definition Schema Components (§3.7.2) must be a ·valid
20531 * restriction· of the {model group} of that model group definition
20532 * in I, as defined in Particle Valid (Restriction) (§3.9.6)."
20533 */
20534 xmlSchemaCheckSRCRedefineFirst(pctxt);
20535
20536 /*
20537 * Add global components to the schemata's hash tables.
20538 */
20539 xmlSchemaAddComponents(pctxt, WXS_CONSTRUCTOR(pctxt)->mainBucket);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020540
20541 pctxt->ctxtType = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020542 items = (xmlSchemaTreeItemPtr *) con->pending->items;
20543 nbItems = con->pending->nbItems;
20544 /*
20545 * Now that we have parsed *all* the schema document(s) and converted
20546 * them to schema components, we can resolve references, apply component
20547 * constraints, create the FSA from the content model, etc.
20548 */
20549 /*
20550 * Resolve references of..
20551 *
20552 * 1. element declarations:
20553 * - the type definition
20554 * - the substitution group affiliation
20555 * 2. simple/complex types:
20556 * - the base type definition
20557 * - the memberTypes of union types
20558 * - the itemType of list types
20559 * 3. attributes declarations and attribute uses:
20560 * - the type definition
20561 * - if an attribute use, then the attribute declaration
20562 * 4. attribute group references:
20563 * - the attribute group definition
20564 * 5. particles:
20565 * - the term of the particle (e.g. a model group)
20566 * 6. IDC key-references:
20567 * - the referenced IDC 'key' or 'unique' definition
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020568 * 7. Attribute prohibitions which had a "ref" attribute.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020569 */
20570 for (i = 0; i < nbItems; i++) {
20571 item = items[i];
20572 switch (item->type) {
20573 case XML_SCHEMA_TYPE_ELEMENT:
20574 xmlSchemaResolveElementReferences(
20575 (xmlSchemaElementPtr) item, pctxt);
20576 FIXHFAILURE;
20577 break;
20578 case XML_SCHEMA_TYPE_COMPLEX:
20579 case XML_SCHEMA_TYPE_SIMPLE:
20580 xmlSchemaResolveTypeReferences(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020581 (xmlSchemaTypePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020582 FIXHFAILURE;
20583 break;
20584 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020585 xmlSchemaResolveAttrTypeReferences(
20586 (xmlSchemaAttributePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020587 FIXHFAILURE;
20588 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020589 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20590 xmlSchemaResolveAttrUseReferences(
20591 (xmlSchemaAttributeUsePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020592 FIXHFAILURE;
20593 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020594 case XML_SCHEMA_EXTRA_QNAMEREF:
20595 if ((WXS_QNAME_CAST item)->itemType ==
20596 XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20597 {
20598 xmlSchemaResolveAttrGroupReferences(
20599 WXS_QNAME_CAST item, pctxt);
20600 }
20601 FIXHFAILURE;
20602 break;
20603 case XML_SCHEMA_TYPE_SEQUENCE:
20604 case XML_SCHEMA_TYPE_CHOICE:
20605 case XML_SCHEMA_TYPE_ALL:
20606 xmlSchemaResolveModelGroupParticleReferences(pctxt,
20607 WXS_MODEL_GROUP_CAST item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020608 FIXHFAILURE;
20609 break;
20610 case XML_SCHEMA_TYPE_IDC_KEY:
20611 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20612 case XML_SCHEMA_TYPE_IDC_KEYREF:
20613 xmlSchemaResolveIDCKeyReferences(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020614 (xmlSchemaIDCPtr) item, pctxt);
20615 FIXHFAILURE;
20616 break;
20617 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20618 /*
20619 * Handle attribue prohibition which had a
20620 * "ref" attribute.
20621 */
20622 xmlSchemaResolveAttrUseProhibReferences(
20623 WXS_ATTR_PROHIB_CAST item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020624 FIXHFAILURE;
20625 break;
20626 default:
20627 break;
20628 }
20629 }
20630 if (pctxt->nberrors != 0)
20631 goto exit_error;
20632
20633 /*
20634 * Now that all references are resolved we
20635 * can check for circularity of...
20636 * 1. the base axis of type definitions
20637 * 2. nested model group definitions
20638 * 3. nested attribute group definitions
20639 * TODO: check for circual substitution groups.
20640 */
20641 for (i = 0; i < nbItems; i++) {
20642 item = items[i];
20643 /*
20644 * Let's better stop on the first error here.
20645 */
20646 switch (item->type) {
20647 case XML_SCHEMA_TYPE_COMPLEX:
20648 case XML_SCHEMA_TYPE_SIMPLE:
20649 xmlSchemaCheckTypeDefCircular(
20650 (xmlSchemaTypePtr) item, pctxt);
20651 FIXHFAILURE;
20652 if (pctxt->nberrors != 0)
20653 goto exit_error;
20654 break;
20655 case XML_SCHEMA_TYPE_GROUP:
20656 xmlSchemaCheckGroupDefCircular(
20657 (xmlSchemaModelGroupDefPtr) item, pctxt);
20658 FIXHFAILURE;
20659 if (pctxt->nberrors != 0)
20660 goto exit_error;
20661 break;
20662 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20663 xmlSchemaCheckAttrGroupCircular(
20664 (xmlSchemaAttributeGroupPtr) item, pctxt);
20665 FIXHFAILURE;
20666 if (pctxt->nberrors != 0)
20667 goto exit_error;
20668 break;
20669 default:
20670 break;
20671 }
20672 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020673 if (pctxt->nberrors != 0)
20674 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020675 /*
20676 * Model group definition references:
20677 * Such a reference is reflected by a particle at the component
20678 * level. Until now the 'term' of such particles pointed
20679 * to the model group definition; this was done, in order to
20680 * ease circularity checks. Now we need to set the 'term' of
20681 * such particles to the model group of the model group definition.
20682 */
20683 for (i = 0; i < nbItems; i++) {
20684 item = items[i];
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020685 switch (item->type) {
20686 case XML_SCHEMA_TYPE_SEQUENCE:
20687 case XML_SCHEMA_TYPE_CHOICE:
20688 xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
20689 WXS_MODEL_GROUP_CAST item);
20690 break;
20691 default:
20692 break;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020693 }
20694 }
20695 if (pctxt->nberrors != 0)
20696 goto exit_error;
20697 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020698 * Expand attribute group references of attribute group definitions.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020699 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020700 for (i = 0; i < nbItems; i++) {
20701 item = items[i];
20702 switch (item->type) {
20703 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20704 if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
20705 WXS_ATTR_GROUP_HAS_REFS(item))
20706 {
20707 xmlSchemaAttributeGroupExpandRefs(pctxt,
20708 WXS_ATTR_GROUP_CAST item);
20709 FIXHFAILURE;
20710 }
20711 break;
20712 default:
20713 break;
20714 }
20715 }
20716 if (pctxt->nberrors != 0)
20717 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020718 /*
20719 * First compute the variety of simple types. This is needed as
20720 * a seperate step, since otherwise we won't be able to detect
20721 * circular union types in all cases.
20722 */
20723 for (i = 0; i < nbItems; i++) {
20724 item = items[i];
20725 switch (item->type) {
20726 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020727 if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020728 xmlSchemaFixupSimpleTypeStageOne(pctxt,
20729 (xmlSchemaTypePtr) item);
20730 FIXHFAILURE;
20731 }
20732 break;
20733 default:
20734 break;
20735 }
20736 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020737 if (pctxt->nberrors != 0)
20738 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020739 /*
20740 * Detect circular union types. Note that this needs the variety to
20741 * be already computed.
20742 */
20743 for (i = 0; i < nbItems; i++) {
20744 item = items[i];
20745 switch (item->type) {
20746 case XML_SCHEMA_TYPE_SIMPLE:
20747 if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
20748 xmlSchemaCheckUnionTypeDefCircular(pctxt,
20749 (xmlSchemaTypePtr) item);
20750 FIXHFAILURE;
20751 }
20752 break;
20753 default:
20754 break;
20755 }
20756 }
20757 if (pctxt->nberrors != 0)
20758 goto exit_error;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020759
20760 /*
20761 * Do the complete type fixup for simple types.
20762 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020763 for (i = 0; i < nbItems; i++) {
20764 item = items[i];
20765 switch (item->type) {
20766 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020767 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
20768 xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
20769 FIXHFAILURE;
20770 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020771 break;
20772 default:
20773 break;
20774 }
20775 }
20776 if (pctxt->nberrors != 0)
20777 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020778 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020779 * At this point we need all simple types to be builded and checked.
20780 */
20781 /*
20782 * Apply contraints for attribute declarations.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020783 */
20784 for (i = 0; i < nbItems; i++) {
20785 item = items[i];
20786 switch (item->type) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020787 case XML_SCHEMA_TYPE_ATTRIBUTE:
20788 xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
20789 FIXHFAILURE;
20790 break;
20791 default:
20792 break;
20793 }
20794 }
20795 if (pctxt->nberrors != 0)
20796 goto exit_error;
20797 /*
20798 * Apply constraints for attribute uses.
20799 */
20800 for (i = 0; i < nbItems; i++) {
20801 item = items[i];
20802 switch (item->type) {
20803 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20804 if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
20805 xmlSchemaCheckAttrUsePropsCorrect(pctxt,
20806 WXS_ATTR_USE_CAST item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020807 FIXHFAILURE;
20808 }
20809 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020810 default:
20811 break;
20812 }
20813 }
20814 if (pctxt->nberrors != 0)
20815 goto exit_error;
20816
20817 /*
20818 * Apply constraints for attribute group definitions.
20819 */
20820 for (i = 0; i < nbItems; i++) {
20821 item = items[i];
20822 switch (item->type) {
20823 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20824 if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
20825 ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
20826 {
20827 xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
20828 FIXHFAILURE;
20829 }
20830 break;
20831 default:
20832 break;
20833 }
20834 }
20835 if (pctxt->nberrors != 0)
20836 goto exit_error;
20837
20838 /*
20839 * Apply constraints for redefinitions.
20840 */
20841 if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
20842 xmlSchemaCheckSRCRedefineSecond(pctxt);
20843 if (pctxt->nberrors != 0)
20844 goto exit_error;
20845
20846 /*
20847 * Fixup complex types.
20848 */
20849 for (i = 0; i < nbItems; i++) {
20850 item = con->pending->items[i];
20851 switch (item->type) {
20852 case XML_SCHEMA_TYPE_COMPLEX:
20853 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
20854 xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
20855 FIXHFAILURE;
20856 }
20857 break;
20858 default:
20859 break;
20860 }
20861 }
20862 if (pctxt->nberrors != 0)
20863 goto exit_error;
20864
20865 /*
20866 * The list could have changed, since xmlSchemaFixupComplexType()
20867 * will create particles and model groups in some cases.
20868 */
20869 items = (xmlSchemaTreeItemPtr *) con->pending->items;
20870 nbItems = con->pending->nbItems;
20871
20872 /*
20873 * At this point all complex types need to be builded and checked.
20874 */
20875 /*
20876 * Apply some constraints for element declarations.
20877 */
20878 for (i = 0; i < nbItems; i++) {
20879 item = items[i];
20880 switch (item->type) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020881 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020882
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020883 if ((((xmlSchemaElementPtr) item)->flags &
20884 XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0) {
20885 xmlSchemaCheckElementDeclComponent(
20886 (xmlSchemaElementPtr) item, pctxt);
20887 FIXHFAILURE;
20888 }
20889 break;
20890 default:
20891 break;
20892 }
20893 }
20894 if (pctxt->nberrors != 0)
20895 goto exit_error;
20896 /*
20897 * Finally we can build the automaton from the content model of
20898 * complex types.
20899 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020900
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020901 for (i = 0; i < nbItems; i++) {
20902 item = items[i];
20903 switch (item->type) {
20904 case XML_SCHEMA_TYPE_COMPLEX:
20905 xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020906 /* FIXHFAILURE; */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020907 break;
20908 default:
20909 break;
20910 }
20911 }
20912 if (pctxt->nberrors != 0)
20913 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020914 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020915 * URGENT TODO: cos-element-consistent
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020916 */
20917 con->pending->nbItems = 0;
20918 return(0);
20919exit_error:
20920 con->pending->nbItems = 0;
20921 return(pctxt->err);
20922exit_failure:
20923 con->pending->nbItems = 0;
20924 return(-1);
20925}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020926/**
Daniel Veillard4255d502002-04-16 15:50:10 +000020927 * xmlSchemaParse:
20928 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000020929 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000020930 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000020931 * XML Shema struture which can be used to validate instances.
Daniel Veillard4255d502002-04-16 15:50:10 +000020932 *
20933 * Returns the internal XML Schema structure built from the resource or
20934 * NULL in case of error
20935 */
20936xmlSchemaPtr
20937xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
20938{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020939 xmlSchemaPtr schema = NULL;
20940 xmlSchemaBucketPtr bucket = NULL;
20941 int res;
Daniel Veillard4255d502002-04-16 15:50:10 +000020942
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020943 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020944 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020945 * the API; i.e. not automatically by the validated instance document.
20946 */
20947
Daniel Veillard4255d502002-04-16 15:50:10 +000020948 xmlSchemaInitTypes();
20949
Daniel Veillard6045c902002-10-09 21:13:59 +000020950 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000020951 return (NULL);
20952
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020953 /* TODO: Init the context. Is this all we need?*/
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000020954 ctxt->nberrors = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020955 ctxt->err = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000020956 ctxt->counter = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000020957
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020958 /* Create the *main* schema. */
20959 schema = xmlSchemaNewSchema(ctxt);
20960 if (schema == NULL)
20961 goto exit_failure;
Daniel Veillard4255d502002-04-16 15:50:10 +000020962 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020963 * Create the schema constructor.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000020964 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020965 if (ctxt->constructor == NULL) {
20966 ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
20967 if (ctxt->constructor == NULL)
20968 return(NULL);
20969 /* Take ownership of the constructor to be able to free it. */
20970 ctxt->ownsConstructor = 1;
20971 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020972 ctxt->constructor->mainSchema = schema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020973 /*
20974 * Locate and add the schema document.
20975 */
20976 res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
20977 ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
20978 NULL, NULL, &bucket);
20979 if (res == -1)
20980 goto exit_failure;
20981 if (res != 0)
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000020982 goto exit;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020983
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020984 if (bucket == NULL) {
20985 /* TODO: Error code, actually we failed to *locate* the schema. */
20986 if (ctxt->URL)
20987 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
20988 NULL, NULL,
20989 "Failed to locate the main schema resource at '%s'",
20990 ctxt->URL, NULL);
20991 else
20992 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
20993 NULL, NULL,
20994 "Failed to locate the main schema resource",
20995 NULL, NULL);
20996 goto exit;
20997 }
20998 /* Set the main schema bucket. */
20999 ctxt->constructor->bucket = bucket;
21000 ctxt->targetNamespace = bucket->targetNamespace;
21001 schema->targetNamespace = bucket->targetNamespace;
21002
21003 /* Then do the parsing for good. */
21004 if (xmlSchemaParseNewDocWithContext(ctxt, schema, bucket) == -1)
21005 goto exit_failure;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021006 if (ctxt->nberrors != 0)
21007 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021008
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021009 schema->doc = bucket->doc;
21010 schema->preserve = ctxt->preserve;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021011
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021012 ctxt->schema = schema;
21013
21014 if (xmlSchemaFixupComponents(ctxt) == -1)
21015 goto exit_failure;
21016
21017 /*
21018 * TODO: This is not nice, since we cannot distinguish from the
21019 * result if there was an internal error or not.
21020 */
21021exit:
21022 if (ctxt->nberrors != 0) {
21023 if (schema) {
21024 xmlSchemaFree(schema);
21025 schema = NULL;
21026 }
21027 if (ctxt->constructor) {
21028 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21029 ctxt->constructor = NULL;
21030 ctxt->ownsConstructor = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021031 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021032 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021033 ctxt->schema = NULL;
21034 return(schema);
21035exit_failure:
21036 /*
21037 * Quite verbose, but should catch internal errors, which were
21038 * not communitated.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021039 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021040 if (schema) {
21041 xmlSchemaFree(schema);
21042 schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021043 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021044 if (ctxt->constructor) {
21045 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21046 ctxt->constructor = NULL;
21047 ctxt->ownsConstructor = 0;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000021048 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021049 PERROR_INT2("xmlSchemaParse",
21050 "An internal error occured");
21051 ctxt->schema = NULL;
21052 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000021053}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021054
Daniel Veillard4255d502002-04-16 15:50:10 +000021055/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000021056 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000021057 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000021058 * @err: the error callback
21059 * @warn: the warning callback
21060 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000021061 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000021062 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000021063 */
21064void
21065xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021066 xmlSchemaValidityErrorFunc err,
21067 xmlSchemaValidityWarningFunc warn, void *ctx)
21068{
Daniel Veillard4255d502002-04-16 15:50:10 +000021069 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021070 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000021071 ctxt->error = err;
21072 ctxt->warning = warn;
21073 ctxt->userData = ctx;
21074}
21075
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021076/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000021077 * xmlSchemaGetParserErrors:
21078 * @ctxt: a XMl-Schema parser context
21079 * @err: the error callback result
21080 * @warn: the warning callback result
21081 * @ctx: contextual data for the callbacks result
21082 *
21083 * Get the callback information used to handle errors for a parser context
21084 *
21085 * Returns -1 in case of failure, 0 otherwise
21086 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021087int
Daniel Veillard259f0df2004-08-18 09:13:18 +000021088xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21089 xmlSchemaValidityErrorFunc * err,
21090 xmlSchemaValidityWarningFunc * warn, void **ctx)
21091{
21092 if (ctxt == NULL)
21093 return(-1);
21094 if (err != NULL)
21095 *err = ctxt->error;
21096 if (warn != NULL)
21097 *warn = ctxt->warning;
21098 if (ctx != NULL)
21099 *ctx = ctxt->userData;
21100 return(0);
21101}
21102
21103/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021104 * xmlSchemaFacetTypeToString:
21105 * @type: the facet type
21106 *
21107 * Convert the xmlSchemaTypeType to a char string.
21108 *
21109 * Returns the char string representation of the facet type if the
21110 * type is a facet and an "Internal Error" string otherwise.
21111 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021112static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021113xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21114{
21115 switch (type) {
21116 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021117 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021118 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021119 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021120 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021121 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021122 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021123 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021124 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021125 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021126 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021127 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021128 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021129 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021130 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021131 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021132 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021133 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021134 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021135 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021136 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021137 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021138 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021139 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021140 default:
21141 break;
21142 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021143 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021144}
21145
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021146static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000021147xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21148{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021149 /*
21150 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000021151 * from xsd:string.
21152 */
21153 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021154 /*
21155 * Note that we assume a whitespace of preserve for anySimpleType.
21156 */
21157 if ((type->builtInType == XML_SCHEMAS_STRING) ||
21158 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21159 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000021160 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021161 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021162 else {
21163 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021164 * For all ·atomic· datatypes other than string (and types ·derived·
21165 * by ·restriction· from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000021166 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021167 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000021168 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021169 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021170 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021171 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021172 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021173 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021174 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021175 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021176 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021177 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021178 } else if (WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021179 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21180 return (XML_SCHEMA_WHITESPACE_PRESERVE);
21181 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21182 return (XML_SCHEMA_WHITESPACE_REPLACE);
21183 else
21184 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021185 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021186 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021187}
21188
Daniel Veillard4255d502002-04-16 15:50:10 +000021189/************************************************************************
21190 * *
21191 * Simple type validation *
21192 * *
21193 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000021194
Daniel Veillard4255d502002-04-16 15:50:10 +000021195
21196/************************************************************************
21197 * *
21198 * DOM Validation code *
21199 * *
21200 ************************************************************************/
21201
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021202/**
21203 * xmlSchemaAssembleByLocation:
21204 * @pctxt: a schema parser context
21205 * @vctxt: a schema validation context
21206 * @schema: the existing schema
21207 * @node: the node that fired the assembling
21208 * @nsName: the namespace name of the new schema
21209 * @location: the location of the schema
21210 *
21211 * Expands an existing schema by an additional schema.
21212 *
21213 * Returns 0 if the new schema is correct, a positive error code
21214 * number otherwise and -1 in case of an internal or API error.
21215 */
21216static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021217xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021218 xmlSchemaPtr schema,
21219 xmlNodePtr node,
21220 const xmlChar *nsName,
21221 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021222{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021223 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021224 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021225 xmlSchemaBucketPtr bucket = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021226
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021227 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021228 return (-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021229
21230 if (vctxt->pctxt == NULL) {
21231 VERROR_INT("xmlSchemaAssembleByLocation",
21232 "no parser context available");
21233 return(-1);
21234 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021235 pctxt = vctxt->pctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021236 if (pctxt->constructor == NULL) {
21237 PERROR_INT("xmlSchemaAssembleByLocation",
21238 "no constructor");
21239 return(-1);
21240 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021241 /*
21242 * Acquire the schema document.
21243 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021244 location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21245 location, node);
21246 /*
21247 * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21248 * the process will automatically change this to
21249 * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21250 */
21251 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21252 location, NULL, NULL, 0, node, NULL, nsName,
21253 &bucket);
21254 if (ret != 0)
21255 return(ret);
21256 if (bucket == NULL) {
21257 PERROR_INT("xmlSchemaAssembleByLocation",
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021258 "no schema bucket acquired");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021259 return(-1);
21260 }
21261 /*
21262 * The first located schema will be handled as if all other
21263 * schemas imported by XSI were imported by this first schema.
21264 */
21265 if ((bucket != NULL) &&
21266 (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21267 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21268 /*
21269 * TODO: Is this handled like an import? I.e. is it not an error
21270 * if the schema cannot be located?
21271 */
21272 if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21273 return(0);
21274 /*
21275 * We will reuse the parser context for every schema imported
21276 * directly via XSI. So reset the context.
21277 */
21278 pctxt->nberrors = 0;
21279 pctxt->err = 0;
21280 pctxt->doc = bucket->doc;
21281
21282 ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21283 if (ret == -1) {
21284 pctxt->doc = NULL;
21285 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021286 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021287 /* Paranoid error channelling. */
21288 if ((ret == 0) && (pctxt->nberrors != 0))
21289 ret = pctxt->err;
21290 if (pctxt->nberrors == 0) {
21291 /*
21292 * Only bother to fixup pending components, if there was
21293 * no error yet.
21294 */
21295 xmlSchemaFixupComponents(pctxt);
21296 vctxt->nberrors += pctxt->nberrors;
21297 } else {
21298 /* Add to validation error sum. */
21299 vctxt->nberrors += pctxt->nberrors;
21300 }
21301 pctxt->doc = NULL;
21302 return(ret);
21303exit_failure:
21304 pctxt->doc = NULL;
21305 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021306}
21307
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021308static xmlSchemaAttrInfoPtr
21309xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21310 int metaType)
21311{
21312 if (vctxt->nbAttrInfos == 0)
21313 return (NULL);
21314 {
21315 int i;
21316 xmlSchemaAttrInfoPtr iattr;
21317
21318 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21319 iattr = vctxt->attrInfos[i];
21320 if (iattr->metaType == metaType)
21321 return (iattr);
21322 }
21323
21324 }
21325 return (NULL);
21326}
21327
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021328/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021329 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021330 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021331 *
21332 * Expands an existing schema by an additional schema using
21333 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21334 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21335 * must be set to 1.
21336 *
21337 * Returns 0 if the new schema is correct, a positive error code
21338 * number otherwise and -1 in case of an internal or API error.
21339 */
21340static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021341xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021342{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021343 const xmlChar *cur, *end;
21344 const xmlChar *nsname = NULL, *location;
21345 int count = 0;
21346 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021347 xmlSchemaAttrInfoPtr iattr;
21348
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021349 /*
21350 * Parse the value; we will assume an even number of values
21351 * to be given (this is how Xerces and XSV work).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021352 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021353 * URGENT TODO: !! This needs to work for both
21354 * @noNamespaceSchemaLocation AND @schemaLocation on the same
21355 * element !!
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021356 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021357 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21358 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21359 if (iattr == NULL)
21360 xmlSchemaGetMetaAttrInfo(vctxt,
21361 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21362 if (iattr == NULL)
21363 return (0);
21364 cur = iattr->value;
21365 do {
21366 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021367 /*
21368 * Get the namespace name.
21369 */
21370 while (IS_BLANK_CH(*cur))
21371 cur++;
21372 end = cur;
21373 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21374 end++;
21375 if (end == cur)
21376 break;
21377 count++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021378 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021379 cur = end;
21380 }
21381 /*
21382 * Get the URI.
21383 */
21384 while (IS_BLANK_CH(*cur))
21385 cur++;
21386 end = cur;
21387 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21388 end++;
21389 if (end == cur)
21390 break;
21391 count++;
21392 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021393 cur = end;
21394 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21395 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021396 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021397 VERROR_INT("xmlSchemaAssembleByXSI",
21398 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021399 return (-1);
21400 }
21401 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021402 return (ret);
21403}
21404
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021405static const xmlChar *
21406xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21407 const xmlChar *prefix)
21408{
21409 if (vctxt->sax != NULL) {
21410 int i, j;
21411 xmlSchemaNodeInfoPtr inode;
21412
21413 for (i = vctxt->depth; i >= 0; i--) {
21414 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21415 inode = vctxt->elemInfos[i];
21416 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21417 if (((prefix == NULL) &&
21418 (inode->nsBindings[j] == NULL)) ||
21419 ((prefix != NULL) && xmlStrEqual(prefix,
21420 inode->nsBindings[j]))) {
21421
21422 /*
21423 * Note that the namespace bindings are already
21424 * in a string dict.
21425 */
21426 return (inode->nsBindings[j+1]);
21427 }
21428 }
21429 }
21430 }
21431 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000021432#ifdef LIBXML_WRITER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021433 } else if (vctxt->reader != NULL) {
21434 xmlChar *nsName;
21435
21436 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21437 if (nsName != NULL) {
21438 const xmlChar *ret;
21439
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021440 ret = xmlDictLookup(vctxt->dict, nsName, -1);
21441 xmlFree(nsName);
21442 return (ret);
21443 } else
21444 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000021445#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021446 } else {
21447 xmlNsPtr ns;
21448
21449 if ((vctxt->inode->node == NULL) ||
21450 (vctxt->inode->node->doc == NULL)) {
21451 VERROR_INT("xmlSchemaLookupNamespace",
21452 "no node or node's doc avaliable");
21453 return (NULL);
21454 }
21455 ns = xmlSearchNs(vctxt->inode->node->doc,
21456 vctxt->inode->node, prefix);
21457 if (ns != NULL)
21458 return (ns->href);
21459 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021460 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021461}
21462
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021463/*
21464* This one works on the schema of the validation context.
21465*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021466static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021467xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21468 xmlSchemaPtr schema,
21469 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021470 const xmlChar *value,
21471 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021472 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021473{
21474 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021475
21476 if (vctxt && (vctxt->schema == NULL)) {
21477 VERROR_INT("xmlSchemaValidateNotation",
21478 "a schema is needed on the validation context");
21479 return (-1);
21480 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021481 ret = xmlValidateQName(value, 1);
21482 if (ret != 0)
21483 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021484 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021485 xmlChar *localName = NULL;
21486 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021487
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021488 localName = xmlSplitQName2(value, &prefix);
21489 if (prefix != NULL) {
21490 const xmlChar *nsName = NULL;
21491
21492 if (vctxt != NULL)
21493 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21494 else if (node != NULL) {
21495 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21496 if (ns != NULL)
21497 nsName = ns->href;
21498 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021499 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021500 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021501 return (1);
21502 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021503 if (nsName == NULL) {
21504 xmlFree(prefix);
21505 xmlFree(localName);
21506 return (1);
21507 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021508 if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021509 if (valNeeded && (val != NULL)) {
21510 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
21511 BAD_CAST xmlStrdup(nsName));
21512 if (*val == NULL)
21513 ret = -1;
21514 }
21515 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021516 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021517 xmlFree(prefix);
21518 xmlFree(localName);
21519 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021520 if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021521 if (valNeeded && (val != NULL)) {
21522 (*val) = xmlSchemaNewNOTATIONValue(
21523 BAD_CAST xmlStrdup(value), NULL);
21524 if (*val == NULL)
21525 ret = -1;
21526 }
21527 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021528 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021529 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021530 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021531 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021532}
21533
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000021534static int
21535xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21536 const xmlChar* lname,
21537 const xmlChar* nsname)
21538{
21539 int i;
21540
21541 lname = xmlDictLookup(vctxt->dict, lname, -1);
21542 if (lname == NULL)
21543 return(-1);
21544 if (nsname != NULL) {
21545 nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21546 if (nsname == NULL)
21547 return(-1);
21548 }
21549 for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21550 if ((vctxt->nodeQNames->items [i] == lname) &&
21551 (vctxt->nodeQNames->items[i +1] == nsname))
21552 /* Already there */
21553 return(i);
21554 }
21555 /* Add new entry. */
21556 i = vctxt->nodeQNames->nbItems;
21557 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21558 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21559 return(i);
21560}
21561
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021562/************************************************************************
21563 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021564 * Validation of identity-constraints (IDC) *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021565 * *
21566 ************************************************************************/
21567
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021568/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021569 * xmlSchemaAugmentIDC:
21570 * @idcDef: the IDC definition
21571 *
21572 * Creates an augmented IDC definition item.
21573 *
21574 * Returns the item, or NULL on internal errors.
21575 */
21576static void
21577xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
21578 xmlSchemaValidCtxtPtr vctxt)
21579{
21580 xmlSchemaIDCAugPtr aidc;
21581
21582 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21583 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021584 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021585 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21586 NULL);
21587 return;
21588 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021589 aidc->keyrefDepth = -1;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021590 aidc->def = idcDef;
21591 aidc->next = NULL;
21592 if (vctxt->aidcs == NULL)
21593 vctxt->aidcs = aidc;
21594 else {
21595 aidc->next = vctxt->aidcs;
21596 vctxt->aidcs = aidc;
21597 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021598 /*
21599 * Save if we have keyrefs at all.
21600 */
21601 if ((vctxt->hasKeyrefs == 0) &&
21602 (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
21603 vctxt->hasKeyrefs = 1;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021604}
21605
21606/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021607 * xmlSchemaIDCNewBinding:
21608 * @idcDef: the IDC definition of this binding
21609 *
21610 * Creates a new IDC binding.
21611 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021612 * Returns the new IDC binding, NULL on internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021613 */
21614static xmlSchemaPSVIIDCBindingPtr
21615xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
21616{
21617 xmlSchemaPSVIIDCBindingPtr ret;
21618
21619 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
21620 sizeof(xmlSchemaPSVIIDCBinding));
21621 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021622 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021623 "allocating a PSVI IDC binding item", NULL);
21624 return (NULL);
21625 }
21626 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
21627 ret->definition = idcDef;
21628 return (ret);
21629}
21630
21631/**
21632 * xmlSchemaIDCStoreNodeTableItem:
21633 * @vctxt: the WXS validation context
21634 * @item: the IDC node table item
21635 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021636 * The validation context is used to store IDC node table items.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021637 * They are stored to avoid copying them if IDC node-tables are merged
21638 * with corresponding parent IDC node-tables (bubbling).
21639 *
21640 * Returns 0 if succeeded, -1 on internal errors.
21641 */
21642static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021643xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021644 xmlSchemaPSVIIDCNodePtr item)
21645{
21646 /*
21647 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021648 */
21649 if (vctxt->idcNodes == NULL) {
21650 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021651 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
21652 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021653 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021654 "allocating the IDC node table item list", NULL);
21655 return (-1);
21656 }
21657 vctxt->sizeIdcNodes = 20;
21658 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
21659 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021660 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
21661 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021662 sizeof(xmlSchemaPSVIIDCNodePtr));
21663 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021664 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021665 "re-allocating the IDC node table item list", NULL);
21666 return (-1);
21667 }
21668 }
21669 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021670
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021671 return (0);
21672}
21673
21674/**
21675 * xmlSchemaIDCStoreKey:
21676 * @vctxt: the WXS validation context
21677 * @item: the IDC key
21678 *
21679 * The validation context is used to store an IDC key.
21680 *
21681 * Returns 0 if succeeded, -1 on internal errors.
21682 */
21683static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021684xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021685 xmlSchemaPSVIIDCKeyPtr key)
21686{
21687 /*
21688 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021689 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021690 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021691 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021692 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
21693 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021694 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021695 "allocating the IDC key storage list", NULL);
21696 return (-1);
21697 }
21698 vctxt->sizeIdcKeys = 40;
21699 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
21700 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021701 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
21702 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021703 sizeof(xmlSchemaPSVIIDCKeyPtr));
21704 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021705 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021706 "re-allocating the IDC key storage list", NULL);
21707 return (-1);
21708 }
21709 }
21710 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021711
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021712 return (0);
21713}
21714
21715/**
21716 * xmlSchemaIDCAppendNodeTableItem:
21717 * @bind: the IDC binding
21718 * @ntItem: the node-table item
21719 *
21720 * Appends the IDC node-table item to the binding.
21721 *
21722 * Returns 0 on success and -1 on internal errors.
21723 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021724static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021725xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
21726 xmlSchemaPSVIIDCNodePtr ntItem)
21727{
21728 if (bind->nodeTable == NULL) {
21729 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021730 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021731 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
21732 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021733 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021734 "allocating an array of IDC node-table items", NULL);
21735 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021736 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021737 } else if (bind->sizeNodes <= bind->nbNodes) {
21738 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021739 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
21740 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021741 sizeof(xmlSchemaPSVIIDCNodePtr));
21742 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021743 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021744 "re-allocating an array of IDC node-table items", NULL);
21745 return(-1);
21746 }
21747 }
21748 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021749 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021750}
21751
21752/**
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021753 * xmlSchemaIDCAcquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021754 * @vctxt: the WXS validation context
21755 * @matcher: the IDC matcher
21756 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021757 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021758 * of the given matcher. If none found, a new one is created
21759 * and added to the IDC table.
21760 *
21761 * Returns an IDC binding or NULL on internal errors.
21762 */
21763static xmlSchemaPSVIIDCBindingPtr
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021764xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021765 xmlSchemaIDCMatcherPtr matcher)
21766{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021767 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021768
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021769 ielem = vctxt->elemInfos[matcher->depth];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021770
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021771 if (ielem->idcTable == NULL) {
21772 ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
21773 if (ielem->idcTable == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021774 return (NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021775 return(ielem->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021776 } else {
21777 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021778
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021779 bind = ielem->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021780 do {
21781 if (bind->definition == matcher->aidc->def)
21782 return(bind);
21783 if (bind->next == NULL) {
21784 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
21785 if (bind->next == NULL)
21786 return (NULL);
21787 return(bind->next);
21788 }
21789 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021790 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021791 }
21792 return (NULL);
21793}
21794
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021795static xmlSchemaItemListPtr
21796xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
21797 xmlSchemaIDCMatcherPtr matcher)
21798{
21799 if (matcher->targets == NULL)
21800 matcher->targets = xmlSchemaItemListCreate();
21801 return(matcher->targets);
21802}
21803
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021804/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021805 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021806 * @key: the IDC key
21807 *
21808 * Frees an IDC key together with its compiled value.
21809 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021810static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021811xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
21812{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021813 if (key->val != NULL)
21814 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021815 xmlFree(key);
21816}
21817
21818/**
21819 * xmlSchemaIDCFreeBinding:
21820 *
21821 * Frees an IDC binding. Note that the node table-items
21822 * are not freed.
21823 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021824static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021825xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
21826{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021827 if (bind->nodeTable != NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021828 xmlFree(bind->nodeTable);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021829 if (bind->dupls != NULL)
21830 xmlSchemaItemListFree(bind->dupls);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021831 xmlFree(bind);
21832}
21833
21834/**
21835 * xmlSchemaIDCFreeIDCTable:
21836 * @bind: the first IDC binding in the list
21837 *
21838 * Frees an IDC table, i.e. all the IDC bindings in the list.
21839 */
21840static void
21841xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
21842{
21843 xmlSchemaPSVIIDCBindingPtr prev;
21844
21845 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021846 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021847 bind = bind->next;
21848 xmlSchemaIDCFreeBinding(prev);
21849 }
21850}
21851
21852/**
21853 * xmlSchemaIDCFreeMatcherList:
21854 * @matcher: the first IDC matcher in the list
21855 *
21856 * Frees a list of IDC matchers.
21857 */
21858static void
21859xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
21860{
21861 xmlSchemaIDCMatcherPtr next;
21862
21863 while (matcher != NULL) {
21864 next = matcher->next;
21865 if (matcher->keySeqs != NULL) {
21866 int i;
21867 for (i = 0; i < matcher->sizeKeySeqs; i++)
21868 if (matcher->keySeqs[i] != NULL)
21869 xmlFree(matcher->keySeqs[i]);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021870 xmlFree(matcher->keySeqs);
21871 }
21872 if (matcher->targets != NULL) {
21873 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
21874 int i;
21875 xmlSchemaPSVIIDCNodePtr idcNode;
21876 /*
21877 * Node-table items for keyrefs are not stored globally
21878 * to the validation context, since they are not bubbled.
21879 * We need to free them here.
21880 */
21881 for (i = 0; i < matcher->targets->nbItems; i++) {
21882 idcNode =
21883 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
21884 xmlFree(idcNode->keys);
21885 xmlFree(idcNode);
21886 }
21887 }
21888 xmlSchemaItemListFree(matcher->targets);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021889 }
21890 xmlFree(matcher);
21891 matcher = next;
21892 }
21893}
21894
21895/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021896 * xmlSchemaIDCAddStateObject:
21897 * @vctxt: the WXS validation context
21898 * @matcher: the IDC matcher
21899 * @sel: the XPath information
21900 * @parent: the parent "selector" state object if any
21901 * @type: "selector" or "field"
21902 *
21903 * Creates/reuses and activates state objects for the given
21904 * XPath information; if the XPath expression consists of unions,
21905 * multiple state objects are created for every unioned expression.
21906 *
21907 * Returns 0 on success and -1 on internal errors.
21908 */
21909static int
21910xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
21911 xmlSchemaIDCMatcherPtr matcher,
21912 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021913 int type)
21914{
21915 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021916
21917 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021918 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021919 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021920 if (vctxt->xpathStatePool != NULL) {
21921 sto = vctxt->xpathStatePool;
21922 vctxt->xpathStatePool = sto->next;
21923 sto->next = NULL;
21924 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021925 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021926 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021927 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021928 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
21929 if (sto == NULL) {
21930 xmlSchemaVErrMemory(NULL,
21931 "allocating an IDC state object", NULL);
21932 return (-1);
21933 }
21934 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
21935 }
21936 /*
21937 * Add to global list.
21938 */
21939 if (vctxt->xpathStates != NULL)
21940 sto->next = vctxt->xpathStates;
21941 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021942
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021943 /*
21944 * Free the old xpath validation context.
21945 */
21946 if (sto->xpathCtxt != NULL)
21947 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
21948
21949 /*
21950 * Create a new XPath (pattern) validation context.
21951 */
21952 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
21953 (xmlPatternPtr) sel->xpathComp);
21954 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021955 VERROR_INT("xmlSchemaIDCAddStateObject",
21956 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021957 return (-1);
21958 }
21959 sto->type = type;
21960 sto->depth = vctxt->depth;
21961 sto->matcher = matcher;
21962 sto->sel = sel;
21963 sto->nbHistory = 0;
21964
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021965#ifdef DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021966 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
21967 sto->sel->xpath);
21968#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021969 return (0);
21970}
21971
21972/**
21973 * xmlSchemaXPathEvaluate:
21974 * @vctxt: the WXS validation context
21975 * @nodeType: the nodeType of the current node
21976 *
21977 * Evaluates all active XPath state objects.
21978 *
21979 * Returns the number of IC "field" state objects which resolved to
21980 * this node, 0 if none resolved and -1 on internal errors.
21981 */
21982static int
21983xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021984 xmlElementType nodeType)
21985{
21986 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021987 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021988
21989 if (vctxt->xpathStates == NULL)
21990 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021991
21992 if (nodeType == XML_ATTRIBUTE_NODE)
21993 depth++;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021994#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021995 {
21996 xmlChar *str = NULL;
21997 xmlGenericError(xmlGenericErrorContext,
21998 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021999 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22000 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022001 FREE_AND_NULL(str)
22002 }
22003#endif
22004 /*
22005 * Process all active XPath state objects.
22006 */
22007 first = vctxt->xpathStates;
22008 sto = first;
22009 while (sto != head) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022010#ifdef DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022011 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022012 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
22013 sto->matcher->aidc->def->name, sto->sel->xpath);
22014 else
22015 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
22016 sto->matcher->aidc->def->name, sto->sel->xpath);
22017#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022018 if (nodeType == XML_ELEMENT_NODE)
22019 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022020 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022021 else
22022 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022023 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022024
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022025 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022026 VERROR_INT("xmlSchemaXPathEvaluate",
22027 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022028 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022029 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022030 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022031 goto next_sto;
22032 /*
22033 * Full match.
22034 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022035#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022036 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022037 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022038#endif
22039 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022040 * Register a match in the state object history.
22041 */
22042 if (sto->history == NULL) {
22043 sto->history = (int *) xmlMalloc(5 * sizeof(int));
22044 if (sto->history == NULL) {
22045 xmlSchemaVErrMemory(NULL,
22046 "allocating the state object history", NULL);
22047 return(-1);
22048 }
22049 sto->sizeHistory = 10;
22050 } else if (sto->sizeHistory <= sto->nbHistory) {
22051 sto->sizeHistory *= 2;
22052 sto->history = (int *) xmlRealloc(sto->history,
22053 sto->sizeHistory * sizeof(int));
22054 if (sto->history == NULL) {
22055 xmlSchemaVErrMemory(NULL,
22056 "re-allocating the state object history", NULL);
22057 return(-1);
22058 }
22059 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022060 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022061
22062#ifdef DEBUG_IDC
22063 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
22064 vctxt->depth);
22065#endif
22066
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022067 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22068 xmlSchemaIDCSelectPtr sel;
22069 /*
22070 * Activate state objects for the IDC fields of
22071 * the IDC selector.
22072 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022073#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022074 xmlGenericError(xmlGenericErrorContext, "IDC: "
22075 "activating field states\n");
22076#endif
22077 sel = sto->matcher->aidc->def->fields;
22078 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022079 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22080 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22081 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022082 sel = sel->next;
22083 }
22084 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22085 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022086 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022087 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022088#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022089 xmlGenericError(xmlGenericErrorContext,
22090 "IDC: key found\n");
22091#endif
22092 /*
22093 * Notify that the character value of this node is
22094 * needed.
22095 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022096 if (resolved == 0) {
22097 if ((vctxt->inode->flags &
22098 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22099 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22100 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022101 resolved++;
22102 }
22103next_sto:
22104 if (sto->next == NULL) {
22105 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022106 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022107 */
22108 head = first;
22109 sto = vctxt->xpathStates;
22110 } else
22111 sto = sto->next;
22112 }
22113 return (resolved);
22114}
22115
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022116static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022117xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022118 xmlChar **buf,
22119 xmlSchemaPSVIIDCKeyPtr *seq,
22120 int count)
22121{
22122 int i, res;
22123 const xmlChar *value = NULL;
22124
22125 *buf = xmlStrdup(BAD_CAST "[");
22126 for (i = 0; i < count; i++) {
22127 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022128 res = xmlSchemaGetCanonValueWhtsp(seq[i]->val, &value,
22129 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type));
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022130 if (res == 0)
22131 *buf = xmlStrcat(*buf, value);
22132 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022133 VERROR_INT("xmlSchemaFormatIDCKeySequence",
22134 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022135 *buf = xmlStrcat(*buf, BAD_CAST "???");
22136 }
22137 if (i < count -1)
22138 *buf = xmlStrcat(*buf, BAD_CAST "', ");
22139 else
22140 *buf = xmlStrcat(*buf, BAD_CAST "'");
22141 if (value != NULL) {
22142 xmlFree((xmlChar *) value);
22143 value = NULL;
22144 }
22145 }
22146 *buf = xmlStrcat(*buf, BAD_CAST "]");
22147
22148 return (BAD_CAST *buf);
22149}
22150
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022151/**
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000022152 * xmlSchemaXPathPop:
22153 * @vctxt: the WXS validation context
22154 *
22155 * Pops all XPath states.
22156 *
22157 * Returns 0 on success and -1 on internal errors.
22158 */
22159static int
22160xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22161{
22162 xmlSchemaIDCStateObjPtr sto;
22163 int res;
22164
22165 if (vctxt->xpathStates == NULL)
22166 return(0);
22167 sto = vctxt->xpathStates;
22168 do {
22169 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22170 if (res == -1)
22171 return (-1);
22172 sto = sto->next;
22173 } while (sto != NULL);
22174 return(0);
22175}
22176
22177/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022178 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022179 * @vctxt: the WXS validation context
22180 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022181 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022182 *
22183 * Processes and pops the history items of the IDC state objects.
22184 * IDC key-sequences are validated/created on IDC bindings.
22185 *
22186 * Returns 0 on success and -1 on internal errors.
22187 */
22188static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022189xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022190 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022191{
22192 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022193 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022194 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022195 xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022196
22197 if (vctxt->xpathStates == NULL)
22198 return (0);
22199 sto = vctxt->xpathStates;
22200
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022201#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022202 {
22203 xmlChar *str = NULL;
22204 xmlGenericError(xmlGenericErrorContext,
22205 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022206 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22207 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022208 FREE_AND_NULL(str)
22209 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022210#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022211 /*
22212 * Evaluate the state objects.
22213 */
22214 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000022215 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22216 if (res == -1) {
22217 VERROR_INT("xmlSchemaXPathProcessHistory",
22218 "calling xmlStreamPop()");
22219 return (-1);
22220 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022221#ifdef DEBUG_IDC
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022222 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
22223 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022224#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022225 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022226 goto deregister_check;
22227
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022228 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022229
22230 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022231 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022232 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022233 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022234 sto = sto->next;
22235 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022236 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022237 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022238 /*
22239 * NOTE: According to
22240 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22241 * ... the simple-content of complex types is also allowed.
22242 */
22243
22244 if (WXS_IS_COMPLEX(type)) {
22245 if (WXS_HAS_SIMPLE_CONTENT(type)) {
22246 /*
22247 * Sanity check for complex types with simple content.
22248 */
22249 simpleType = type->contentTypeDef;
22250 if (simpleType == NULL) {
22251 VERROR_INT("xmlSchemaXPathProcessHistory",
22252 "field resolves to a CT with simple content "
22253 "but the CT is missing the ST definition");
22254 return (-1);
22255 }
22256 } else
22257 simpleType = NULL;
22258 } else
22259 simpleType = type;
22260 if (simpleType == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022261 xmlChar *str = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022262
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022263 /*
22264 * Not qualified if the field resolves to a node of non
22265 * simple type.
22266 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022267 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022268 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022269 WXS_BASIC_CAST sto->matcher->aidc->def,
22270 "The XPath '%s' of a field of %s does evaluate to a node of "
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022271 "non-simple type",
22272 sto->sel->xpath,
22273 xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22274 FREE_AND_NULL(str);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022275 sto->nbHistory--;
22276 goto deregister_check;
22277 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022278
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022279 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022280 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022281 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022282 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022283 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022284 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022285 WXS_BASIC_CAST sto->matcher->aidc->def,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000022286 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022287 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022288 sto->nbHistory--;
22289 goto deregister_check;
22290 } else {
22291 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22292 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022293 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022294
22295 /*
22296 * The key will be anchored on the matcher's list of
22297 * key-sequences. The position in this list is determined
22298 * by the target node's depth relative to the matcher's
22299 * depth of creation (i.e. the depth of the scope element).
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022300 *
22301 * Element Depth Pos List-entries
22302 * <scope> 0 NULL
22303 * <bar> 1 NULL
22304 * <target/> 2 2 target
22305 * <bar>
22306 * </scope>
22307 *
22308 * The size of the list is only dependant on the depth of
22309 * the tree.
22310 * An entry will be NULLed in selector_leave, i.e. when
22311 * we hit the target's
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022312 */
22313 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022314 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022315
22316 /*
22317 * Create/grow the array of key-sequences.
22318 */
22319 if (matcher->keySeqs == NULL) {
22320 if (pos > 9)
22321 matcher->sizeKeySeqs = pos * 2;
22322 else
22323 matcher->sizeKeySeqs = 10;
22324 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22325 xmlMalloc(matcher->sizeKeySeqs *
22326 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22327 if (matcher->keySeqs == NULL) {
22328 xmlSchemaVErrMemory(NULL,
22329 "allocating an array of key-sequences",
22330 NULL);
22331 return(-1);
22332 }
22333 memset(matcher->keySeqs, 0,
22334 matcher->sizeKeySeqs *
22335 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22336 } else if (pos >= matcher->sizeKeySeqs) {
22337 int i = matcher->sizeKeySeqs;
22338
22339 matcher->sizeKeySeqs *= 2;
22340 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22341 xmlRealloc(matcher->keySeqs,
22342 matcher->sizeKeySeqs *
22343 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022344 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022345 xmlSchemaVErrMemory(NULL,
22346 "reallocating an array of key-sequences",
22347 NULL);
22348 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022349 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022350 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022351 * The array needs to be NULLed.
22352 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022353 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022354 for (; i < matcher->sizeKeySeqs; i++)
22355 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022356 }
22357
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022358 /*
22359 * Get/create the key-sequence.
22360 */
22361 keySeq = matcher->keySeqs[pos];
22362 if (keySeq == NULL) {
22363 goto create_sequence;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022364 } else if (keySeq[idx] != NULL) {
22365 xmlChar *str = NULL;
22366 /*
22367 * cvc-identity-constraint:
22368 * 3 For each node in the ·target node set· all
22369 * of the {fields}, with that node as the context
22370 * node, evaluate to either an empty node-set or
22371 * a node-set with exactly one member, which must
22372 * have a simple type.
22373 *
22374 * The key was already set; report an error.
22375 */
22376 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22377 XML_SCHEMAV_CVC_IDC, NULL,
22378 WXS_BASIC_CAST matcher->aidc->def,
22379 "The XPath '%s' of a field of %s evaluates to a "
22380 "node-set with more than one member",
22381 sto->sel->xpath,
22382 xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22383 FREE_AND_NULL(str);
22384 sto->nbHistory--;
22385 goto deregister_check;
22386 } else
22387 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022388
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022389create_sequence:
22390 /*
22391 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022392 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022393 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22394 matcher->aidc->def->nbFields *
22395 sizeof(xmlSchemaPSVIIDCKeyPtr));
22396 if (keySeq == NULL) {
22397 xmlSchemaVErrMemory(NULL,
22398 "allocating an IDC key-sequence", NULL);
22399 return(-1);
22400 }
22401 memset(keySeq, 0, matcher->aidc->def->nbFields *
22402 sizeof(xmlSchemaPSVIIDCKeyPtr));
22403 matcher->keySeqs[pos] = keySeq;
22404create_key:
22405 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022406 * Create a key once per node only.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022407 */
22408 if (key == NULL) {
22409 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22410 sizeof(xmlSchemaPSVIIDCKey));
22411 if (key == NULL) {
22412 xmlSchemaVErrMemory(NULL,
22413 "allocating a IDC key", NULL);
22414 xmlFree(keySeq);
22415 matcher->keySeqs[pos] = NULL;
22416 return(-1);
22417 }
22418 /*
22419 * Consume the compiled value.
22420 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022421 key->type = simpleType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022422 key->val = vctxt->inode->val;
22423 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022424 /*
22425 * Store the key in a global list.
22426 */
22427 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22428 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022429 return (-1);
22430 }
22431 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022432 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022433 }
22434 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022435
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022436 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022437 /* xmlSchemaPSVIIDCBindingPtr bind; */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022438 xmlSchemaPSVIIDCNodePtr ntItem;
22439 xmlSchemaIDCMatcherPtr matcher;
22440 xmlSchemaIDCPtr idc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022441 xmlSchemaItemListPtr targets;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022442 int pos, i, j, nbKeys;
22443 /*
22444 * Here we have the following scenario:
22445 * An IDC 'selector' state object resolved to a target node,
22446 * during the time this target node was in the
22447 * ancestor-or-self axis, the 'field' state object(s) looked
22448 * out for matching nodes to create a key-sequence for this
22449 * target node. Now we are back to this target node and need
22450 * to put the key-sequence, together with the target node
22451 * itself, into the node-table of the corresponding IDC
22452 * binding.
22453 */
22454 matcher = sto->matcher;
22455 idc = matcher->aidc->def;
22456 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022457 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022458 /*
22459 * Check if the matcher has any key-sequences at all, plus
22460 * if it has a key-sequence for the current target node.
22461 */
22462 if ((matcher->keySeqs == NULL) ||
22463 (matcher->sizeKeySeqs <= pos)) {
22464 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22465 goto selector_key_error;
22466 else
22467 goto selector_leave;
22468 }
22469
22470 keySeq = &(matcher->keySeqs[pos]);
22471 if (*keySeq == NULL) {
22472 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22473 goto selector_key_error;
22474 else
22475 goto selector_leave;
22476 }
22477
22478 for (i = 0; i < nbKeys; i++) {
22479 if ((*keySeq)[i] == NULL) {
22480 /*
22481 * Not qualified, if not all fields did resolve.
22482 */
22483 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22484 /*
22485 * All fields of a "key" IDC must resolve.
22486 */
22487 goto selector_key_error;
22488 }
22489 goto selector_leave;
22490 }
22491 }
22492 /*
22493 * All fields did resolve.
22494 */
22495
22496 /*
22497 * 4.1 If the {identity-constraint category} is unique(/key),
22498 * then no two members of the ·qualified node set· have
22499 * ·key-sequences· whose members are pairwise equal, as
22500 * defined by Equal in [XML Schemas: Datatypes].
22501 *
22502 * Get the IDC binding from the matcher and check for
22503 * duplicate key-sequences.
22504 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022505#if 0
22506 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22507#endif
22508 targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022509 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022510 (targets->nbItems != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022511 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022512
22513 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022514 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022515 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022516 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022517 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022518 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022519 bkeySeq =
22520 ((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022521 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022522 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022523 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022524 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022525 if (res == -1) {
22526 return (-1);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022527 } else if (res == 0) {
22528 /*
22529 * One of the keys differs, so the key-sequence
22530 * won't be equal; get out.
22531 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022532 break;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022533 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022534 }
22535 if (res == 1) {
22536 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022537 * Duplicate key-sequence found.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022538 */
22539 break;
22540 }
22541 i++;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022542 } while (i < targets->nbItems);
22543 if (i != targets->nbItems) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022544 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022545 /*
22546 * TODO: Try to report the key-sequence.
22547 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022548 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022549 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022550 WXS_BASIC_CAST idc,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022551 "Duplicate key-sequence %s in %s",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022552 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022553 (*keySeq), nbKeys),
22554 xmlSchemaGetIDCDesignation(&strB, idc));
22555 FREE_AND_NULL(str);
22556 FREE_AND_NULL(strB);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022557 goto selector_leave;
22558 }
22559 }
22560 /*
22561 * Add a node-table item to the IDC binding.
22562 */
22563 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
22564 sizeof(xmlSchemaPSVIIDCNode));
22565 if (ntItem == NULL) {
22566 xmlSchemaVErrMemory(NULL,
22567 "allocating an IDC node-table item", NULL);
22568 xmlFree(*keySeq);
22569 *keySeq = NULL;
22570 return(-1);
22571 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022572 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022573
22574 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022575 * Store the node-table item in a global list.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022576 */
22577 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
22578 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
22579 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022580 xmlFree(*keySeq);
22581 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022582 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022583 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022584 ntItem->nodeQNameID = -1;
22585 } else {
22586 /*
22587 * Save a cached QName for this node on the IDC node, to be
22588 * able to report it, even if the node is not saved.
22589 */
22590 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
22591 vctxt->inode->localName, vctxt->inode->nsName);
22592 if (ntItem->nodeQNameID == -1) {
22593 xmlFree(ntItem);
22594 xmlFree(*keySeq);
22595 *keySeq = NULL;
22596 return (-1);
22597 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022598 }
22599 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022600 * Init the node-table item: Save the node, position and
22601 * consume the key-sequence.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022602 */
22603 ntItem->node = vctxt->node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022604 ntItem->nodeLine = vctxt->inode->nodeLine;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022605 ntItem->keys = *keySeq;
22606 *keySeq = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022607#if 0
22608 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
22609#endif
22610 if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022611 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
22612 /*
22613 * Free the item, since keyref items won't be
22614 * put on a global list.
22615 */
22616 xmlFree(ntItem->keys);
22617 xmlFree(ntItem);
22618 }
22619 return (-1);
22620 }
22621
22622 goto selector_leave;
22623selector_key_error:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022624 {
22625 xmlChar *str = NULL;
22626 /*
22627 * 4.2.1 (KEY) The ·target node set· and the
22628 * ·qualified node set· are equal, that is, every
22629 * member of the ·target node set· is also a member
22630 * of the ·qualified node set· and vice versa.
22631 */
22632 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22633 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022634 WXS_BASIC_CAST idc,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022635 "Not all fields of %s evaluate to a node",
22636 xmlSchemaGetIDCDesignation(&str, idc), NULL);
22637 FREE_AND_NULL(str);
22638 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022639selector_leave:
22640 /*
22641 * Free the key-sequence if not added to the IDC table.
22642 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022643 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022644 xmlFree(*keySeq);
22645 *keySeq = NULL;
22646 }
22647 } /* if selector */
22648
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022649 sto->nbHistory--;
22650
22651deregister_check:
22652 /*
22653 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022654 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022655 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022656#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022657 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
22658 sto->sel->xpath);
22659#endif
22660 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022661 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022662 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022663 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022664 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022665 nextsto = sto->next;
22666 /*
22667 * Unlink from the list of active XPath state objects.
22668 */
22669 vctxt->xpathStates = sto->next;
22670 sto->next = vctxt->xpathStatePool;
22671 /*
22672 * Link it to the pool of reusable state objects.
22673 */
22674 vctxt->xpathStatePool = sto;
22675 sto = nextsto;
22676 } else
22677 sto = sto->next;
22678 } /* while (sto != NULL) */
22679 return (0);
22680}
22681
22682/**
22683 * xmlSchemaIDCRegisterMatchers:
22684 * @vctxt: the WXS validation context
22685 * @elemDecl: the element declaration
22686 *
22687 * Creates helper objects to evaluate IDC selectors/fields
22688 * successively.
22689 *
22690 * Returns 0 if OK and -1 on internal errors.
22691 */
22692static int
22693xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
22694 xmlSchemaElementPtr elemDecl)
22695{
22696 xmlSchemaIDCMatcherPtr matcher, last = NULL;
22697 xmlSchemaIDCPtr idc, refIdc;
22698 xmlSchemaIDCAugPtr aidc;
22699
22700 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
22701 if (idc == NULL)
22702 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022703
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022704#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022705 {
22706 xmlChar *str = NULL;
22707 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022708 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022709 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22710 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022711 FREE_AND_NULL(str)
22712 }
22713#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022714 if (vctxt->inode->idcMatchers != NULL) {
22715 VERROR_INT("xmlSchemaIDCRegisterMatchers",
22716 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022717 return (-1);
22718 }
22719 do {
22720 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
22721 /*
22722 * Since IDCs bubbles are expensive we need to know the
22723 * depth at which the bubbles should stop; this will be
22724 * the depth of the top-most keyref IDC. If no keyref
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022725 * references a key/unique IDC, the keyrefDepth will
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022726 * be -1, indicating that no bubbles are needed.
22727 */
22728 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
22729 if (refIdc != NULL) {
22730 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022731 * Remember that we have keyrefs on this node.
22732 */
22733 vctxt->inode->hasKeyrefs = 1;
22734 /*
22735 * Lookup the referenced augmented IDC info.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022736 */
22737 aidc = vctxt->aidcs;
22738 while (aidc != NULL) {
22739 if (aidc->def == refIdc)
22740 break;
22741 aidc = aidc->next;
22742 }
22743 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022744 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022745 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022746 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022747 return (-1);
22748 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022749 if ((aidc->keyrefDepth == -1) ||
22750 (vctxt->depth < aidc->keyrefDepth))
22751 aidc->keyrefDepth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022752 }
22753 }
22754 /*
22755 * Lookup the augmented IDC item for the IDC definition.
22756 */
22757 aidc = vctxt->aidcs;
22758 while (aidc != NULL) {
22759 if (aidc->def == idc)
22760 break;
22761 aidc = aidc->next;
22762 }
22763 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022764 VERROR_INT("xmlSchemaIDCRegisterMatchers",
22765 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022766 return (-1);
22767 }
22768 /*
22769 * Create an IDC matcher for every IDC definition.
22770 */
22771 matcher = (xmlSchemaIDCMatcherPtr)
22772 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
22773 if (matcher == NULL) {
22774 xmlSchemaVErrMemory(vctxt,
22775 "allocating an IDC matcher", NULL);
22776 return (-1);
22777 }
22778 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
22779 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022780 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022781 else
22782 last->next = matcher;
22783 last = matcher;
22784
22785 matcher->type = IDC_MATCHER;
22786 matcher->depth = vctxt->depth;
22787 matcher->aidc = aidc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022788 matcher->idcType = aidc->def->type;
22789#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022790 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
22791#endif
22792 /*
22793 * Init the automaton state object.
22794 */
22795 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022796 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022797 return (-1);
22798
22799 idc = idc->next;
22800 } while (idc != NULL);
22801 return (0);
22802}
22803
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022804static int
22805xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
22806 xmlSchemaNodeInfoPtr ielem)
22807{
22808 xmlSchemaPSVIIDCBindingPtr bind;
22809 int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
22810 xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
22811 xmlSchemaPSVIIDCNodePtr *targets, *dupls;
22812
22813 xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
22814 /* vctxt->createIDCNodeTables */
22815 while (matcher != NULL) {
22816 /*
22817 * Skip keyref IDCs and empty IDC target-lists.
22818 */
22819 if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
22820 WXS_ILIST_IS_EMPTY(matcher->targets))
22821 {
22822 matcher = matcher->next;
22823 continue;
22824 }
22825 /*
22826 * If we _want_ the IDC node-table to be created in any case
22827 * then do so. Otherwise create them only if keyrefs need them.
22828 */
22829 if ((! vctxt->createIDCNodeTables) &&
22830 ((matcher->aidc->keyrefDepth == -1) ||
22831 (matcher->aidc->keyrefDepth > vctxt->depth)))
22832 {
22833 matcher = matcher->next;
22834 continue;
22835 }
22836 /*
22837 * Get/create the IDC binding on this element for the IDC definition.
22838 */
22839 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22840
22841 if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
22842 dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
22843 nbDupls = bind->dupls->nbItems;
22844 } else {
22845 dupls = NULL;
22846 nbDupls = 0;
22847 }
22848 if (bind->nodeTable != NULL) {
22849 nbNodeTable = bind->nbNodes;
22850 } else {
22851 nbNodeTable = 0;
22852 }
22853
22854 if ((nbNodeTable == 0) && (nbDupls == 0)) {
22855 /*
22856 * Transfer all IDC target-nodes to the IDC node-table.
22857 */
22858 bind->nodeTable =
22859 (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
22860 bind->sizeNodes = matcher->targets->sizeItems;
22861 bind->nbNodes = matcher->targets->nbItems;
22862
22863 matcher->targets->items = NULL;
22864 matcher->targets->sizeItems = 0;
22865 matcher->targets->nbItems = 0;
22866 } else {
22867 /*
22868 * Compare the key-sequences and add to the IDC node-table.
22869 */
22870 nbTargets = matcher->targets->nbItems;
22871 targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
22872 nbFields = matcher->aidc->def->nbFields;
22873 i = 0;
22874 do {
22875 keys = targets[i]->keys;
22876 if (nbDupls) {
22877 /*
22878 * Search in already found duplicates first.
22879 */
22880 j = 0;
22881 do {
22882 if (nbFields == 1) {
22883 res = xmlSchemaAreValuesEqual(keys[0]->val,
22884 dupls[j]->keys[0]->val);
22885 if (res == -1)
22886 goto internal_error;
22887 if (res == 1) {
22888 /*
22889 * Equal key-sequence.
22890 */
22891 goto next_target;
22892 }
22893 } else {
22894 res = 0;
22895 ntkeys = dupls[j]->keys;
22896 for (k = 0; k < nbFields; k++) {
22897 res = xmlSchemaAreValuesEqual(keys[k]->val,
22898 ntkeys[k]->val);
22899 if (res == -1)
22900 goto internal_error;
22901 if (res == 0) {
22902 /*
22903 * One of the keys differs.
22904 */
22905 break;
22906 }
22907 }
22908 if (res == 1) {
22909 /*
22910 * Equal key-sequence found.
22911 */
22912 goto next_target;
22913 }
22914 }
22915 j++;
22916 } while (j < nbDupls);
22917 }
22918 if (nbNodeTable) {
22919 j = 0;
22920 do {
22921 if (nbFields == 1) {
22922 res = xmlSchemaAreValuesEqual(keys[0]->val,
22923 bind->nodeTable[j]->keys[0]->val);
22924 if (res == -1)
22925 goto internal_error;
22926 if (res == 0) {
22927 /*
22928 * The key-sequence differs.
22929 */
22930 goto next_node_table_entry;
22931 }
22932 } else {
22933 res = 0;
22934 ntkeys = bind->nodeTable[j]->keys;
22935 for (k = 0; k < nbFields; k++) {
22936 res = xmlSchemaAreValuesEqual(keys[k]->val,
22937 ntkeys[k]->val);
22938 if (res == -1)
22939 goto internal_error;
22940 if (res == 0) {
22941 /*
22942 * One of the keys differs.
22943 */
22944 goto next_node_table_entry;
22945 }
22946 }
22947 }
22948 /*
22949 * Add the duplicate to the list of duplicates.
22950 */
22951 if (bind->dupls == NULL) {
22952 bind->dupls = xmlSchemaItemListCreate();
22953 if (bind->dupls == NULL)
22954 goto internal_error;
22955 }
22956 if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
22957 goto internal_error;
22958 /*
22959 * Remove the duplicate entry from the IDC node-table.
22960 */
22961 bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
22962 bind->nbNodes--;
22963
22964 goto next_target;
22965
22966next_node_table_entry:
22967 j++;
22968 } while (j < nbNodeTable);
22969 }
22970 /*
22971 * If everything is fine, then add the IDC target-node to
22972 * the IDC node-table.
22973 */
22974 if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
22975 goto internal_error;
22976
22977next_target:
22978 i++;
22979 } while (i < nbTargets);
22980 }
22981 matcher = matcher->next;
22982 }
22983 return(0);
22984
22985internal_error:
22986 return(-1);
22987}
22988
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022989/**
22990 * xmlSchemaBubbleIDCNodeTables:
22991 * @depth: the current tree depth
22992 *
22993 * Merges IDC bindings of an element at @depth into the corresponding IDC
22994 * bindings of its parent element. If a duplicate note-table entry is found,
22995 * both, the parent node-table entry and child entry are discarded from the
22996 * node-table of the parent.
22997 *
22998 * Returns 0 if OK and -1 on internal errors.
22999 */
23000static int
23001xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23002{
23003 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023004 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23005 xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023006 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023007 int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023008
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023009 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023010 if (bind == NULL) {
23011 /* Fine, no table, no bubbles. */
23012 return (0);
23013 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000023014
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023015 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23016 /*
23017 * Walk all bindings; create new or add to existing bindings.
23018 * Remove duplicate key-sequences.
23019 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023020 while (bind != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023021
23022 if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23023 goto next_binding;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023024 /*
23025 * Check if the key/unique IDC table needs to be bubbled.
23026 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023027 if (! vctxt->createIDCNodeTables) {
23028 aidc = vctxt->aidcs;
23029 do {
23030 if (aidc->def == bind->definition) {
23031 if ((aidc->keyrefDepth == -1) ||
23032 (aidc->keyrefDepth >= vctxt->depth)) {
23033 goto next_binding;
23034 }
23035 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023036 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023037 aidc = aidc->next;
23038 } while (aidc != NULL);
23039 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023040
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023041 if (parTable != NULL)
23042 parBind = *parTable;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023043 /*
23044 * Search a matching parent binding for the
23045 * IDC definition.
23046 */
23047 while (parBind != NULL) {
23048 if (parBind->definition == bind->definition)
23049 break;
23050 parBind = parBind->next;
23051 }
23052
23053 if (parBind != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023054 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023055 * Compare every node-table entry of the child node,
23056 * i.e. the key-sequence within, ...
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023057 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023058 oldNum = parBind->nbNodes; /* Skip newly added items. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023059
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023060 if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23061 oldDupls = parBind->dupls->nbItems;
23062 dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23063 } else {
23064 dupls = NULL;
23065 oldDupls = 0;
23066 }
23067
23068 parNodes = parBind->nodeTable;
23069 nbFields = bind->definition->nbFields;
23070
23071 for (i = 0; i < bind->nbNodes; i++) {
23072 node = bind->nodeTable[i];
23073 if (node == NULL)
23074 continue;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023075 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023076 * ...with every key-sequence of the parent node, already
23077 * evaluated to be a duplicate key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023078 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023079 if (oldDupls) {
23080 j = 0;
23081 while (j < oldDupls) {
23082 if (nbFields == 1) {
23083 ret = xmlSchemaAreValuesEqual(
23084 node->keys[0]->val,
23085 dupls[j]->keys[0]->val);
23086 if (ret == -1)
23087 goto internal_error;
23088 if (ret == 0) {
23089 j++;
23090 continue;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023091 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023092 } else {
23093 parNode = dupls[j];
23094 for (k = 0; k < nbFields; k++) {
23095 ret = xmlSchemaAreValuesEqual(
23096 node->keys[k]->val,
23097 parNode->keys[k]->val);
23098 if (ret == -1)
23099 goto internal_error;
23100 if (ret == 0)
23101 break;
23102 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023103 }
23104 if (ret == 1)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023105 /* Duplicate found. */
23106 break;
23107 j++;
23108 }
23109 if (j != oldDupls) {
23110 /* Duplicate found. Skip this entry. */
23111 continue;
23112 }
23113 }
23114 /*
23115 * ... and with every key-sequence of the parent node.
23116 */
23117 if (oldNum) {
23118 j = 0;
23119 while (j < oldNum) {
23120 if (nbFields == 1) {
23121 ret = xmlSchemaAreValuesEqual(
23122 node->keys[0]->val,
23123 parNodes[j]->keys[0]->val);
23124 if (ret == -1)
23125 goto internal_error;
23126 if (ret == 0) {
23127 j++;
23128 continue;
23129 }
23130 } else {
23131 parNode = parNodes[j];
23132 for (k = 0; k < nbFields; k++) {
23133 ret = xmlSchemaAreValuesEqual(
23134 node->keys[k]->val,
23135 parNode->keys[k]->val);
23136 if (ret == -1)
23137 goto internal_error;
23138 if (ret == 0)
23139 break;
23140 }
23141 }
23142 if (ret == 1)
23143 /* Duplicate found. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023144 break;
23145 j++;
23146 }
23147 if (j != oldNum) {
23148 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023149 * Handle duplicates. Move the duplicate in
23150 * the parent's node-table to the list of
23151 * duplicates.
23152 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023153 oldNum--;
23154 parBind->nbNodes--;
23155 /*
23156 * Move last old item to pos of duplicate.
23157 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023158 parNodes[j] = parNodes[oldNum];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023159
23160 if (parBind->nbNodes != oldNum) {
23161 /*
23162 * If new items exist, move last new item to
23163 * last of old items.
23164 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023165 parNodes[oldNum] =
23166 parNodes[parBind->nbNodes];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023167 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023168 if (parBind->dupls == NULL) {
23169 parBind->dupls = xmlSchemaItemListCreate();
23170 if (parBind->dupls == NULL)
23171 goto internal_error;
23172 }
23173 xmlSchemaItemListAdd(parBind->dupls, parNode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023174 } else {
23175 /*
23176 * Add the node-table entry (node and key-sequence) of
23177 * the child node to the node table of the parent node.
23178 */
23179 if (parBind->nodeTable == NULL) {
23180 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000023181 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023182 if (parBind->nodeTable == NULL) {
23183 xmlSchemaVErrMemory(NULL,
23184 "allocating IDC list of node-table items", NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023185 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023186 }
23187 parBind->sizeNodes = 1;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023188 } else if (parBind->nbNodes >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000023189 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023190 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23191 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23192 sizeof(xmlSchemaPSVIIDCNodePtr));
23193 if (parBind->nodeTable == NULL) {
23194 xmlSchemaVErrMemory(NULL,
23195 "re-allocating IDC list of node-table items", NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023196 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023197 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023198 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023199 /*
23200 * Append the new node-table entry to the 'new node-table
23201 * entries' section.
23202 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023203 parBind->nodeTable[parBind->nbNodes++] = node;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023204 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023205
23206 }
23207
23208 }
23209 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023210 /*
23211 * No binding for the IDC was found: create a new one and
23212 * copy all node-tables.
23213 */
23214 parBind = xmlSchemaIDCNewBinding(bind->definition);
23215 if (parBind == NULL)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023216 goto internal_error;
23217
23218 /*
23219 * TODO: Hmm, how to optimize the initial number of
23220 * allocated entries?
23221 */
23222 if (bind->nbNodes != 0) {
23223 /*
23224 * Add all IDC node-table entries.
23225 */
23226 if (! vctxt->psviExposeIDCNodeTables) {
23227 /*
23228 * Just move the entries.
23229 * NOTE: this is quite save here, since
23230 * all the keyref lookups have already been
23231 * performed.
23232 */
23233 parBind->nodeTable = bind->nodeTable;
23234 bind->nodeTable = NULL;
23235 parBind->sizeNodes = bind->sizeNodes;
23236 bind->sizeNodes = 0;
23237 parBind->nbNodes = bind->nbNodes;
23238 bind->nbNodes = 0;
23239 } else {
23240 /*
23241 * Copy the entries.
23242 */
23243 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23244 xmlMalloc(bind->nbNodes *
23245 sizeof(xmlSchemaPSVIIDCNodePtr));
23246 if (parBind->nodeTable == NULL) {
23247 xmlSchemaVErrMemory(NULL,
23248 "allocating an array of IDC node-table "
23249 "items", NULL);
23250 xmlSchemaIDCFreeBinding(parBind);
23251 goto internal_error;
23252 }
23253 parBind->sizeNodes = bind->nbNodes;
23254 parBind->nbNodes = bind->nbNodes;
23255 memcpy(parBind->nodeTable, bind->nodeTable,
23256 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23257 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023258 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023259 if (bind->dupls) {
23260 /*
23261 * Move the duplicates.
23262 */
23263 if (parBind->dupls != NULL)
23264 xmlSchemaItemListFree(parBind->dupls);
23265 parBind->dupls = bind->dupls;
23266 bind->dupls = NULL;
23267 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023268 if (*parTable == NULL)
23269 *parTable = parBind;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023270 else {
23271 parBind->next = *parTable;
23272 *parTable = parBind;
23273 }
23274 }
23275
23276next_binding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023277 bind = bind->next;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023278 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023279 return (0);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023280
23281internal_error:
23282 return(-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023283}
23284
23285/**
23286 * xmlSchemaCheckCVCIDCKeyRef:
23287 * @vctxt: the WXS validation context
23288 * @elemDecl: the element declaration
23289 *
23290 * Check the cvc-idc-keyref constraints.
23291 */
23292static int
23293xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23294{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023295 xmlSchemaIDCMatcherPtr matcher;
23296 xmlSchemaPSVIIDCBindingPtr bind;
23297
23298 matcher = vctxt->inode->idcMatchers;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023299 /*
23300 * Find a keyref.
23301 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023302 while (matcher != NULL) {
23303 if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23304 matcher->targets &&
23305 matcher->targets->nbItems)
23306 {
23307 int i, j, k, res, nbFields, hasDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023308 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023309 xmlSchemaPSVIIDCNodePtr refNode = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023310
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023311 nbFields = matcher->aidc->def->nbFields;
23312
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023313 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023314 * Find the IDC node-table for the referenced IDC key/unique.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023315 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023316 bind = vctxt->inode->idcTable;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023317 while (bind != NULL) {
23318 if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023319 bind->definition)
23320 break;
23321 bind = bind->next;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023322 }
23323 hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023324 /*
23325 * Search for a matching key-sequences.
23326 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023327 for (i = 0; i < matcher->targets->nbItems; i++) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023328 res = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023329 refNode = matcher->targets->items[i];
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023330 if (bind != NULL) {
23331 refKeys = refNode->keys;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023332 for (j = 0; j < bind->nbNodes; j++) {
23333 keys = bind->nodeTable[j]->keys;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023334 for (k = 0; k < nbFields; k++) {
23335 res = xmlSchemaAreValuesEqual(keys[k]->val,
23336 refKeys[k]->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023337 if (res == 0)
23338 break;
23339 else if (res == -1) {
23340 return (-1);
23341 }
23342 }
23343 if (res == 1) {
23344 /*
23345 * Match found.
23346 */
23347 break;
23348 }
23349 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023350 if ((res == 0) && hasDupls) {
23351 /*
23352 * Search in duplicates
23353 */
23354 for (j = 0; j < bind->dupls->nbItems; j++) {
23355 keys = ((xmlSchemaPSVIIDCNodePtr)
23356 bind->dupls->items[j])->keys;
23357 for (k = 0; k < nbFields; k++) {
23358 res = xmlSchemaAreValuesEqual(keys[k]->val,
23359 refKeys[k]->val);
23360 if (res == 0)
23361 break;
23362 else if (res == -1) {
23363 return (-1);
23364 }
23365 }
23366 if (res == 1) {
23367 /*
23368 * Match in duplicates found.
23369 */
23370 xmlChar *str = NULL, *strB = NULL;
23371 xmlSchemaKeyrefErr(vctxt,
23372 XML_SCHEMAV_CVC_IDC, refNode,
23373 (xmlSchemaTypePtr) matcher->aidc->def,
23374 "More than one match found for "
23375 "key-sequence %s of keyref '%s'",
23376 xmlSchemaFormatIDCKeySequence(vctxt, &str,
23377 refNode->keys, nbFields),
23378 xmlSchemaGetComponentQName(&strB,
23379 matcher->aidc->def));
23380 FREE_AND_NULL(str);
23381 FREE_AND_NULL(strB);
23382 break;
23383 }
23384 }
23385 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023386 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023387
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023388 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023389 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023390 xmlSchemaKeyrefErr(vctxt,
23391 XML_SCHEMAV_CVC_IDC, refNode,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023392 (xmlSchemaTypePtr) matcher->aidc->def,
23393 "No match found for key-sequence %s of keyref '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000023394 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023395 refNode->keys, nbFields),
23396 xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023397 FREE_AND_NULL(str);
23398 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023399 }
23400 }
23401 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023402 matcher = matcher->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023403 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023404 /* TODO: Return an error if any error encountered. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023405 return (0);
23406}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023407
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023408/************************************************************************
23409 * *
23410 * XML Reader validation code *
23411 * *
23412 ************************************************************************/
23413
23414static xmlSchemaAttrInfoPtr
23415xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023416{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023417 xmlSchemaAttrInfoPtr iattr;
23418 /*
23419 * Grow/create list of attribute infos.
23420 */
23421 if (vctxt->attrInfos == NULL) {
23422 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23423 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23424 vctxt->sizeAttrInfos = 1;
23425 if (vctxt->attrInfos == NULL) {
23426 xmlSchemaVErrMemory(vctxt,
23427 "allocating attribute info list", NULL);
23428 return (NULL);
23429 }
23430 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23431 vctxt->sizeAttrInfos++;
23432 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23433 xmlRealloc(vctxt->attrInfos,
23434 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23435 if (vctxt->attrInfos == NULL) {
23436 xmlSchemaVErrMemory(vctxt,
23437 "re-allocating attribute info list", NULL);
23438 return (NULL);
23439 }
23440 } else {
23441 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23442 if (iattr->localName != NULL) {
23443 VERROR_INT("xmlSchemaGetFreshAttrInfo",
23444 "attr info not cleared");
23445 return (NULL);
23446 }
23447 iattr->nodeType = XML_ATTRIBUTE_NODE;
23448 return (iattr);
23449 }
23450 /*
23451 * Create an attribute info.
23452 */
23453 iattr = (xmlSchemaAttrInfoPtr)
23454 xmlMalloc(sizeof(xmlSchemaAttrInfo));
23455 if (iattr == NULL) {
23456 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23457 return (NULL);
23458 }
23459 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23460 iattr->nodeType = XML_ATTRIBUTE_NODE;
23461 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23462
23463 return (iattr);
23464}
23465
23466static int
23467xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23468 xmlNodePtr attrNode,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023469 int nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023470 const xmlChar *localName,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023471 const xmlChar *nsName,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023472 int ownedNames,
23473 xmlChar *value,
23474 int ownedValue)
23475{
23476 xmlSchemaAttrInfoPtr attr;
23477
23478 attr = xmlSchemaGetFreshAttrInfo(vctxt);
23479 if (attr == NULL) {
23480 VERROR_INT("xmlSchemaPushAttribute",
23481 "calling xmlSchemaGetFreshAttrInfo()");
23482 return (-1);
23483 }
23484 attr->node = attrNode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023485 attr->nodeLine = nodeLine;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023486 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23487 attr->localName = localName;
23488 attr->nsName = nsName;
23489 if (ownedNames)
23490 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23491 /*
23492 * Evaluate if it's an XSI attribute.
23493 */
23494 if (nsName != NULL) {
23495 if (xmlStrEqual(localName, BAD_CAST "nil")) {
23496 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23497 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23498 }
23499 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
23500 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23501 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23502 }
23503 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23504 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23505 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23506 }
23507 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23508 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23509 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23510 }
23511 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
23512 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
23513 }
23514 }
23515 attr->value = value;
23516 if (ownedValue)
23517 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23518 if (attr->metaType != 0)
23519 attr->state = XML_SCHEMAS_ATTR_META;
23520 return (0);
23521}
23522
23523static void
23524xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
23525{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023526 ielem->hasKeyrefs = 0;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000023527 ielem->appliedXPath = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023528 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
23529 FREE_AND_NULL(ielem->localName);
23530 FREE_AND_NULL(ielem->nsName);
23531 } else {
23532 ielem->localName = NULL;
23533 ielem->nsName = NULL;
23534 }
23535 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
23536 FREE_AND_NULL(ielem->value);
23537 } else {
23538 ielem->value = NULL;
23539 }
23540 if (ielem->val != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023541 /*
23542 * PSVI TODO: Be careful not to free it when the value is
23543 * exposed via PSVI.
23544 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023545 xmlSchemaFreeValue(ielem->val);
23546 ielem->val = NULL;
23547 }
23548 if (ielem->idcMatchers != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023549 /*
23550 * URGENT OPTIMIZE TODO: Use a pool of IDC matchers.
23551 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023552 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
23553 ielem->idcMatchers = NULL;
23554 }
23555 if (ielem->idcTable != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023556 /*
23557 * OPTIMIZE TODO: Use a pool of IDC tables??.
23558 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023559 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
23560 ielem->idcTable = NULL;
23561 }
23562 if (ielem->regexCtxt != NULL) {
23563 xmlRegFreeExecCtxt(ielem->regexCtxt);
23564 ielem->regexCtxt = NULL;
23565 }
23566 if (ielem->nsBindings != NULL) {
23567 xmlFree((xmlChar **)ielem->nsBindings);
23568 ielem->nsBindings = NULL;
23569 ielem->nbNsBindings = 0;
23570 ielem->sizeNsBindings = 0;
23571 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023572}
23573
23574/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023575 * xmlSchemaGetFreshElemInfo:
23576 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023577 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023578 * Creates/reuses and initializes the element info item for
23579 * the currect tree depth.
23580 *
23581 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023582 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023583static xmlSchemaNodeInfoPtr
23584xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023585{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023586 xmlSchemaNodeInfoPtr info = NULL;
23587
23588 if (vctxt->depth > vctxt->sizeElemInfos) {
23589 VERROR_INT("xmlSchemaGetFreshElemInfo",
23590 "inconsistent depth encountered");
23591 return (NULL);
23592 }
23593 if (vctxt->elemInfos == NULL) {
23594 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
23595 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
23596 if (vctxt->elemInfos == NULL) {
23597 xmlSchemaVErrMemory(vctxt,
23598 "allocating the element info array", NULL);
23599 return (NULL);
23600 }
23601 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
23602 vctxt->sizeElemInfos = 10;
23603 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
23604 int i = vctxt->sizeElemInfos;
23605
23606 vctxt->sizeElemInfos *= 2;
23607 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
23608 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
23609 sizeof(xmlSchemaNodeInfoPtr));
23610 if (vctxt->elemInfos == NULL) {
23611 xmlSchemaVErrMemory(vctxt,
23612 "re-allocating the element info array", NULL);
23613 return (NULL);
23614 }
23615 /*
23616 * We need the new memory to be NULLed.
23617 * TODO: Use memset instead?
23618 */
23619 for (; i < vctxt->sizeElemInfos; i++)
23620 vctxt->elemInfos[i] = NULL;
23621 } else
23622 info = vctxt->elemInfos[vctxt->depth];
23623
23624 if (info == NULL) {
23625 info = (xmlSchemaNodeInfoPtr)
23626 xmlMalloc(sizeof(xmlSchemaNodeInfo));
23627 if (info == NULL) {
23628 xmlSchemaVErrMemory(vctxt,
23629 "allocating an element info", NULL);
23630 return (NULL);
23631 }
23632 vctxt->elemInfos[vctxt->depth] = info;
23633 } else {
23634 if (info->localName != NULL) {
23635 VERROR_INT("xmlSchemaGetFreshElemInfo",
23636 "elem info has not been cleared");
23637 return (NULL);
23638 }
23639 }
23640 memset(info, 0, sizeof(xmlSchemaNodeInfo));
23641 info->nodeType = XML_ELEMENT_NODE;
23642 info->depth = vctxt->depth;
23643
23644 return (info);
23645}
23646
23647#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
23648#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
23649#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
23650
23651static int
23652xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
23653 xmlNodePtr node,
23654 xmlSchemaTypePtr type,
23655 xmlSchemaValType valType,
23656 const xmlChar * value,
23657 xmlSchemaValPtr val,
23658 unsigned long length,
23659 int fireErrors)
23660{
23661 int ret, error = 0;
23662
23663 xmlSchemaTypePtr tmpType;
23664 xmlSchemaFacetLinkPtr facetLink;
23665 xmlSchemaFacetPtr facet;
23666 unsigned long len = 0;
23667 xmlSchemaWhitespaceValueType ws;
23668
23669 /*
23670 * In Libxml2, derived built-in types have currently no explicit facets.
23671 */
23672 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023673 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023674
23675 /*
23676 * NOTE: Do not jump away, if the facetSet of the given type is
23677 * empty: until now, "pattern" and "enumeration" facets of the
23678 * *base types* need to be checked as well.
23679 */
23680 if (type->facetSet == NULL)
23681 goto pattern_and_enum;
23682
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023683 if (! WXS_IS_ATOMIC(type)) {
23684 if (WXS_IS_LIST(type))
23685 goto WXS_IS_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023686 else
23687 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023688 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023689 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023690 * Whitespace handling is only of importance for string-based
23691 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023692 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023693 tmpType = xmlSchemaGetPrimitiveType(type);
23694 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023695 WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023696 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
23697 } else
23698 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
23699 /*
23700 * If the value was not computed (for string or
23701 * anySimpleType based types), then use the provided
23702 * type.
23703 */
23704 if (val == NULL)
23705 valType = valType;
23706 else
23707 valType = xmlSchemaGetValType(val);
23708
23709 ret = 0;
23710 for (facetLink = type->facetSet; facetLink != NULL;
23711 facetLink = facetLink->next) {
23712 /*
23713 * Skip the pattern "whiteSpace": it is used to
23714 * format the character content beforehand.
23715 */
23716 switch (facetLink->facet->type) {
23717 case XML_SCHEMA_FACET_WHITESPACE:
23718 case XML_SCHEMA_FACET_PATTERN:
23719 case XML_SCHEMA_FACET_ENUMERATION:
23720 continue;
23721 case XML_SCHEMA_FACET_LENGTH:
23722 case XML_SCHEMA_FACET_MINLENGTH:
23723 case XML_SCHEMA_FACET_MAXLENGTH:
23724 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
23725 valType, value, val, &len, ws);
23726 break;
23727 default:
23728 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
23729 valType, value, val, ws);
23730 break;
23731 }
23732 if (ret < 0) {
23733 AERROR_INT("xmlSchemaValidateFacets",
23734 "validating against a atomic type facet");
23735 return (-1);
23736 } else if (ret > 0) {
23737 if (fireErrors)
23738 xmlSchemaFacetErr(actxt, ret, node,
23739 value, len, type, facetLink->facet, NULL, NULL, NULL);
23740 else
23741 return (ret);
23742 if (error == 0)
23743 error = ret;
23744 }
23745 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023746 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023747
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023748WXS_IS_LIST:
23749 if (! WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023750 goto pattern_and_enum;
23751 /*
23752 * "length", "minLength" and "maxLength" of list types.
23753 */
23754 ret = 0;
23755 for (facetLink = type->facetSet; facetLink != NULL;
23756 facetLink = facetLink->next) {
23757
23758 switch (facetLink->facet->type) {
23759 case XML_SCHEMA_FACET_LENGTH:
23760 case XML_SCHEMA_FACET_MINLENGTH:
23761 case XML_SCHEMA_FACET_MAXLENGTH:
23762 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
23763 value, length, NULL);
23764 break;
23765 default:
23766 continue;
23767 }
23768 if (ret < 0) {
23769 AERROR_INT("xmlSchemaValidateFacets",
23770 "validating against a list type facet");
23771 return (-1);
23772 } else if (ret > 0) {
23773 if (fireErrors)
23774 xmlSchemaFacetErr(actxt, ret, node,
23775 value, length, type, facetLink->facet, NULL, NULL, NULL);
23776 else
23777 return (ret);
23778 if (error == 0)
23779 error = ret;
23780 }
23781 ret = 0;
23782 }
23783
23784pattern_and_enum:
23785 if (error >= 0) {
23786 int found = 0;
23787 /*
23788 * Process enumerations. Facet values are in the value space
23789 * of the defining type's base type. This seems to be a bug in the
23790 * XML Schema 1.0 spec. Use the whitespace type of the base type.
23791 * Only the first set of enumerations in the ancestor-or-self axis
23792 * is used for validation.
23793 */
23794 ret = 0;
23795 tmpType = type;
23796 do {
23797 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
23798 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
23799 continue;
23800 found = 1;
23801 ret = xmlSchemaAreValuesEqual(facet->val, val);
23802 if (ret == 1)
23803 break;
23804 else if (ret < 0) {
23805 AERROR_INT("xmlSchemaValidateFacets",
23806 "validating against an enumeration facet");
23807 return (-1);
23808 }
23809 }
23810 if (ret != 0)
23811 break;
23812 tmpType = tmpType->baseType;
23813 } while ((tmpType != NULL) &&
23814 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
23815 if (found && (ret == 0)) {
23816 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
23817 if (fireErrors) {
23818 xmlSchemaFacetErr(actxt, ret, node,
23819 value, 0, type, NULL, NULL, NULL, NULL);
23820 } else
23821 return (ret);
23822 if (error == 0)
23823 error = ret;
23824 }
23825 }
23826
23827 if (error >= 0) {
23828 int found;
23829 /*
23830 * Process patters. Pattern facets are ORed at type level
23831 * and ANDed if derived. Walk the base type axis.
23832 */
23833 tmpType = type;
23834 facet = NULL;
23835 do {
23836 found = 0;
23837 for (facetLink = tmpType->facetSet; facetLink != NULL;
23838 facetLink = facetLink->next) {
23839 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
23840 continue;
23841 found = 1;
23842 /*
23843 * NOTE that for patterns, @value needs to be the
23844 * normalized vaule.
23845 */
23846 ret = xmlRegexpExec(facetLink->facet->regexp, value);
23847 if (ret == 1)
23848 break;
23849 else if (ret < 0) {
23850 AERROR_INT("xmlSchemaValidateFacets",
23851 "validating against a pattern facet");
23852 return (-1);
23853 } else {
23854 /*
23855 * Save the last non-validating facet.
23856 */
23857 facet = facetLink->facet;
23858 }
23859 }
23860 if (found && (ret != 1)) {
23861 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
23862 if (fireErrors) {
23863 xmlSchemaFacetErr(actxt, ret, node,
23864 value, 0, type, facet, NULL, NULL, NULL);
23865 } else
23866 return (ret);
23867 if (error == 0)
23868 error = ret;
23869 break;
23870 }
23871 tmpType = tmpType->baseType;
23872 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
23873 }
23874
23875 return (error);
23876}
23877
23878static xmlChar *
23879xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
23880 const xmlChar *value)
23881{
23882 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
23883 case XML_SCHEMA_WHITESPACE_COLLAPSE:
23884 return (xmlSchemaCollapseString(value));
23885 case XML_SCHEMA_WHITESPACE_REPLACE:
23886 return (xmlSchemaWhiteSpaceReplace(value));
23887 default:
23888 return (NULL);
23889 }
23890}
23891
23892static int
23893xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
23894 const xmlChar *value,
23895 xmlSchemaValPtr *val,
23896 int valNeeded)
23897{
23898 int ret;
23899 const xmlChar *nsName;
23900 xmlChar *local, *prefix = NULL;
23901
23902 ret = xmlValidateQName(value, 1);
23903 if (ret != 0) {
23904 if (ret == -1) {
23905 VERROR_INT("xmlSchemaValidateQName",
23906 "calling xmlValidateQName()");
23907 return (-1);
23908 }
23909 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
23910 }
23911 /*
23912 * NOTE: xmlSplitQName2 will always return a duplicated
23913 * strings.
23914 */
23915 local = xmlSplitQName2(value, &prefix);
23916 if (local == NULL)
23917 local = xmlStrdup(value);
23918 /*
23919 * OPTIMIZE TODO: Use flags for:
23920 * - is there any namespace binding?
23921 * - is there a default namespace?
23922 */
23923 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
23924
23925 if (prefix != NULL) {
23926 xmlFree(prefix);
23927 /*
23928 * A namespace must be found if the prefix is
23929 * NOT NULL.
23930 */
23931 if (nsName == NULL) {
23932 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023933 xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023934 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023935 "The QName value '%s' has no "
23936 "corresponding namespace declaration in "
23937 "scope", value, NULL);
23938 if (local != NULL)
23939 xmlFree(local);
23940 return (ret);
23941 }
23942 }
23943 if (valNeeded && val) {
23944 if (nsName != NULL)
23945 *val = xmlSchemaNewQNameValue(
23946 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
23947 else
23948 *val = xmlSchemaNewQNameValue(NULL,
23949 BAD_CAST local);
23950 } else
23951 xmlFree(local);
23952 return (0);
23953}
23954
23955/*
23956* cvc-simple-type
23957*/
23958static int
23959xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
23960 xmlNodePtr node,
23961 xmlSchemaTypePtr type,
23962 const xmlChar *value,
23963 xmlSchemaValPtr *retVal,
23964 int fireErrors,
23965 int normalize,
23966 int isNormalized)
23967{
23968 int ret = 0, valNeeded = (retVal) ? 1 : 0;
23969 xmlSchemaValPtr val = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023970 /* xmlSchemaWhitespaceValueType ws; */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023971 xmlChar *normValue = NULL;
23972
23973#define NORMALIZE(atype) \
23974 if ((! isNormalized) && \
23975 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
23976 normValue = xmlSchemaNormalizeValue(atype, value); \
23977 if (normValue != NULL) \
23978 value = normValue; \
23979 isNormalized = 1; \
23980 }
23981
23982 if ((retVal != NULL) && (*retVal != NULL)) {
23983 xmlSchemaFreeValue(*retVal);
23984 *retVal = NULL;
23985 }
23986 /*
23987 * 3.14.4 Simple Type Definition Validation Rules
23988 * Validation Rule: String Valid
23989 */
23990 /*
23991 * 1 It is schema-valid with respect to that definition as defined
23992 * by Datatype Valid in [XML Schemas: Datatypes].
23993 */
23994 /*
23995 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
23996 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
23997 * the string must be a ·declared entity name·.
23998 */
23999 /*
24000 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24001 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
24002 * then every whitespace-delimited substring of the string must be a ·declared
24003 * entity name·.
24004 */
24005 /*
24006 * 2.3 otherwise no further condition applies.
24007 */
24008 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24009 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000024010 if (value == NULL)
24011 value = BAD_CAST "";
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024012 if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024013 xmlSchemaTypePtr biType; /* The built-in type. */
24014 /*
24015 * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match·
24016 * a literal in the ·lexical space· of {base type definition}"
24017 */
24018 /*
24019 * Whitespace-normalize.
24020 */
24021 NORMALIZE(type);
24022 if (type->type != XML_SCHEMA_TYPE_BASIC) {
24023 /*
24024 * Get the built-in type.
24025 */
24026 biType = type->baseType;
24027 while ((biType != NULL) &&
24028 (biType->type != XML_SCHEMA_TYPE_BASIC))
24029 biType = biType->baseType;
24030
24031 if (biType == NULL) {
24032 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24033 "could not get the built-in type");
24034 goto internal_error;
24035 }
24036 } else
24037 biType = type;
24038 /*
24039 * NOTATIONs need to be processed here, since they need
24040 * to lookup in the hashtable of NOTATION declarations of the schema.
24041 */
24042 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24043 switch (biType->builtInType) {
24044 case XML_SCHEMAS_NOTATION:
24045 ret = xmlSchemaValidateNotation(
24046 (xmlSchemaValidCtxtPtr) actxt,
24047 ((xmlSchemaValidCtxtPtr) actxt)->schema,
24048 NULL, value, &val, valNeeded);
24049 break;
24050 case XML_SCHEMAS_QNAME:
24051 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24052 value, &val, valNeeded);
24053 break;
24054 default:
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024055 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024056 if (valNeeded)
24057 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24058 value, &val, NULL);
24059 else
24060 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24061 value, NULL, NULL);
24062 break;
24063 }
24064 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24065 switch (biType->builtInType) {
24066 case XML_SCHEMAS_NOTATION:
24067 ret = xmlSchemaValidateNotation(NULL,
24068 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24069 value, &val, valNeeded);
24070 break;
24071 default:
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024072 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024073 if (valNeeded)
24074 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24075 value, &val, node);
24076 else
24077 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24078 value, NULL, node);
24079 break;
24080 }
24081 } else {
24082 /*
24083 * Validation via a public API is not implemented yet.
24084 */
24085 TODO
24086 goto internal_error;
24087 }
24088 if (ret != 0) {
24089 if (ret < 0) {
24090 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24091 "validating against a built-in type");
24092 goto internal_error;
24093 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024094 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024095 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24096 else
24097 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24098 }
24099 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24100 /*
24101 * Check facets.
24102 */
24103 ret = xmlSchemaValidateFacets(actxt, node, type,
24104 (xmlSchemaValType) biType->builtInType, value, val,
24105 0, fireErrors);
24106 if (ret != 0) {
24107 if (ret < 0) {
24108 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24109 "validating facets of atomic simple type");
24110 goto internal_error;
24111 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024112 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024113 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24114 else
24115 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24116 }
24117 }
24118 if (fireErrors && (ret > 0))
24119 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024120 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024121
24122 xmlSchemaTypePtr itemType;
24123 const xmlChar *cur, *end;
24124 xmlChar *tmpValue = NULL;
24125 unsigned long len = 0;
24126 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24127 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
24128 * of white space separated tokens, each of which ·match·es a literal
24129 * in the ·lexical space· of {item type definition}
24130 */
24131 /*
24132 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24133 * the list type has an enum or pattern facet.
24134 */
24135 NORMALIZE(type);
24136 /*
24137 * VAL TODO: Optimize validation of empty values.
24138 * VAL TODO: We do not have computed values for lists.
24139 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024140 itemType = WXS_LIST_ITEMTYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024141 cur = value;
24142 do {
24143 while (IS_BLANK_CH(*cur))
24144 cur++;
24145 end = cur;
24146 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24147 end++;
24148 if (end == cur)
24149 break;
24150 tmpValue = xmlStrndup(cur, end - cur);
24151 len++;
24152
24153 if (valNeeded)
24154 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24155 tmpValue, &curVal, fireErrors, 0, 1);
24156 else
24157 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24158 tmpValue, NULL, fireErrors, 0, 1);
24159 FREE_AND_NULL(tmpValue);
24160 if (curVal != NULL) {
24161 /*
24162 * Add to list of computed values.
24163 */
24164 if (val == NULL)
24165 val = curVal;
24166 else
24167 xmlSchemaValueAppend(prevVal, curVal);
24168 prevVal = curVal;
24169 curVal = NULL;
24170 }
24171 if (ret != 0) {
24172 if (ret < 0) {
24173 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24174 "validating an item of list simple type");
24175 goto internal_error;
24176 }
24177 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24178 break;
24179 }
24180 cur = end;
24181 } while (*cur != 0);
24182 FREE_AND_NULL(tmpValue);
24183 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24184 /*
24185 * Apply facets (pattern, enumeration).
24186 */
24187 ret = xmlSchemaValidateFacets(actxt, node, type,
24188 XML_SCHEMAS_UNKNOWN, value, val,
24189 len, fireErrors);
24190 if (ret != 0) {
24191 if (ret < 0) {
24192 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24193 "validating facets of list simple type");
24194 goto internal_error;
24195 }
24196 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24197 }
24198 }
24199 if (fireErrors && (ret > 0)) {
24200 /*
24201 * Report the normalized value.
24202 */
24203 normalize = 1;
24204 NORMALIZE(type);
24205 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24206 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024207 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024208 xmlSchemaTypeLinkPtr memberLink;
24209 /*
24210 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
24211 * not apply directly; however, the normalization behavior of ·union·
24212 * types is controlled by the value of whiteSpace on that one of the
24213 * ·memberTypes· against which the ·union· is successfully validated.
24214 *
24215 * This means that the value is normalized by the first validating
24216 * member type, then the facets of the union type are applied. This
24217 * needs changing of the value!
24218 */
24219
24220 /*
24221 * 1.2.3 if {variety} is ·union· then the string must ·match· a
24222 * literal in the ·lexical space· of at least one member of
24223 * {member type definitions}
24224 */
24225 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24226 if (memberLink == NULL) {
24227 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24228 "union simple type has no member types");
24229 goto internal_error;
24230 }
24231 /*
24232 * Always normalize union type values, since we currently
24233 * cannot store the whitespace information with the value
24234 * itself; otherwise a later value-comparison would be
24235 * not possible.
24236 */
24237 while (memberLink != NULL) {
24238 if (valNeeded)
24239 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24240 memberLink->type, value, &val, 0, 1, 0);
24241 else
24242 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24243 memberLink->type, value, NULL, 0, 1, 0);
24244 if (ret <= 0)
24245 break;
24246 memberLink = memberLink->next;
24247 }
24248 if (ret != 0) {
24249 if (ret < 0) {
24250 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24251 "validating members of union simple type");
24252 goto internal_error;
24253 }
24254 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24255 }
24256 /*
24257 * Apply facets (pattern, enumeration).
24258 */
24259 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24260 /*
24261 * The normalization behavior of ·union· types is controlled by
24262 * the value of whiteSpace on that one of the ·memberTypes·
24263 * against which the ·union· is successfully validated.
24264 */
24265 NORMALIZE(memberLink->type);
24266 ret = xmlSchemaValidateFacets(actxt, node, type,
24267 XML_SCHEMAS_UNKNOWN, value, val,
24268 0, fireErrors);
24269 if (ret != 0) {
24270 if (ret < 0) {
24271 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24272 "validating facets of union simple type");
24273 goto internal_error;
24274 }
24275 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24276 }
24277 }
24278 if (fireErrors && (ret > 0))
24279 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24280 }
24281
24282 if (normValue != NULL)
24283 xmlFree(normValue);
24284 if (ret == 0) {
24285 if (retVal != NULL)
24286 *retVal = val;
24287 else if (val != NULL)
24288 xmlSchemaFreeValue(val);
24289 } else if (val != NULL)
24290 xmlSchemaFreeValue(val);
24291 return (ret);
24292internal_error:
24293 if (normValue != NULL)
24294 xmlFree(normValue);
24295 if (val != NULL)
24296 xmlSchemaFreeValue(val);
24297 return (-1);
24298}
24299
24300static int
24301xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24302 const xmlChar *value,
24303 const xmlChar **nsName,
24304 const xmlChar **localName)
24305{
24306 int ret = 0;
24307
24308 if ((nsName == NULL) || (localName == NULL))
24309 return (-1);
24310 *nsName = NULL;
24311 *localName = NULL;
24312
24313 ret = xmlValidateQName(value, 1);
24314 if (ret == -1)
24315 return (-1);
24316 if (ret > 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024317 xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024318 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24319 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24320 return (1);
24321 }
24322 {
24323 xmlChar *local = NULL;
24324 xmlChar *prefix;
24325
24326 /*
24327 * NOTE: xmlSplitQName2 will return a duplicated
24328 * string.
24329 */
24330 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024331 if (local == NULL)
24332 *localName = xmlDictLookup(vctxt->dict, value, -1);
24333 else {
24334 *localName = xmlDictLookup(vctxt->dict, local, -1);
24335 xmlFree(local);
24336 }
24337
24338 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24339
24340 if (prefix != NULL) {
24341 xmlFree(prefix);
24342 /*
24343 * A namespace must be found if the prefix is NOT NULL.
24344 */
24345 if (*nsName == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024346 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024347 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024348 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024349 "The QName value '%s' has no "
24350 "corresponding namespace declaration in scope",
24351 value, NULL);
24352 return (2);
24353 }
24354 }
24355 }
24356 return (0);
24357}
24358
24359static int
24360xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24361 xmlSchemaAttrInfoPtr iattr,
24362 xmlSchemaTypePtr *localType,
24363 xmlSchemaElementPtr elemDecl)
24364{
24365 int ret = 0;
24366 /*
24367 * cvc-elt (3.3.4) : (4)
24368 * AND
24369 * Schema-Validity Assessment (Element) (cvc-assess-elt)
24370 * (1.2.1.2.1) - (1.2.1.2.4)
24371 * Handle 'xsi:type'.
24372 */
24373 if (localType == NULL)
24374 return (-1);
24375 *localType = NULL;
24376 if (iattr == NULL)
24377 return (0);
24378 else {
24379 const xmlChar *nsName = NULL, *local = NULL;
24380 /*
24381 * TODO: We should report a *warning* that the type was overriden
24382 * by the instance.
24383 */
24384 ACTIVATE_ATTRIBUTE(iattr);
24385 /*
24386 * (cvc-elt) (3.3.4) : (4.1)
24387 * (cvc-assess-elt) (1.2.1.2.2)
24388 */
24389 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24390 &nsName, &local);
24391 if (ret != 0) {
24392 if (ret < 0) {
24393 VERROR_INT("xmlSchemaValidateElementByDeclaration",
24394 "calling xmlSchemaQNameExpand() to validate the "
24395 "attribute 'xsi:type'");
24396 goto internal_error;
24397 }
24398 goto exit;
24399 }
24400 /*
24401 * (cvc-elt) (3.3.4) : (4.2)
24402 * (cvc-assess-elt) (1.2.1.2.3)
24403 */
24404 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24405 if (*localType == NULL) {
24406 xmlChar *str = NULL;
24407
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_ELT_4_2, 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' of the xsi:type attribute does not "
24412 "resolve to a type definition",
24413 xmlSchemaFormatQName(&str, nsName, local), NULL);
24414 FREE_AND_NULL(str);
24415 ret = vctxt->err;
24416 goto exit;
24417 }
24418 if (elemDecl != NULL) {
24419 int set = 0;
24420
24421 /*
24422 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24423 * "The ·local type definition· must be validly
24424 * derived from the {type definition} given the union of
24425 * the {disallowed substitutions} and the {type definition}'s
24426 * {prohibited substitutions}, as defined in
24427 * Type Derivation OK (Complex) (§3.4.6)
24428 * (if it is a complex type definition),
24429 * or given {disallowed substitutions} as defined in Type
24430 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
24431 * definition)."
24432 *
24433 * {disallowed substitutions}: the "block" on the element decl.
24434 * {prohibited substitutions}: the "block" on the type def.
24435 */
24436 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24437 (elemDecl->subtypes->flags &
24438 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24439 set |= SUBSET_EXTENSION;
24440
24441 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24442 (elemDecl->subtypes->flags &
24443 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24444 set |= SUBSET_RESTRICTION;
24445
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024446 if ((vctxt->pctxt == NULL) &&
24447 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24448 return (-1);
24449 if (xmlSchemaCheckCOSDerivedOK(vctxt->pctxt, *localType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024450 elemDecl->subtypes, set) != 0) {
24451 xmlChar *str = NULL;
24452
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024453 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024454 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24455 "The type definition '%s', specified by xsi:type, is "
24456 "blocked or not validly derived from the type definition "
24457 "of the element declaration",
24458 xmlSchemaFormatQName(&str,
24459 (*localType)->targetNamespace,
24460 (*localType)->name),
24461 NULL);
24462 FREE_AND_NULL(str);
24463 ret = vctxt->err;
24464 *localType = NULL;
24465 }
24466 }
24467 }
24468exit:
24469 ACTIVATE_ELEM;
24470 return (ret);
24471internal_error:
24472 ACTIVATE_ELEM;
24473 return (-1);
24474}
24475
24476static int
24477xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24478{
24479 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024480 xmlSchemaTypePtr actualType = WXS_ELEM_TYPEDEF(elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024481
24482 /*
24483 * cvc-elt (3.3.4) : 1
24484 */
24485 if (elemDecl == NULL) {
24486 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
24487 "No matching declaration available");
24488 return (vctxt->err);
24489 }
24490 /*
24491 * cvc-elt (3.3.4) : 2
24492 */
24493 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
24494 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
24495 "The element declaration is abstract");
24496 return (vctxt->err);
24497 }
24498 if (actualType == NULL) {
24499 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24500 "The type definition is absent");
24501 return (XML_SCHEMAV_CVC_TYPE_1);
24502 }
24503 if (vctxt->nbAttrInfos != 0) {
24504 int ret;
24505 xmlSchemaAttrInfoPtr iattr;
24506 /*
24507 * cvc-elt (3.3.4) : 3
24508 * Handle 'xsi:nil'.
24509 */
24510 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24511 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
24512 if (iattr) {
24513 ACTIVATE_ATTRIBUTE(iattr);
24514 /*
24515 * Validate the value.
24516 */
24517 ret = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024518 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024519 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
24520 iattr->value, &(iattr->val), 1, 0, 0);
24521 ACTIVATE_ELEM;
24522 if (ret < 0) {
24523 VERROR_INT("xmlSchemaValidateElemDecl",
24524 "calling xmlSchemaVCheckCVCSimpleType() to "
24525 "validate the attribute 'xsi:nil'");
24526 return (-1);
24527 }
24528 if (ret == 0) {
24529 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
24530 /*
24531 * cvc-elt (3.3.4) : 3.1
24532 */
24533 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
24534 "The element is not 'nillable'");
24535 /* Does not return an error on purpose. */
24536 } else {
24537 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
24538 /*
24539 * cvc-elt (3.3.4) : 3.2.2
24540 */
24541 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
24542 (elemDecl->value != NULL)) {
24543 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
24544 "The element cannot be 'nilled' because "
24545 "there is a fixed value constraint defined "
24546 "for it");
24547 /* Does not return an error on purpose. */
24548 } else
24549 vctxt->inode->flags |=
24550 XML_SCHEMA_ELEM_INFO_NILLED;
24551 }
24552 }
24553 }
24554 }
24555 /*
24556 * cvc-elt (3.3.4) : 4
24557 * Handle 'xsi:type'.
24558 */
24559 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24560 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
24561 if (iattr) {
24562 xmlSchemaTypePtr localType = NULL;
24563
24564 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
24565 elemDecl);
24566 if (ret != 0) {
24567 if (ret == -1) {
24568 VERROR_INT("xmlSchemaValidateElemDecl",
24569 "calling xmlSchemaProcessXSIType() to "
24570 "process the attribute 'xsi:type'");
24571 return (-1);
24572 }
24573 /* Does not return an error on purpose. */
24574 }
24575 if (localType != NULL) {
24576 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
24577 actualType = localType;
24578 }
24579 }
24580 }
24581 /*
24582 * IDC: Register identity-constraint XPath matchers.
24583 */
24584 if ((elemDecl->idcs != NULL) &&
24585 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
24586 return (-1);
24587 /*
24588 * No actual type definition.
24589 */
24590 if (actualType == NULL) {
24591 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24592 "The type definition is absent");
24593 return (XML_SCHEMAV_CVC_TYPE_1);
24594 }
24595 /*
24596 * Remember the actual type definition.
24597 */
24598 vctxt->inode->typeDef = actualType;
24599
24600 return (0);
24601}
24602
24603static int
24604xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
24605{
24606 xmlSchemaAttrInfoPtr iattr;
24607 int ret = 0, i;
24608
24609 /*
24610 * SPEC cvc-type (3.1.1)
24611 * "The attributes of must be empty, excepting those whose namespace
24612 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
24613 * whose local name is one of type, nil, schemaLocation or
24614 * noNamespaceSchemaLocation."
24615 */
24616 if (vctxt->nbAttrInfos == 0)
24617 return (0);
24618 for (i = 0; i < vctxt->nbAttrInfos; i++) {
24619 iattr = vctxt->attrInfos[i];
24620 if (! iattr->metaType) {
24621 ACTIVATE_ATTRIBUTE(iattr)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024622 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024623 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
24624 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
24625 }
24626 }
24627 ACTIVATE_ELEM
24628 return (ret);
24629}
24630
24631/*
24632* Cleanup currently used attribute infos.
24633*/
24634static void
24635xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
24636{
24637 int i;
24638 xmlSchemaAttrInfoPtr attr;
24639
24640 if (vctxt->nbAttrInfos == 0)
24641 return;
24642 for (i = 0; i < vctxt->nbAttrInfos; i++) {
24643 attr = vctxt->attrInfos[i];
24644 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24645 if (attr->localName != NULL)
24646 xmlFree((xmlChar *) attr->localName);
24647 if (attr->nsName != NULL)
24648 xmlFree((xmlChar *) attr->nsName);
24649 }
24650 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24651 if (attr->value != NULL)
24652 xmlFree((xmlChar *) attr->value);
24653 }
24654 if (attr->val != NULL) {
24655 xmlSchemaFreeValue(attr->val);
24656 attr->val = NULL;
24657 }
24658 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
24659 }
24660 vctxt->nbAttrInfos = 0;
24661}
24662
24663/*
24664* 3.4.4 Complex Type Definition Validation Rules
24665* Element Locally Valid (Complex Type) (cvc-complex-type)
24666* 3.2.4 Attribute Declaration Validation Rules
24667* Validation Rule: Attribute Locally Valid (cvc-attribute)
24668* Attribute Locally Valid (Use) (cvc-au)
24669*
24670* Only "assessed" attribute information items will be visible to
24671* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
24672*/
24673static int
24674xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
24675{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024676 xmlSchemaTypePtr type = vctxt->inode->typeDef;
24677 xmlSchemaItemListPtr attrUseList;
24678 xmlSchemaAttributeUsePtr attrUse = NULL;
24679 xmlSchemaAttributePtr attrDecl = NULL;
24680 xmlSchemaAttrInfoPtr iattr, tmpiattr;
24681 int i, j, found, nbAttrs, nbUses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024682 int xpathRes = 0, res, wildIDs = 0, fixed;
24683
24684 /*
24685 * SPEC (cvc-attribute)
24686 * (1) "The declaration must not be ·absent· (see Missing
24687 * Sub-components (§5.3) for how this can fail to be
24688 * the case)."
24689 * (2) "Its {type definition} must not be absent."
24690 *
24691 * NOTE (1) + (2): This is not handled here, since we currently do not
24692 * allow validation against schemas which have missing sub-components.
24693 *
24694 * SPEC (cvc-complex-type)
24695 * (3) "For each attribute information item in the element information
24696 * item's [attributes] excepting those whose [namespace name] is
24697 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
24698 * [local name] is one of type, nil, schemaLocation or
24699 * noNamespaceSchemaLocation, the appropriate case among the following
24700 * must be true:
24701 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024702 */
24703 attrUseList = (xmlSchemaItemListPtr) type->attrUses;
24704 /*
24705 * @nbAttrs is the number of attributes present in the instance.
24706 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024707 nbAttrs = vctxt->nbAttrInfos;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024708 if (attrUseList != NULL)
24709 nbUses = attrUseList->nbItems;
24710 else
24711 nbUses = 0;
24712 for (i = 0; i < nbUses; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024713 found = 0;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024714 attrUse = attrUseList->items[i];
24715 attrDecl = WXS_ATTRUSE_DECL(attrUse);
24716 for (j = 0; j < nbAttrs; j++) {
24717 iattr = vctxt->attrInfos[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024718 /*
24719 * SPEC (cvc-complex-type) (3)
24720 * Skip meta attributes.
24721 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024722 if (iattr->metaType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024723 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024724 if (iattr->localName[0] != attrDecl->name[0])
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024725 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024726 if (!xmlStrEqual(iattr->localName, attrDecl->name))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024727 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024728 if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024729 continue;
24730 found = 1;
24731 /*
24732 * SPEC (cvc-complex-type)
24733 * (3.1) "If there is among the {attribute uses} an attribute
24734 * use with an {attribute declaration} whose {name} matches
24735 * the attribute information item's [local name] and whose
24736 * {target namespace} is identical to the attribute information
24737 * item's [namespace name] (where an ·absent· {target namespace}
24738 * is taken to be identical to a [namespace name] with no value),
24739 * then the attribute information must be ·valid· with respect
24740 * to that attribute use as per Attribute Locally Valid (Use)
24741 * (§3.5.4). In this case the {attribute declaration} of that
24742 * attribute use is the ·context-determined declaration· for the
24743 * attribute information item with respect to Schema-Validity
24744 * Assessment (Attribute) (§3.2.4) and
24745 * Assessment Outcome (Attribute) (§3.2.5).
24746 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024747 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
24748 iattr->use = attrUse;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024749 /*
24750 * Context-determined declaration.
24751 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024752 iattr->decl = attrDecl;
24753 iattr->typeDef = attrDecl->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024754 break;
24755 }
24756
24757 if (found)
24758 continue;
24759
24760 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
24761 /*
24762 * Handle non-existent, required attributes.
24763 *
24764 * SPEC (cvc-complex-type)
24765 * (4) "The {attribute declaration} of each attribute use in
24766 * the {attribute uses} whose {required} is true matches one
24767 * of the attribute information items in the element information
24768 * item's [attributes] as per clause 3.1 above."
24769 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024770 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
24771 if (tmpiattr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024772 VERROR_INT(
24773 "xmlSchemaVAttributesComplex",
24774 "calling xmlSchemaGetFreshAttrInfo()");
24775 return (-1);
24776 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024777 tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
24778 tmpiattr->use = attrUse;
24779 tmpiattr->decl = attrDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024780 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
24781 ((attrUse->defValue != NULL) ||
24782 (attrDecl->defValue != NULL))) {
24783 /*
24784 * Handle non-existent, optional, default/fixed attributes.
24785 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024786 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
24787 if (tmpiattr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024788 VERROR_INT(
24789 "xmlSchemaVAttributesComplex",
24790 "calling xmlSchemaGetFreshAttrInfo()");
24791 return (-1);
24792 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024793 tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
24794 tmpiattr->use = attrUse;
24795 tmpiattr->decl = attrDecl;
24796 tmpiattr->typeDef = attrDecl->subtypes;
24797 tmpiattr->localName = attrDecl->name;
24798 tmpiattr->nsName = attrDecl->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024799 }
24800 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024801
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024802 if (vctxt->nbAttrInfos == 0)
24803 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024804 nbUses = vctxt->nbAttrInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024805 /*
24806 * Validate against the wildcard.
24807 */
24808 if (type->attributeWildcard != NULL) {
24809 /*
24810 * SPEC (cvc-complex-type)
24811 * (3.2.1) "There must be an {attribute wildcard}."
24812 */
24813 for (i = 0; i < nbAttrs; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024814 iattr = vctxt->attrInfos[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024815 /*
24816 * SPEC (cvc-complex-type) (3)
24817 * Skip meta attributes.
24818 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024819 if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024820 continue;
24821 /*
24822 * SPEC (cvc-complex-type)
24823 * (3.2.2) "The attribute information item must be ·valid· with
24824 * respect to it as defined in Item Valid (Wildcard) (§3.10.4)."
24825 *
24826 * SPEC Item Valid (Wildcard) (cvc-wildcard)
24827 * "... its [namespace name] must be ·valid· with respect to
24828 * the wildcard constraint, as defined in Wildcard allows
24829 * Namespace Name (§3.10.4)."
24830 */
24831 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024832 iattr->nsName) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024833 /*
24834 * Handle processContents.
24835 *
24836 * SPEC (cvc-wildcard):
24837 * processContents | context-determined declaration:
24838 * "strict" "mustFind"
24839 * "lax" "none"
24840 * "skip" "skip"
24841 */
24842 if (type->attributeWildcard->processContents ==
24843 XML_SCHEMAS_ANY_SKIP) {
24844 /*
24845 * context-determined declaration = "skip"
24846 *
24847 * SPEC PSVI Assessment Outcome (Attribute)
24848 * [validity] = "notKnown"
24849 * [validation attempted] = "none"
24850 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024851 iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024852 continue;
24853 }
24854 /*
24855 * Find an attribute declaration.
24856 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024857 iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
24858 iattr->localName, iattr->nsName);
24859 if (iattr->decl != NULL) {
24860 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024861 /*
24862 * SPEC (cvc-complex-type)
24863 * (5) "Let [Definition:] the wild IDs be the set of
24864 * all attribute information item to which clause 3.2
24865 * applied and whose ·validation· resulted in a
24866 * ·context-determined declaration· of mustFind or no
24867 * ·context-determined declaration· at all, and whose
24868 * [local name] and [namespace name] resolve (as
24869 * defined by QName resolution (Instance) (§3.15.4)) to
24870 * an attribute declaration whose {type definition} is
24871 * or is derived from ID. Then all of the following
24872 * must be true:"
24873 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024874 iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024875 if (xmlSchemaIsDerivedFromBuiltInType(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024876 iattr->typeDef, XML_SCHEMAS_ID)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024877 /*
24878 * SPEC (5.1) "There must be no more than one
24879 * item in ·wild IDs·."
24880 */
24881 if (wildIDs != 0) {
24882 /* VAL TODO */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024883 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024884 TODO
24885 continue;
24886 }
24887 wildIDs++;
24888 /*
24889 * SPEC (cvc-complex-type)
24890 * (5.2) "If ·wild IDs· is non-empty, there must not
24891 * be any attribute uses among the {attribute uses}
24892 * whose {attribute declaration}'s {type definition}
24893 * is or is derived from ID."
24894 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024895 for (j = 0; j < attrUseList->nbItems; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024896 if (xmlSchemaIsDerivedFromBuiltInType(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024897 WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024898 XML_SCHEMAS_ID)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024899 /* URGENT VAL TODO: implement */
24900 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024901 TODO
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024902 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024903 }
24904 }
24905 }
24906 } else if (type->attributeWildcard->processContents ==
24907 XML_SCHEMAS_ANY_LAX) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024908 iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024909 /*
24910 * SPEC PSVI Assessment Outcome (Attribute)
24911 * [validity] = "notKnown"
24912 * [validation attempted] = "none"
24913 */
24914 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024915 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024916 }
24917 }
24918 }
24919 }
24920
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024921 if (vctxt->nbAttrInfos == 0)
24922 return (0);
24923
24924 /*
24925 * Validate values, create default attributes, evaluate IDCs.
24926 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024927 for (i = 0; i < vctxt->nbAttrInfos; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024928 iattr = vctxt->attrInfos[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024929 /*
24930 * VAL TODO: Note that we won't try to resolve IDCs to
24931 * "lax" and "skip" validated attributes. Check what to
24932 * do in this case.
24933 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024934 if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
24935 (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024936 continue;
24937 /*
24938 * VAL TODO: What to do if the type definition is missing?
24939 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024940 if (iattr->typeDef == NULL) {
24941 iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024942 continue;
24943 }
24944
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024945 ACTIVATE_ATTRIBUTE(iattr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000024946 fixed = 0;
24947 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024948
24949 if (vctxt->xpathStates != NULL) {
24950 /*
24951 * Evaluate IDCs.
24952 */
24953 xpathRes = xmlSchemaXPathEvaluate(vctxt,
24954 XML_ATTRIBUTE_NODE);
24955 if (xpathRes == -1) {
24956 VERROR_INT("xmlSchemaVAttributesComplex",
24957 "calling xmlSchemaXPathEvaluate()");
24958 goto internal_error;
24959 }
24960 }
24961
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024962 if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024963 /*
24964 * Default/fixed attributes.
24965 */
24966 if (xpathRes) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024967 if (iattr->use->defValue != NULL) {
24968 iattr->value = (xmlChar *) iattr->use->defValue;
24969 iattr->val = iattr->use->defVal;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024970 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024971 iattr->value = (xmlChar *) iattr->decl->defValue;
24972 iattr->val = iattr->decl->defVal;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024973 }
24974 /*
24975 * IDCs will consume the precomputed default value,
24976 * so we need to clone it.
24977 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024978 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024979 VERROR_INT("xmlSchemaVAttributesComplex",
24980 "default/fixed value on an attribute use was "
24981 "not precomputed");
24982 goto internal_error;
24983 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024984 iattr->val = xmlSchemaCopyValue(iattr->val);
24985 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024986 VERROR_INT("xmlSchemaVAttributesComplex",
24987 "calling xmlSchemaCopyValue()");
24988 goto internal_error;
24989 }
24990 }
24991 /*
24992 * PSVI: Add the default attribute to the current element.
24993 * VAL TODO: Should we use the *normalized* value? This currently
24994 * uses the *initial* value.
24995 */
24996 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024997 (iattr->node != NULL) && (iattr->node->doc != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024998 xmlChar *normValue;
24999 const xmlChar *value;
25000
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025001 value = iattr->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025002 /*
25003 * Normalize the value.
25004 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025005 normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25006 iattr->value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025007 if (normValue != NULL)
25008 value = BAD_CAST normValue;
25009
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025010 if (iattr->nsName == NULL) {
25011 if (xmlNewProp(iattr->node->parent,
25012 iattr->localName, value) == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025013 VERROR_INT("xmlSchemaVAttributesComplex",
25014 "callling xmlNewProp()");
25015 if (normValue != NULL)
25016 xmlFree(normValue);
25017 goto internal_error;
25018 }
25019 } else {
25020 xmlNsPtr ns;
25021
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025022 ns = xmlSearchNsByHref(iattr->node->doc,
25023 iattr->node->parent, iattr->nsName);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025024 if (ns == NULL) {
25025 xmlChar prefix[12];
25026 int counter = 0;
25027
25028 /*
25029 * Create a namespace declaration on the validation
25030 * root node if no namespace declaration is in scope.
25031 */
25032 do {
25033 snprintf((char *) prefix, 12, "p%d", counter++);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025034 ns = xmlSearchNs(iattr->node->doc,
25035 iattr->node->parent, BAD_CAST prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025036 if (counter > 1000) {
25037 VERROR_INT(
25038 "xmlSchemaVAttributesComplex",
25039 "could not compute a ns prefix for a "
25040 "default/fixed attribute");
25041 if (normValue != NULL)
25042 xmlFree(normValue);
25043 goto internal_error;
25044 }
25045 } while (ns != NULL);
25046 ns = xmlNewNs(vctxt->validationRoot,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025047 iattr->nsName, BAD_CAST prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025048 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025049 /*
25050 * TODO:
25051 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25052 * If we have QNames: do we need to ensure there's a
25053 * prefix defined for the QName?
25054 */
25055 xmlNewNsProp(iattr->node->parent, ns,
25056 iattr->localName, value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025057 }
25058 if (normValue != NULL)
25059 xmlFree(normValue);
25060 }
25061 /*
25062 * Go directly to IDC evaluation.
25063 */
25064 goto eval_idcs;
25065 }
25066 /*
25067 * Validate the value.
25068 */
25069 if (vctxt->value != NULL) {
25070 /*
25071 * Free last computed value; just for safety reasons.
25072 */
25073 xmlSchemaFreeValue(vctxt->value);
25074 vctxt->value = NULL;
25075 }
25076 /*
25077 * Note that the attribute *use* can be unavailable, if
25078 * the attribute was a wild attribute.
25079 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025080 if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25081 ((iattr->use != NULL) &&
25082 (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025083 fixed = 1;
25084 else
25085 fixed = 0;
25086 /*
25087 * SPEC (cvc-attribute)
25088 * (3) "The item's ·normalized value· must be locally ·valid·
25089 * with respect to that {type definition} as per
25090 * String Valid (§3.14.4)."
25091 *
25092 * VAL TODO: Do we already have the
25093 * "normalized attribute value" here?
25094 */
25095 if (xpathRes || fixed) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025096 iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025097 /*
25098 * Request a computed value.
25099 */
25100 res = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025101 ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025102 iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025103 1, 1, 0);
25104 } else {
25105 res = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025106 ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025107 iattr->node, iattr->typeDef, iattr->value, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025108 1, 0, 0);
25109 }
25110
25111 if (res != 0) {
25112 if (res == -1) {
25113 VERROR_INT("xmlSchemaVAttributesComplex",
25114 "calling xmlSchemaStreamValidateSimpleTypeValue()");
25115 goto internal_error;
25116 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025117 iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025118 /*
25119 * SPEC PSVI Assessment Outcome (Attribute)
25120 * [validity] = "invalid"
25121 */
25122 goto eval_idcs;
25123 }
25124
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025125 if (fixed) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025126 /*
25127 * SPEC Attribute Locally Valid (Use) (cvc-au)
25128 * "For an attribute information item to be·valid·
25129 * with respect to an attribute use its *normalized*
25130 * value· must match the *canonical* lexical
25131 * representation of the attribute use's {value
25132 * constraint}value, if it is present and fixed."
25133 *
25134 * VAL TODO: The requirement for the *canonical* value
25135 * will be removed in XML Schema 1.1.
25136 */
25137 /*
25138 * SPEC Attribute Locally Valid (cvc-attribute)
25139 * (4) "The item's *actual* value· must match the *value* of
25140 * the {value constraint}, if it is present and fixed."
25141 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025142 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025143 /* VAL TODO: A value was not precomputed. */
25144 TODO
25145 goto eval_idcs;
25146 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025147 if ((iattr->use != NULL) &&
25148 (iattr->use->defValue != NULL)) {
25149 if (iattr->use->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025150 /* VAL TODO: A default value was not precomputed. */
25151 TODO
25152 goto eval_idcs;
25153 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025154 iattr->vcValue = iattr->use->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025155 /*
25156 if (xmlSchemaCompareValuesWhtsp(attr->val,
25157 (xmlSchemaWhitespaceValueType) ws,
25158 attr->use->defVal,
25159 (xmlSchemaWhitespaceValueType) ws) != 0) {
25160 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025161 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25162 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025163 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025164 if (iattr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025165 /* VAL TODO: A default value was not precomputed. */
25166 TODO
25167 goto eval_idcs;
25168 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025169 iattr->vcValue = iattr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025170 /*
25171 if (xmlSchemaCompareValuesWhtsp(attr->val,
25172 (xmlSchemaWhitespaceValueType) ws,
25173 attrDecl->defVal,
25174 (xmlSchemaWhitespaceValueType) ws) != 0) {
25175 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025176 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25177 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025178 }
25179 /*
25180 * [validity] = "valid"
25181 */
25182 }
25183eval_idcs:
25184 /*
25185 * Evaluate IDCs.
25186 */
25187 if (xpathRes) {
25188 if (xmlSchemaXPathProcessHistory(vctxt,
25189 vctxt->depth +1) == -1) {
25190 VERROR_INT("xmlSchemaVAttributesComplex",
25191 "calling xmlSchemaXPathEvaluate()");
25192 goto internal_error;
25193 }
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000025194 } else if (vctxt->xpathStates != NULL)
25195 xmlSchemaXPathPop(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025196 }
25197
25198 /*
25199 * Report errors.
25200 */
25201 for (i = 0; i < vctxt->nbAttrInfos; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025202 iattr = vctxt->attrInfos[i];
25203 if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25204 (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25205 (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25206 (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025207 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025208 ACTIVATE_ATTRIBUTE(iattr);
25209 switch (iattr->state) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025210 case XML_SCHEMAS_ATTR_ERR_MISSING: {
25211 xmlChar *str = NULL;
25212 ACTIVATE_ELEM;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025213 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025214 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25215 "The attribute '%s' is required but missing",
25216 xmlSchemaFormatQName(&str,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025217 iattr->decl->targetNamespace,
25218 iattr->decl->name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025219 NULL);
25220 FREE_AND_NULL(str)
25221 break;
25222 }
25223 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25224 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25225 "The type definition is absent");
25226 break;
25227 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025228 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025229 XML_SCHEMAV_CVC_AU, NULL, NULL,
25230 "The value '%s' does not match the fixed "
25231 "value constraint '%s'",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025232 iattr->value, iattr->vcValue);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025233 break;
25234 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25235 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25236 "No matching global attribute declaration available, but "
25237 "demanded by the strict wildcard");
25238 break;
25239 case XML_SCHEMAS_ATTR_UNKNOWN:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025240 if (iattr->metaType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025241 break;
25242 /*
25243 * MAYBE VAL TODO: One might report different error messages
25244 * for the following errors.
25245 */
25246 if (type->attributeWildcard == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025247 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025248 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025249 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025250 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025251 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025252 }
25253 break;
25254 default:
25255 break;
25256 }
25257 }
25258
25259 ACTIVATE_ELEM;
25260 return (0);
25261internal_error:
25262 ACTIVATE_ELEM;
25263 return (-1);
25264}
25265
25266static int
25267xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25268 int *skip)
25269{
25270 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25271 /*
25272 * The namespace of the element was already identified to be
25273 * matching the wildcard.
25274 */
25275 if ((skip == NULL) || (wild == NULL) ||
25276 (wild->type != XML_SCHEMA_TYPE_ANY)) {
25277 VERROR_INT("xmlSchemaValidateElemWildcard",
25278 "bad arguments");
25279 return (-1);
25280 }
25281 *skip = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025282 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25283 /*
25284 * URGENT VAL TODO: Either we need to position the stream to the
25285 * next sibling, or walk the whole subtree.
25286 */
25287 *skip = 1;
25288 return (0);
25289 }
25290 {
25291 xmlSchemaElementPtr decl = NULL;
25292
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025293 decl = xmlSchemaGetElem(vctxt->schema,
25294 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025295 if (decl != NULL) {
25296 vctxt->inode->decl = decl;
25297 return (0);
25298 }
25299 }
25300 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25301 /* VAL TODO: Change to proper error code. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025302 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025303 "No matching global element declaration available, but "
25304 "demanded by the strict wildcard");
25305 return (vctxt->err);
25306 }
25307 if (vctxt->nbAttrInfos != 0) {
25308 xmlSchemaAttrInfoPtr iattr;
25309 /*
25310 * SPEC Validation Rule: Schema-Validity Assessment (Element)
25311 * (1.2.1.2.1) - (1.2.1.2.3 )
25312 *
25313 * Use the xsi:type attribute for the type definition.
25314 */
25315 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25316 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25317 if (iattr != NULL) {
25318 if (xmlSchemaProcessXSIType(vctxt, iattr,
25319 &(vctxt->inode->typeDef), NULL) == -1) {
25320 VERROR_INT("xmlSchemaValidateElemWildcard",
25321 "calling xmlSchemaProcessXSIType() to "
25322 "process the attribute 'xsi:nil'");
25323 return (-1);
25324 }
25325 /*
25326 * Don't return an error on purpose.
25327 */
25328 return (0);
25329 }
25330 }
25331 /*
25332 * SPEC Validation Rule: Schema-Validity Assessment (Element)
25333 *
25334 * Fallback to "anyType".
25335 */
25336 vctxt->inode->typeDef =
25337 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25338 return (0);
25339}
25340
25341/*
25342* xmlSchemaCheckCOSValidDefault:
25343*
25344* This will be called if: not nilled, no content and a default/fixed
25345* value is provided.
25346*/
25347
25348static int
25349xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25350 const xmlChar *value,
25351 xmlSchemaValPtr *val)
25352{
25353 int ret = 0;
25354 xmlSchemaNodeInfoPtr inode = vctxt->inode;
25355
25356 /*
25357 * cos-valid-default:
25358 * Schema Component Constraint: Element Default Valid (Immediate)
25359 * For a string to be a valid default with respect to a type
25360 * definition the appropriate case among the following must be true:
25361 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025362 if WXS_IS_COMPLEX(inode->typeDef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025363 /*
25364 * Complex type.
25365 *
25366 * SPEC (2.1) "its {content type} must be a simple type definition
25367 * or mixed."
25368 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
25369 * type}'s particle must be ·emptiable· as defined by
25370 * Particle Emptiable (§3.9.6)."
25371 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025372 if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25373 ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25374 (! WXS_EMPTIABLE(inode->typeDef)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025375 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25376 /* NOTE that this covers (2.2.2) as well. */
25377 VERROR(ret, NULL,
25378 "For a string to be a valid default, the type definition "
25379 "must be a simple type or a complex type with simple content "
25380 "or mixed content and a particle emptiable");
25381 return(ret);
25382 }
25383 }
25384 /*
25385 * 1 If the type definition is a simple type definition, then the string
25386 * must be ·valid· with respect to that definition as defined by String
25387 * Valid (§3.14.4).
25388 *
25389 * AND
25390 *
25391 * 2.2.1 If the {content type} is a simple type definition, then the
25392 * string must be ·valid· with respect to that simple type definition
25393 * as defined by String Valid (§3.14.4).
25394 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025395 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025396
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025397 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025398 NULL, inode->typeDef, value, val, 1, 1, 0);
25399
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025400 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025401
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025402 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025403 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25404 }
25405 if (ret < 0) {
25406 VERROR_INT("xmlSchemaCheckCOSValidDefault",
25407 "calling xmlSchemaVCheckCVCSimpleType()");
25408 }
25409 return (ret);
25410}
25411
25412static void
25413xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25414 const xmlChar * name ATTRIBUTE_UNUSED,
25415 xmlSchemaElementPtr item,
25416 xmlSchemaNodeInfoPtr inode)
25417{
25418 inode->decl = item;
25419#ifdef DEBUG_CONTENT
25420 {
25421 xmlChar *str = NULL;
25422
25423 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25424 xmlGenericError(xmlGenericErrorContext,
25425 "AUTOMATON callback for '%s' [declaration]\n",
25426 xmlSchemaFormatQName(&str,
25427 inode->localName, inode->nsName));
25428 } else {
25429 xmlGenericError(xmlGenericErrorContext,
25430 "AUTOMATON callback for '%s' [wildcard]\n",
25431 xmlSchemaFormatQName(&str,
25432 inode->localName, inode->nsName));
25433
25434 }
25435 FREE_AND_NULL(str)
25436 }
25437#endif
25438}
25439
25440static int
25441xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000025442{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025443 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25444 if (vctxt->inode == NULL) {
25445 VERROR_INT("xmlSchemaValidatorPushElem",
25446 "calling xmlSchemaGetFreshElemInfo()");
25447 return (-1);
25448 }
25449 vctxt->nbAttrInfos = 0;
25450 return (0);
25451}
25452
25453static int
25454xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25455 xmlSchemaNodeInfoPtr inode,
25456 xmlSchemaTypePtr type,
25457 const xmlChar *value)
25458{
25459 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25460 return (xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025461 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025462 type, value, &(inode->val), 1, 1, 0));
25463 else
25464 return (xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025465 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025466 type, value, NULL, 1, 0, 0));
25467}
25468
25469
25470
25471/*
25472* Process END of element.
25473*/
25474static int
25475xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
25476{
25477 int ret = 0;
25478 xmlSchemaNodeInfoPtr inode = vctxt->inode;
25479
25480 if (vctxt->nbAttrInfos != 0)
25481 xmlSchemaClearAttrInfos(vctxt);
25482 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
25483 /*
25484 * This element was not expected;
25485 * we will not validate child elements of broken parents.
25486 * Skip validation of all content of the parent.
25487 */
25488 vctxt->skipDepth = vctxt->depth -1;
25489 goto end_elem;
25490 }
25491 if ((inode->typeDef == NULL) ||
25492 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
25493 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000025494 * 1. the type definition might be missing if the element was
25495 * error prone
25496 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025497 */
25498 goto end_elem;
25499 }
25500 /*
25501 * Check the content model.
25502 */
25503 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
25504 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
25505
25506 /*
25507 * Workaround for "anyType".
25508 */
25509 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
25510 goto character_content;
25511
25512 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
25513 xmlChar *values[10];
25514 int terminal, nbval = 10, nbneg;
25515
25516 if (inode->regexCtxt == NULL) {
25517 /*
25518 * Create the regex context.
25519 */
25520 inode->regexCtxt =
25521 xmlRegNewExecCtxt(inode->typeDef->contModel,
25522 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
25523 vctxt);
25524 if (inode->regexCtxt == NULL) {
25525 VERROR_INT("xmlSchemaValidatorPopElem",
25526 "failed to create a regex context");
25527 goto internal_error;
25528 }
25529#ifdef DEBUG_AUTOMATA
25530 xmlGenericError(xmlGenericErrorContext,
25531 "AUTOMATON create on '%s'\n", inode->localName);
25532#endif
25533 }
25534 /*
25535 * Get hold of the still expected content, since a further
25536 * call to xmlRegExecPushString() will loose this information.
25537 */
25538 xmlRegExecNextValues(inode->regexCtxt,
25539 &nbval, &nbneg, &values[0], &terminal);
25540 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
25541 if (ret <= 0) {
25542 /*
25543 * Still missing something.
25544 */
25545 ret = 1;
25546 inode->flags |=
25547 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025548 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025549 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
25550 "Missing child element(s)",
25551 nbval, nbneg, values);
25552#ifdef DEBUG_AUTOMATA
25553 xmlGenericError(xmlGenericErrorContext,
25554 "AUTOMATON missing ERROR on '%s'\n",
25555 inode->localName);
25556#endif
25557 } else {
25558 /*
25559 * Content model is satisfied.
25560 */
25561 ret = 0;
25562#ifdef DEBUG_AUTOMATA
25563 xmlGenericError(xmlGenericErrorContext,
25564 "AUTOMATON succeeded on '%s'\n",
25565 inode->localName);
25566#endif
25567 }
25568
25569 }
25570 }
25571 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
25572 goto end_elem;
25573
25574character_content:
25575
25576 if (vctxt->value != NULL) {
25577 xmlSchemaFreeValue(vctxt->value);
25578 vctxt->value = NULL;
25579 }
25580 /*
25581 * Check character content.
25582 */
25583 if (inode->decl == NULL) {
25584 /*
25585 * Speedup if no declaration exists.
25586 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025587 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025588 ret = xmlSchemaVCheckINodeDataType(vctxt,
25589 inode, inode->typeDef, inode->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025590 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025591 ret = xmlSchemaVCheckINodeDataType(vctxt,
25592 inode, inode->typeDef->contentTypeDef,
25593 inode->value);
25594 }
25595 if (ret < 0) {
25596 VERROR_INT("xmlSchemaValidatorPopElem",
25597 "calling xmlSchemaVCheckCVCSimpleType()");
25598 goto internal_error;
25599 }
25600 goto end_elem;
25601 }
25602 /*
25603 * cvc-elt (3.3.4) : 5
25604 * The appropriate case among the following must be true:
25605 */
25606 /*
25607 * cvc-elt (3.3.4) : 5.1
25608 * If the declaration has a {value constraint},
25609 * the item has neither element nor character [children] and
25610 * clause 3.2 has not applied, then all of the following must be true:
25611 */
25612 if ((inode->decl->value != NULL) &&
25613 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
25614 (! INODE_NILLED(inode))) {
25615 /*
25616 * cvc-elt (3.3.4) : 5.1.1
25617 * If the ·actual type definition· is a ·local type definition·
25618 * then the canonical lexical representation of the {value constraint}
25619 * value must be a valid default for the ·actual type definition· as
25620 * defined in Element Default Valid (Immediate) (§3.3.6).
25621 */
25622 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025623 * NOTE: 'local' above means types acquired by xsi:type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025624 * NOTE: Although the *canonical* value is stated, it is not
25625 * relevant if canonical or not. Additionally XML Schema 1.1
25626 * will removed this requirement as well.
25627 */
25628 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
25629
25630 ret = xmlSchemaCheckCOSValidDefault(vctxt,
25631 inode->decl->value, &(inode->val));
25632 if (ret != 0) {
25633 if (ret < 0) {
25634 VERROR_INT("xmlSchemaValidatorPopElem",
25635 "calling xmlSchemaCheckCOSValidDefault()");
25636 goto internal_error;
25637 }
25638 goto end_elem;
25639 }
25640 /*
25641 * Stop here, to avoid redundant validation of the value
25642 * (see following).
25643 */
25644 goto default_psvi;
25645 }
25646 /*
25647 * cvc-elt (3.3.4) : 5.1.2
25648 * The element information item with the canonical lexical
25649 * representation of the {value constraint} value used as its
25650 * ·normalized value· must be ·valid· with respect to the
25651 * ·actual type definition· as defined by Element Locally Valid (Type)
25652 * (§3.3.4).
25653 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025654 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025655 ret = xmlSchemaVCheckINodeDataType(vctxt,
25656 inode, inode->typeDef, inode->decl->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025657 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025658 ret = xmlSchemaVCheckINodeDataType(vctxt,
25659 inode, inode->typeDef->contentTypeDef,
25660 inode->decl->value);
25661 }
25662 if (ret != 0) {
25663 if (ret < 0) {
25664 VERROR_INT("xmlSchemaValidatorPopElem",
25665 "calling xmlSchemaVCheckCVCSimpleType()");
25666 goto internal_error;
25667 }
25668 goto end_elem;
25669 }
25670
25671default_psvi:
25672 /*
25673 * PSVI: Create a text node on the instance element.
25674 */
25675 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
25676 (inode->node != NULL)) {
25677 xmlNodePtr textChild;
25678 xmlChar *normValue;
25679 /*
25680 * VAL TODO: Normalize the value.
25681 */
25682 normValue = xmlSchemaNormalizeValue(inode->typeDef,
25683 inode->decl->value);
25684 if (normValue != NULL) {
25685 textChild = xmlNewText(BAD_CAST normValue);
25686 xmlFree(normValue);
25687 } else
25688 textChild = xmlNewText(inode->decl->value);
25689 if (textChild == NULL) {
25690 VERROR_INT("xmlSchemaValidatorPopElem",
25691 "calling xmlNewText()");
25692 goto internal_error;
25693 } else
25694 xmlAddChild(inode->node, textChild);
25695 }
25696
25697 } else if (! INODE_NILLED(inode)) {
25698 /*
25699 * 5.2.1 The element information item must be ·valid· with respect
25700 * to the ·actual type definition· as defined by Element Locally
25701 * Valid (Type) (§3.3.4).
25702 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025703 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025704 /*
25705 * SPEC (cvc-type) (3.1)
25706 * "If the type definition is a simple type definition, ..."
25707 * (3.1.3) "If clause 3.2 of Element Locally Valid
25708 * (Element) (§3.3.4) did not apply, then the ·normalized value·
25709 * must be ·valid· with respect to the type definition as defined
25710 * by String Valid (§3.14.4).
25711 */
25712 ret = xmlSchemaVCheckINodeDataType(vctxt,
25713 inode, inode->typeDef, inode->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025714 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025715 /*
25716 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
25717 * definition, then the element information item must be
25718 * ·valid· with respect to the type definition as per
25719 * Element Locally Valid (Complex Type) (§3.4.4);"
25720 *
25721 * SPEC (cvc-complex-type) (2.2)
25722 * "If the {content type} is a simple type definition, ...
25723 * the ·normalized value· of the element information item is
25724 * ·valid· with respect to that simple type definition as
25725 * defined by String Valid (§3.14.4)."
25726 */
25727 ret = xmlSchemaVCheckINodeDataType(vctxt,
25728 inode, inode->typeDef->contentTypeDef, inode->value);
25729 }
25730 if (ret != 0) {
25731 if (ret < 0) {
25732 VERROR_INT("xmlSchemaValidatorPopElem",
25733 "calling xmlSchemaVCheckCVCSimpleType()");
25734 goto internal_error;
25735 }
25736 goto end_elem;
25737 }
25738 /*
25739 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
25740 * not applied, all of the following must be true:
25741 */
25742 if ((inode->decl->value != NULL) &&
25743 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
25744
25745 /*
25746 * TODO: We will need a computed value, when comparison is
25747 * done on computed values.
25748 */
25749 /*
25750 * 5.2.2.1 The element information item must have no element
25751 * information item [children].
25752 */
25753 if (inode->flags &
25754 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
25755 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
25756 VERROR(ret, NULL,
25757 "The content must not containt element nodes since "
25758 "there is a fixed value constraint");
25759 goto end_elem;
25760 } else {
25761 /*
25762 * 5.2.2.2 The appropriate case among the following must
25763 * be true:
25764 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025765 if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025766 /*
25767 * 5.2.2.2.1 If the {content type} of the ·actual type
25768 * definition· is mixed, then the *initial value* of the
25769 * item must match the canonical lexical representation
25770 * of the {value constraint} value.
25771 *
25772 * ... the *initial value* of an element information
25773 * item is the string composed of, in order, the
25774 * [character code] of each character information item in
25775 * the [children] of that element information item.
25776 */
25777 if (! xmlStrEqual(inode->value, inode->decl->value)){
25778 /*
25779 * VAL TODO: Report invalid & expected values as well.
25780 * VAL TODO: Implement the canonical stuff.
25781 */
25782 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025783 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025784 ret, NULL, NULL,
25785 "The initial value '%s' does not match the fixed "
25786 "value constraint '%s'",
25787 inode->value, inode->decl->value);
25788 goto end_elem;
25789 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025790 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025791 /*
25792 * 5.2.2.2.2 If the {content type} of the ·actual type
25793 * definition· is a simple type definition, then the
25794 * *actual value* of the item must match the canonical
25795 * lexical representation of the {value constraint} value.
25796 */
25797 /*
25798 * VAL TODO: *actual value* is the normalized value, impl.
25799 * this.
25800 * VAL TODO: Report invalid & expected values as well.
25801 * VAL TODO: Implement a comparison with the computed values.
25802 */
25803 if (! xmlStrEqual(inode->value,
25804 inode->decl->value)) {
25805 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025806 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025807 ret, NULL, NULL,
25808 "The actual value '%s' does not match the fixed "
25809 "value constraint '%s'",
25810 inode->value,
25811 inode->decl->value);
25812 goto end_elem;
25813 }
25814 }
25815 }
25816 }
25817 }
25818
25819end_elem:
25820 if (vctxt->depth < 0) {
25821 /* TODO: raise error? */
25822 return (0);
25823 }
25824 if (vctxt->depth == vctxt->skipDepth)
25825 vctxt->skipDepth = -1;
25826 /*
25827 * Evaluate the history of XPath state objects.
25828 */
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000025829 if (inode->appliedXPath &&
25830 (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025831 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025832 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025833 * MAYBE TODO:
25834 * SPEC (6) "The element information item must be ·valid· with
25835 * respect to each of the {identity-constraint definitions} as per
25836 * Identity-constraint Satisfied (§3.11.4)."
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025837 */
25838 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025839 * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
25840 * need to be built in any case.
25841 * We will currently build IDC node-tables and bubble them only if
25842 * keyrefs do exist.
25843 */
25844
25845 /*
25846 * Add the current IDC target-nodes to the IDC node-tables.
25847 */
25848 if ((inode->idcMatchers != NULL) &&
25849 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
25850 {
25851 if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
25852 goto internal_error;
25853 }
25854 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025855 * Validate IDC keyrefs.
25856 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025857 if (vctxt->inode->hasKeyrefs)
25858 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
25859 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025860 /*
25861 * Merge/free the IDC table.
25862 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025863 if (inode->idcTable != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025864#ifdef DEBUG_IDC_NODE_TABLE
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025865 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025866 inode->nsName,
25867 inode->localName,
25868 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025869#endif
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025870 if ((vctxt->depth > 0) &&
25871 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
25872 {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025873 /*
25874 * Merge the IDC node table with the table of the parent node.
25875 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025876 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
25877 goto internal_error;
25878 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025879 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025880 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025881 * Clear the current ielem.
25882 * VAL TODO: Don't free the PSVI IDC tables if they are
25883 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025884 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025885 xmlSchemaClearElemInfo(inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025886 /*
25887 * Skip further processing if we are on the validation root.
25888 */
25889 if (vctxt->depth == 0) {
25890 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025891 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000025892 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025893 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025894 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025895 * Reset the keyrefDepth if needed.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025896 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025897 if (vctxt->aidcs != NULL) {
25898 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
25899 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025900 if (aidc->keyrefDepth == vctxt->depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025901 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025902 * A 'keyrefDepth' of a key/unique IDC matches the current
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025903 * depth, this means that we are leaving the scope of the
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025904 * top-most keyref IDC which refers to this IDC.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025905 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025906 aidc->keyrefDepth = -1;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025907 }
25908 aidc = aidc->next;
25909 } while (aidc != NULL);
25910 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025911 vctxt->depth--;
25912 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000025913 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025914 * VAL TODO: 7 If the element information item is the ·validation root·, it must be
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000025915 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
25916 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025917 return (ret);
25918
25919internal_error:
25920 vctxt->err = -1;
25921 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000025922}
25923
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025924/*
25925* 3.4.4 Complex Type Definition Validation Rules
25926* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
25927*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000025928static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025929xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000025930{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025931 xmlSchemaNodeInfoPtr pielem;
25932 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000025933 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000025934
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025935 if (vctxt->depth <= 0) {
25936 VERROR_INT("xmlSchemaValidateChildElem",
25937 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000025938 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025939 }
25940 pielem = vctxt->elemInfos[vctxt->depth -1];
25941 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
25942 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000025943 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025944 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000025945 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025946 if (INODE_NILLED(pielem)) {
25947 /*
25948 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
25949 */
25950 ACTIVATE_PARENT_ELEM;
25951 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
25952 VERROR(ret, NULL,
25953 "Neither character nor element content is allowed, "
25954 "because the element was 'nilled'");
25955 ACTIVATE_ELEM;
25956 goto unexpected_elem;
25957 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000025958
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025959 ptype = pielem->typeDef;
25960
25961 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
25962 /*
25963 * Workaround for "anyType": we have currently no content model
25964 * assigned for "anyType", so handle it explicitely.
25965 * "anyType" has an unbounded, lax "any" wildcard.
25966 */
25967 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
25968 vctxt->inode->localName,
25969 vctxt->inode->nsName);
25970
25971 if (vctxt->inode->decl == NULL) {
25972 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000025973 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025974 * Process "xsi:type".
25975 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000025976 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025977 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25978 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25979 if (iattr != NULL) {
25980 ret = xmlSchemaProcessXSIType(vctxt, iattr,
25981 &(vctxt->inode->typeDef), NULL);
25982 if (ret != 0) {
25983 if (ret == -1) {
25984 VERROR_INT("xmlSchemaValidateChildElem",
25985 "calling xmlSchemaProcessXSIType() to "
25986 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000025987 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000025988 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025989 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000025990 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025991 } else {
25992 /*
25993 * Fallback to "anyType".
25994 *
25995 * SPEC (cvc-assess-elt)
25996 * "If the item cannot be ·strictly assessed·, [...]
25997 * an element information item's schema validity may be laxly
25998 * assessed if its ·context-determined declaration· is not
25999 * skip by ·validating· with respect to the ·ur-type
26000 * definition· as per Element Locally Valid (Type) (§3.3.4)."
26001 */
26002 vctxt->inode->typeDef =
26003 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026004 }
26005 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026006 return (0);
26007 }
26008
26009 switch (ptype->contentType) {
26010 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026011 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026012 * SPEC (2.1) "If the {content type} is empty, then the
26013 * element information item has no character or element
26014 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026015 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026016 ACTIVATE_PARENT_ELEM
26017 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26018 VERROR(ret, NULL,
26019 "Element content is not allowed, "
26020 "because the content type is empty");
26021 ACTIVATE_ELEM
26022 goto unexpected_elem;
26023 break;
26024
26025 case XML_SCHEMA_CONTENT_MIXED:
26026 case XML_SCHEMA_CONTENT_ELEMENTS: {
26027 xmlRegExecCtxtPtr regexCtxt;
26028 xmlChar *values[10];
26029 int terminal, nbval = 10, nbneg;
26030
26031 /* VAL TODO: Optimized "anyType" validation.*/
26032
26033 if (ptype->contModel == NULL) {
26034 VERROR_INT("xmlSchemaValidateChildElem",
26035 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026036 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000026037 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026038 /*
26039 * Safety belf for evaluation if the cont. model was already
26040 * examined to be invalid.
26041 */
26042 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26043 VERROR_INT("xmlSchemaValidateChildElem",
26044 "validating elem, but elem content is already invalid");
26045 return (-1);
26046 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000026047
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026048 regexCtxt = pielem->regexCtxt;
26049 if (regexCtxt == NULL) {
26050 /*
26051 * Create the regex context.
26052 */
26053 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26054 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26055 vctxt);
26056 if (regexCtxt == NULL) {
26057 VERROR_INT("xmlSchemaValidateChildElem",
26058 "failed to create a regex context");
26059 return (-1);
26060 }
26061 pielem->regexCtxt = regexCtxt;
26062#ifdef DEBUG_AUTOMATA
26063 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26064 pielem->localName);
26065#endif
26066 }
26067
26068 /*
26069 * SPEC (2.4) "If the {content type} is element-only or mixed,
26070 * then the sequence of the element information item's
26071 * element information item [children], if any, taken in
26072 * order, is ·valid· with respect to the {content type}'s
26073 * particle, as defined in Element Sequence Locally Valid
26074 * (Particle) (§3.9.4)."
26075 */
26076 ret = xmlRegExecPushString2(regexCtxt,
26077 vctxt->inode->localName,
26078 vctxt->inode->nsName,
26079 vctxt->inode);
26080#ifdef DEBUG_AUTOMATA
26081 if (ret < 0)
26082 xmlGenericError(xmlGenericErrorContext,
26083 "AUTOMATON push ERROR for '%s' on '%s'\n",
26084 vctxt->inode->localName, pielem->localName);
26085 else
26086 xmlGenericError(xmlGenericErrorContext,
26087 "AUTOMATON push OK for '%s' on '%s'\n",
26088 vctxt->inode->localName, pielem->localName);
26089#endif
26090 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26091 VERROR_INT("xmlSchemaValidateChildElem",
26092 "calling xmlRegExecPushString2()");
26093 return (-1);
26094 }
26095 if (ret < 0) {
26096 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26097 &values[0], &terminal);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026098 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026099 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26100 "This element is not expected",
26101 nbval, nbneg, values);
26102 ret = vctxt->err;
26103 goto unexpected_elem;
26104 } else
26105 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000026106 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026107 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026108 case XML_SCHEMA_CONTENT_SIMPLE:
26109 case XML_SCHEMA_CONTENT_BASIC:
26110 ACTIVATE_PARENT_ELEM
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026111 if (WXS_IS_COMPLEX(ptype)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026112 /*
26113 * SPEC (cvc-complex-type) (2.2)
26114 * "If the {content type} is a simple type definition, then
26115 * the element information item has no element information
26116 * item [children], ..."
26117 */
26118 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26119 VERROR(ret, NULL, "Element content is not allowed, "
26120 "because the content type is a simple type definition");
26121 } else {
26122 /*
26123 * SPEC (cvc-type) (3.1.2) "The element information item must
26124 * have no element information item [children]."
26125 */
26126 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26127 VERROR(ret, NULL, "Element content is not allowed, "
26128 "because the type definition is simple");
26129 }
26130 ACTIVATE_ELEM
26131 ret = vctxt->err;
26132 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026133 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026134
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026135 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026136 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026137 }
26138 return (ret);
26139unexpected_elem:
26140 /*
26141 * Pop this element and set the skipDepth to skip
26142 * all further content of the parent element.
26143 */
26144 vctxt->skipDepth = vctxt->depth;
26145 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26146 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26147 return (ret);
26148}
26149
26150#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26151#define XML_SCHEMA_PUSH_TEXT_CREATED 2
26152#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26153
26154static int
26155xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26156 int nodeType, const xmlChar *value, int len,
26157 int mode, int *consumed)
26158{
26159 /*
26160 * Unfortunately we have to duplicate the text sometimes.
26161 * OPTIMIZE: Maybe we could skip it, if:
26162 * 1. content type is simple
26163 * 2. whitespace is "collapse"
26164 * 3. it consists of whitespace only
26165 *
26166 * Process character content.
26167 */
26168 if (consumed != NULL)
26169 *consumed = 0;
26170 if (INODE_NILLED(vctxt->inode)) {
26171 /*
26172 * SPEC cvc-elt (3.3.4 - 3.2.1)
26173 * "The element information item must have no character or
26174 * element information item [children]."
26175 */
26176 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26177 "Neither character nor element content is allowed "
26178 "because the element is 'nilled'");
26179 return (vctxt->err);
26180 }
26181 /*
26182 * SPEC (2.1) "If the {content type} is empty, then the
26183 * element information item has no character or element
26184 * information item [children]."
26185 */
26186 if (vctxt->inode->typeDef->contentType ==
26187 XML_SCHEMA_CONTENT_EMPTY) {
26188 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26189 "Character content is not allowed, "
26190 "because the content type is empty");
26191 return (vctxt->err);
26192 }
26193
26194 if (vctxt->inode->typeDef->contentType ==
26195 XML_SCHEMA_CONTENT_ELEMENTS) {
26196 if ((nodeType != XML_TEXT_NODE) ||
26197 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26198 /*
26199 * SPEC cvc-complex-type (2.3)
26200 * "If the {content type} is element-only, then the
26201 * element information item has no character information
26202 * item [children] other than those whose [character
26203 * code] is defined as a white space in [XML 1.0 (Second
26204 * Edition)]."
26205 */
26206 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26207 "Character content other than whitespace is not allowed "
26208 "because the content type is 'element-only'");
26209 return (vctxt->err);
26210 }
26211 return (0);
26212 }
26213
26214 if ((value == NULL) || (value[0] == 0))
26215 return (0);
26216 /*
26217 * Save the value.
26218 * NOTE that even if the content type is *mixed*, we need the
26219 * *initial value* for default/fixed value constraints.
26220 */
26221 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26222 ((vctxt->inode->decl == NULL) ||
26223 (vctxt->inode->decl->value == NULL)))
26224 return (0);
26225
26226 if (vctxt->inode->value == NULL) {
26227 /*
26228 * Set the value.
26229 */
26230 switch (mode) {
26231 case XML_SCHEMA_PUSH_TEXT_PERSIST:
26232 /*
26233 * When working on a tree.
26234 */
26235 vctxt->inode->value = value;
26236 break;
26237 case XML_SCHEMA_PUSH_TEXT_CREATED:
26238 /*
26239 * When working with the reader.
26240 * The value will be freed by the element info.
26241 */
26242 vctxt->inode->value = value;
26243 if (consumed != NULL)
26244 *consumed = 1;
26245 vctxt->inode->flags |=
26246 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26247 break;
26248 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26249 /*
26250 * When working with SAX.
26251 * The value will be freed by the element info.
26252 */
26253 if (len != -1)
26254 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26255 else
26256 vctxt->inode->value = BAD_CAST xmlStrdup(value);
26257 vctxt->inode->flags |=
26258 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26259 break;
26260 default:
26261 break;
26262 }
26263 } else {
26264 /*
26265 * Concat the value.
26266 */
26267 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000026268 vctxt->inode->value = BAD_CAST xmlStrncat(
26269 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026270 } else {
26271 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026272 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026273 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26274 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026275 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026276
26277 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000026278}
26279
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026280static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026281xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000026282{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026283 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000026284
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026285 if ((vctxt->skipDepth != -1) &&
26286 (vctxt->depth >= vctxt->skipDepth)) {
26287 VERROR_INT("xmlSchemaValidateElem",
26288 "in skip-state");
26289 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026290 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026291 if (vctxt->xsiAssemble) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026292 /*
26293 * URGENT TODO: Better to fully stop validation
26294 * if there was an error during dynamic schema construction.
26295 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026296 if (xmlSchemaAssembleByXSI(vctxt) == -1)
26297 goto internal_error;
26298 }
26299 if (vctxt->depth > 0) {
26300 /*
26301 * Validate this element against the content model
26302 * of the parent.
26303 */
26304 ret = xmlSchemaValidateChildElem(vctxt);
26305 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026306 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026307 VERROR_INT("xmlSchemaValidateElem",
26308 "calling xmlSchemaStreamValidateChildElement()");
26309 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026310 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026311 goto exit;
26312 }
26313 if (vctxt->depth == vctxt->skipDepth)
26314 goto exit;
26315 if ((vctxt->inode->decl == NULL) &&
26316 (vctxt->inode->typeDef == NULL)) {
26317 VERROR_INT("xmlSchemaValidateElem",
26318 "the child element was valid but neither the "
26319 "declaration nor the type was set");
26320 goto internal_error;
26321 }
26322 } else {
26323 /*
26324 * Get the declaration of the validation root.
26325 */
26326 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26327 vctxt->inode->localName,
26328 vctxt->inode->nsName);
26329 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026330 ret = XML_SCHEMAV_CVC_ELT_1;
26331 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026332 "No matching global declaration available "
26333 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026334 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026335 }
26336 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026337
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026338 if (vctxt->inode->decl == NULL)
26339 goto type_validation;
26340
26341 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26342 int skip;
26343 /*
26344 * Wildcards.
26345 */
26346 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26347 if (ret != 0) {
26348 if (ret < 0) {
26349 VERROR_INT("xmlSchemaValidateElem",
26350 "calling xmlSchemaValidateElemWildcard()");
26351 goto internal_error;
26352 }
26353 goto exit;
26354 }
26355 if (skip) {
26356 vctxt->skipDepth = vctxt->depth;
26357 goto exit;
26358 }
26359 /*
26360 * The declaration might be set by the wildcard validation,
26361 * when the processContents is "lax" or "strict".
26362 */
26363 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26364 /*
26365 * Clear the "decl" field to not confuse further processing.
26366 */
26367 vctxt->inode->decl = NULL;
26368 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026369 }
Daniel Veillard4255d502002-04-16 15:50:10 +000026370 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026371 /*
26372 * Validate against the declaration.
26373 */
26374 ret = xmlSchemaValidateElemDecl(vctxt);
26375 if (ret != 0) {
26376 if (ret < 0) {
26377 VERROR_INT("xmlSchemaValidateElem",
26378 "calling xmlSchemaValidateElemDecl()");
26379 goto internal_error;
26380 }
26381 goto exit;
26382 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026383 /*
26384 * Validate against the type definition.
26385 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026386type_validation:
26387
26388 if (vctxt->inode->typeDef == NULL) {
26389 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26390 ret = XML_SCHEMAV_CVC_TYPE_1;
26391 VERROR(ret, NULL,
26392 "The type definition is absent");
26393 goto exit;
26394 }
26395 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26396 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26397 ret = XML_SCHEMAV_CVC_TYPE_2;
26398 VERROR(ret, NULL,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026399 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026400 goto exit;
26401 }
26402 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026403 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026404 * during validation against the declaration. This must be done
26405 * _before_ attribute validation.
26406 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026407 if (vctxt->xpathStates != NULL) {
26408 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000026409 vctxt->inode->appliedXPath = 1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026410 if (ret == -1) {
26411 VERROR_INT("xmlSchemaValidateElem",
26412 "calling xmlSchemaXPathEvaluate()");
26413 goto internal_error;
26414 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026415 }
26416 /*
26417 * Validate attributes.
26418 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026419 if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026420 if ((vctxt->nbAttrInfos != 0) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026421 (vctxt->inode->typeDef->attrUses != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026422
26423 ret = xmlSchemaVAttributesComplex(vctxt);
26424 }
26425 } else if (vctxt->nbAttrInfos != 0) {
26426
26427 ret = xmlSchemaVAttributesSimple(vctxt);
26428 }
26429 /*
26430 * Clear registered attributes.
26431 */
26432 if (vctxt->nbAttrInfos != 0)
26433 xmlSchemaClearAttrInfos(vctxt);
26434 if (ret == -1) {
26435 VERROR_INT("xmlSchemaValidateElem",
26436 "calling attributes validation");
26437 goto internal_error;
26438 }
26439 /*
26440 * Don't return an error if attributes are invalid on purpose.
26441 */
26442 ret = 0;
26443
26444exit:
26445 if (ret != 0)
26446 vctxt->skipDepth = vctxt->depth;
26447 return (ret);
26448internal_error:
26449 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000026450}
26451
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026452#ifdef XML_SCHEMA_READER_ENABLED
26453static int
26454xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000026455{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026456 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
26457 int depth, nodeType, ret = 0, consumed;
26458 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000026459
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026460 vctxt->depth = -1;
26461 ret = xmlTextReaderRead(vctxt->reader);
26462 /*
26463 * Move to the document element.
26464 */
26465 while (ret == 1) {
26466 nodeType = xmlTextReaderNodeType(vctxt->reader);
26467 if (nodeType == XML_ELEMENT_NODE)
26468 goto root_found;
26469 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026470 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026471 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026472
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026473root_found:
26474
26475 do {
26476 depth = xmlTextReaderDepth(vctxt->reader);
26477 nodeType = xmlTextReaderNodeType(vctxt->reader);
26478
26479 if (nodeType == XML_ELEMENT_NODE) {
26480
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026481 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026482 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26483 VERROR_INT("xmlSchemaVReaderWalk",
26484 "calling xmlSchemaValidatorPushElem()");
26485 goto internal_error;
26486 }
26487 ielem = vctxt->inode;
26488 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
26489 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
26490 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
26491 /*
26492 * Is the element empty?
26493 */
26494 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
26495 if (ret == -1) {
26496 VERROR_INT("xmlSchemaVReaderWalk",
26497 "calling xmlTextReaderIsEmptyElement()");
26498 goto internal_error;
26499 }
26500 if (ret) {
26501 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26502 }
26503 /*
26504 * Register attributes.
26505 */
26506 vctxt->nbAttrInfos = 0;
26507 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
26508 if (ret == -1) {
26509 VERROR_INT("xmlSchemaVReaderWalk",
26510 "calling xmlTextReaderMoveToFirstAttribute()");
26511 goto internal_error;
26512 }
26513 if (ret == 1) {
26514 do {
26515 /*
26516 * VAL TODO: How do we know that the reader works on a
26517 * node tree, to be able to pass a node here?
26518 */
26519 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
26520 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
26521 xmlTextReaderNamespaceUri(vctxt->reader), 1,
26522 xmlTextReaderValue(vctxt->reader), 1) == -1) {
26523
26524 VERROR_INT("xmlSchemaVReaderWalk",
26525 "calling xmlSchemaValidatorPushAttribute()");
26526 goto internal_error;
26527 }
26528 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
26529 if (ret == -1) {
26530 VERROR_INT("xmlSchemaVReaderWalk",
26531 "calling xmlTextReaderMoveToFirstAttribute()");
26532 goto internal_error;
26533 }
26534 } while (ret == 1);
26535 /*
26536 * Back to element position.
26537 */
26538 ret = xmlTextReaderMoveToElement(vctxt->reader);
26539 if (ret == -1) {
26540 VERROR_INT("xmlSchemaVReaderWalk",
26541 "calling xmlTextReaderMoveToElement()");
26542 goto internal_error;
26543 }
26544 }
26545 /*
26546 * Validate the element.
26547 */
26548 ret= xmlSchemaValidateElem(vctxt);
26549 if (ret != 0) {
26550 if (ret == -1) {
26551 VERROR_INT("xmlSchemaVReaderWalk",
26552 "calling xmlSchemaValidateElem()");
26553 goto internal_error;
26554 }
26555 goto exit;
26556 }
26557 if (vctxt->depth == vctxt->skipDepth) {
26558 int curDepth;
26559 /*
26560 * Skip all content.
26561 */
26562 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
26563 ret = xmlTextReaderRead(vctxt->reader);
26564 curDepth = xmlTextReaderDepth(vctxt->reader);
26565 while ((ret == 1) && (curDepth != depth)) {
26566 ret = xmlTextReaderRead(vctxt->reader);
26567 curDepth = xmlTextReaderDepth(vctxt->reader);
26568 }
26569 if (ret < 0) {
26570 /*
26571 * VAL TODO: A reader error occured; what to do here?
26572 */
26573 ret = 1;
26574 goto exit;
26575 }
26576 }
26577 goto leave_elem;
26578 }
26579 /*
26580 * READER VAL TODO: Is an END_ELEM really never called
26581 * if the elem is empty?
26582 */
26583 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26584 goto leave_elem;
26585 } else if (nodeType == END_ELEM) {
26586 /*
26587 * Process END of element.
26588 */
26589leave_elem:
26590 ret = xmlSchemaValidatorPopElem(vctxt);
26591 if (ret != 0) {
26592 if (ret < 0) {
26593 VERROR_INT("xmlSchemaVReaderWalk",
26594 "calling xmlSchemaValidatorPopElem()");
26595 goto internal_error;
26596 }
26597 goto exit;
26598 }
26599 if (vctxt->depth >= 0)
26600 ielem = vctxt->inode;
26601 else
26602 ielem = NULL;
26603 } else if ((nodeType == XML_TEXT_NODE) ||
26604 (nodeType == XML_CDATA_SECTION_NODE) ||
26605 (nodeType == WHTSP) ||
26606 (nodeType == SIGN_WHTSP)) {
26607 /*
26608 * Process character content.
26609 */
26610 xmlChar *value;
26611
26612 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
26613 nodeType = XML_TEXT_NODE;
26614
26615 value = xmlTextReaderValue(vctxt->reader);
26616 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
26617 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
26618 if (! consumed)
26619 xmlFree(value);
26620 if (ret == -1) {
26621 VERROR_INT("xmlSchemaVReaderWalk",
26622 "calling xmlSchemaVPushText()");
26623 goto internal_error;
26624 }
26625 } else if ((nodeType == XML_ENTITY_NODE) ||
26626 (nodeType == XML_ENTITY_REF_NODE)) {
26627 /*
26628 * VAL TODO: What to do with entities?
26629 */
26630 TODO
26631 }
26632 /*
26633 * Read next node.
26634 */
26635 ret = xmlTextReaderRead(vctxt->reader);
26636 } while (ret == 1);
26637
26638exit:
26639 return (ret);
26640internal_error:
26641 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000026642}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026643#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000026644
26645/************************************************************************
26646 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026647 * SAX validation handlers *
Daniel Veillard4255d502002-04-16 15:50:10 +000026648 * *
26649 ************************************************************************/
26650
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026651/*
26652* Process text content.
26653*/
26654static void
26655xmlSchemaSAXHandleText(void *ctx,
26656 const xmlChar * ch,
26657 int len)
26658{
26659 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26660
26661 if (vctxt->depth < 0)
26662 return;
26663 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26664 return;
26665 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26666 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26667 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
26668 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
26669 VERROR_INT("xmlSchemaSAXHandleCDataSection",
26670 "calling xmlSchemaVPushText()");
26671 vctxt->err = -1;
26672 xmlStopParser(vctxt->parserCtxt);
26673 }
26674}
26675
26676/*
26677* Process CDATA content.
26678*/
26679static void
26680xmlSchemaSAXHandleCDataSection(void *ctx,
26681 const xmlChar * ch,
26682 int len)
26683{
26684 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26685
26686 if (vctxt->depth < 0)
26687 return;
26688 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26689 return;
26690 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26691 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26692 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
26693 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
26694 VERROR_INT("xmlSchemaSAXHandleCDataSection",
26695 "calling xmlSchemaVPushText()");
26696 vctxt->err = -1;
26697 xmlStopParser(vctxt->parserCtxt);
26698 }
26699}
26700
26701static void
26702xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
26703 const xmlChar * name ATTRIBUTE_UNUSED)
26704{
26705 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26706
26707 if (vctxt->depth < 0)
26708 return;
26709 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26710 return;
26711 /* SAX VAL TODO: What to do here? */
26712 TODO
26713}
26714
26715static void
26716xmlSchemaSAXHandleStartElementNs(void *ctx,
26717 const xmlChar * localname,
26718 const xmlChar * prefix ATTRIBUTE_UNUSED,
26719 const xmlChar * URI,
26720 int nb_namespaces,
26721 const xmlChar ** namespaces,
26722 int nb_attributes,
26723 int nb_defaulted ATTRIBUTE_UNUSED,
26724 const xmlChar ** attributes)
26725{
26726 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26727 int ret;
26728 xmlSchemaNodeInfoPtr ielem;
26729 int i, j;
26730
26731 /*
26732 * SAX VAL TODO: What to do with nb_defaulted?
26733 */
26734 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026735 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026736 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026737 vctxt->depth++;
26738 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026739 return;
26740 /*
26741 * Push the element.
26742 */
26743 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26744 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26745 "calling xmlSchemaValidatorPushElem()");
26746 goto internal_error;
26747 }
26748 ielem = vctxt->inode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026749 /*
26750 * TODO: Is this OK?
26751 */
26752 ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026753 ielem->localName = localname;
26754 ielem->nsName = URI;
26755 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26756 /*
26757 * Register namespaces on the elem info.
26758 */
26759 if (nb_namespaces != 0) {
26760 /*
26761 * Although the parser builds its own namespace list,
26762 * we have no access to it, so we'll use an own one.
26763 */
26764 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
26765 /*
26766 * Store prefix and namespace name.
26767 */
26768 if (ielem->nsBindings == NULL) {
26769 ielem->nsBindings =
26770 (const xmlChar **) xmlMalloc(10 *
26771 sizeof(const xmlChar *));
26772 if (ielem->nsBindings == NULL) {
26773 xmlSchemaVErrMemory(vctxt,
26774 "allocating namespace bindings for SAX validation",
26775 NULL);
26776 goto internal_error;
26777 }
26778 ielem->nbNsBindings = 0;
26779 ielem->sizeNsBindings = 5;
26780 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
26781 ielem->sizeNsBindings *= 2;
26782 ielem->nsBindings =
26783 (const xmlChar **) xmlRealloc(
26784 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026785 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026786 if (ielem->nsBindings == NULL) {
26787 xmlSchemaVErrMemory(vctxt,
26788 "re-allocating namespace bindings for SAX validation",
26789 NULL);
26790 goto internal_error;
26791 }
26792 }
26793
26794 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
26795 if (namespaces[j+1][0] == 0) {
26796 /*
26797 * Handle xmlns="".
26798 */
26799 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
26800 } else
26801 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
26802 namespaces[j+1];
26803 ielem->nbNsBindings++;
26804 }
26805 }
26806 /*
26807 * Register attributes.
26808 * SAX VAL TODO: We are not adding namespace declaration
26809 * attributes yet.
26810 */
26811 if (nb_attributes != 0) {
26812 xmlChar *value;
26813
26814 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
26815 /*
26816 * Duplicate the value.
26817 */
26818 value = xmlStrndup(attributes[j+3],
26819 attributes[j+4] - attributes[j+3]);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026820 /*
26821 * TODO: Set the node line.
26822 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026823 ret = xmlSchemaValidatorPushAttribute(vctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026824 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026825 value, 1);
26826 if (ret == -1) {
26827 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26828 "calling xmlSchemaValidatorPushAttribute()");
26829 goto internal_error;
26830 }
26831 }
26832 }
26833 /*
26834 * Validate the element.
26835 */
26836 ret = xmlSchemaValidateElem(vctxt);
26837 if (ret != 0) {
26838 if (ret == -1) {
26839 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26840 "calling xmlSchemaValidateElem()");
26841 goto internal_error;
26842 }
26843 goto exit;
26844 }
26845
26846exit:
26847 return;
26848internal_error:
26849 vctxt->err = -1;
26850 xmlStopParser(vctxt->parserCtxt);
26851 return;
26852}
26853
26854static void
26855xmlSchemaSAXHandleEndElementNs(void *ctx,
26856 const xmlChar * localname ATTRIBUTE_UNUSED,
26857 const xmlChar * prefix ATTRIBUTE_UNUSED,
26858 const xmlChar * URI ATTRIBUTE_UNUSED)
26859{
26860 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26861 int res;
26862
26863 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026864 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026865 */
26866 if (vctxt->skipDepth != -1) {
26867 if (vctxt->depth > vctxt->skipDepth) {
26868 vctxt->depth--;
26869 return;
26870 } else
26871 vctxt->skipDepth = -1;
26872 }
26873 /*
26874 * SAX VAL TODO: Just a temporary check.
26875 */
26876 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
26877 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
26878 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
26879 "elem pop mismatch");
26880 }
26881 res = xmlSchemaValidatorPopElem(vctxt);
26882 if (res != 0) {
26883 if (res < 0) {
26884 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
26885 "calling xmlSchemaValidatorPopElem()");
26886 goto internal_error;
26887 }
26888 goto exit;
26889 }
26890exit:
26891 return;
26892internal_error:
26893 vctxt->err = -1;
26894 xmlStopParser(vctxt->parserCtxt);
26895 return;
26896}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026897
Daniel Veillard4255d502002-04-16 15:50:10 +000026898/************************************************************************
26899 * *
26900 * Validation interfaces *
26901 * *
26902 ************************************************************************/
26903
26904/**
26905 * xmlSchemaNewValidCtxt:
26906 * @schema: a precompiled XML Schemas
26907 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026908 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000026909 *
26910 * Returns the validation context or NULL in case of error
26911 */
26912xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000026913xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
26914{
Daniel Veillard4255d502002-04-16 15:50:10 +000026915 xmlSchemaValidCtxtPtr ret;
26916
26917 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
26918 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000026919 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000026920 return (NULL);
26921 }
26922 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026923 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026924 ret->dict = xmlDictCreate();
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000026925 ret->nodeQNames = xmlSchemaItemListCreate();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026926 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000026927 return (ret);
26928}
26929
26930/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026931 * xmlSchemaClearValidCtxt:
26932 * @ctxt: the schema validation context
26933 *
26934 * Free the resources associated to the schema validation context;
26935 * leaves some fields alive intended for reuse of the context.
26936 */
26937static void
26938xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
26939{
26940 if (vctxt == NULL)
26941 return;
26942
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026943 /*
26944 * TODO: Should we clear the flags?
26945 * Might be problematic if one reuses the context
26946 * and assumes that the options remain the same.
26947 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026948 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026949 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026950 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000026951#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026952 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000026953#endif
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026954 vctxt->hasKeyrefs = 0;
26955
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026956 if (vctxt->value != NULL) {
26957 xmlSchemaFreeValue(vctxt->value);
26958 vctxt->value = NULL;
26959 }
26960 /*
26961 * Augmented IDC information.
26962 */
26963 if (vctxt->aidcs != NULL) {
26964 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
26965 do {
26966 next = cur->next;
26967 xmlFree(cur);
26968 cur = next;
26969 } while (cur != NULL);
26970 vctxt->aidcs = NULL;
26971 }
26972 if (vctxt->idcNodes != NULL) {
26973 int i;
26974 xmlSchemaPSVIIDCNodePtr item;
26975
26976 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026977 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026978 xmlFree(item->keys);
26979 xmlFree(item);
26980 }
26981 xmlFree(vctxt->idcNodes);
26982 vctxt->idcNodes = NULL;
26983 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026984 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026985 * Note that we won't delete the XPath state pool here.
26986 */
26987 if (vctxt->xpathStates != NULL) {
26988 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
26989 vctxt->xpathStates = NULL;
26990 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026991 /*
26992 * Attribute info.
26993 */
26994 if (vctxt->nbAttrInfos != 0) {
26995 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026996 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026997 /*
26998 * Element info.
26999 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027000 if (vctxt->elemInfos != NULL) {
27001 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027002 xmlSchemaNodeInfoPtr ei;
27003
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027004 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027005 ei = vctxt->elemInfos[i];
27006 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027007 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027008 xmlSchemaClearElemInfo(ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027009 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027010 }
27011 xmlSchemaItemListClear(vctxt->nodeQNames);
27012 /* Recreate the dict. */
27013 xmlDictFree(vctxt->dict);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027014 /*
27015 * TODO: Is is save to recreate it? Do we have a scenario
27016 * where the user provides the dict?
27017 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027018 vctxt->dict = xmlDictCreate();
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027019}
27020
27021/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027022 * xmlSchemaFreeValidCtxt:
27023 * @ctxt: the schema validation context
27024 *
27025 * Free the resources associated to the schema validation context
27026 */
27027void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027028xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27029{
Daniel Veillard4255d502002-04-16 15:50:10 +000027030 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027031 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000027032 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027033 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027034 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027035 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027036 if (ctxt->idcNodes != NULL) {
27037 int i;
27038 xmlSchemaPSVIIDCNodePtr item;
27039
27040 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027041 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027042 xmlFree(item->keys);
27043 xmlFree(item);
27044 }
27045 xmlFree(ctxt->idcNodes);
27046 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027047 if (ctxt->idcKeys != NULL) {
27048 int i;
27049 for (i = 0; i < ctxt->nbIdcKeys; i++)
27050 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27051 xmlFree(ctxt->idcKeys);
27052 }
27053
27054 if (ctxt->xpathStates != NULL)
27055 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27056 if (ctxt->xpathStatePool != NULL)
27057 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27058
27059 /*
27060 * Augmented IDC information.
27061 */
27062 if (ctxt->aidcs != NULL) {
27063 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27064 do {
27065 next = cur->next;
27066 xmlFree(cur);
27067 cur = next;
27068 } while (cur != NULL);
27069 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027070 if (ctxt->attrInfos != NULL) {
27071 int i;
27072 xmlSchemaAttrInfoPtr attr;
27073
27074 /* Just a paranoid call to the cleanup. */
27075 if (ctxt->nbAttrInfos != 0)
27076 xmlSchemaClearAttrInfos(ctxt);
27077 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27078 attr = ctxt->attrInfos[i];
27079 xmlFree(attr);
27080 }
27081 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000027082 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027083 if (ctxt->elemInfos != NULL) {
27084 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027085 xmlSchemaNodeInfoPtr ei;
27086
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027087 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027088 ei = ctxt->elemInfos[i];
27089 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027090 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027091 xmlSchemaClearElemInfo(ei);
27092 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027093 }
27094 xmlFree(ctxt->elemInfos);
27095 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027096 if (ctxt->nodeQNames != NULL)
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000027097 xmlSchemaItemListFree(ctxt->nodeQNames);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027098 if (ctxt->dict != NULL)
27099 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000027100 xmlFree(ctxt);
27101}
27102
27103/**
Daniel Veillardf10ae122005-07-10 19:03:16 +000027104 * xmlSchemaIsValid:
27105 * @ctxt: the schema validation context
27106 *
27107 * Check if any error was detected during validation.
27108 *
27109 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27110 * of internal error.
27111 */
27112int
27113xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27114{
27115 if (ctxt == NULL)
27116 return(-1);
27117 return(ctxt->err == 0);
27118}
27119
27120/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027121 * xmlSchemaSetValidErrors:
27122 * @ctxt: a schema validation context
27123 * @err: the error function
27124 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000027125 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000027126 *
William M. Brack2f2a6632004-08-20 23:09:47 +000027127 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000027128 */
27129void
27130xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027131 xmlSchemaValidityErrorFunc err,
27132 xmlSchemaValidityWarningFunc warn, void *ctx)
27133{
Daniel Veillard4255d502002-04-16 15:50:10 +000027134 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027135 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000027136 ctxt->error = err;
27137 ctxt->warning = warn;
27138 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027139 if (ctxt->pctxt != NULL)
27140 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000027141}
27142
27143/**
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027144 * xmlSchemaSetValidStructuredErrors:
27145 * @ctxt: a schema validation context
27146 * @serror: the structured error function
27147 * @ctx: the functions context
27148 *
27149 * Set the structured error callback
27150 */
27151void
27152xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
27153 xmlStructuredErrorFunc serror, void *ctx)
27154{
27155 if (ctxt == NULL)
27156 return;
27157 ctxt->serror = serror;
27158 ctxt->error = NULL;
27159 ctxt->warning = NULL;
27160 ctxt->userData = ctx;
27161}
27162
27163/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000027164 * xmlSchemaGetValidErrors:
27165 * @ctxt: a XML-Schema validation context
27166 * @err: the error function result
27167 * @warn: the warning function result
27168 * @ctx: the functions context result
27169 *
27170 * Get the error and warning callback informations
27171 *
27172 * Returns -1 in case of error and 0 otherwise
27173 */
27174int
27175xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27176 xmlSchemaValidityErrorFunc * err,
27177 xmlSchemaValidityWarningFunc * warn, void **ctx)
27178{
27179 if (ctxt == NULL)
27180 return (-1);
27181 if (err != NULL)
27182 *err = ctxt->error;
27183 if (warn != NULL)
27184 *warn = ctxt->warning;
27185 if (ctx != NULL)
27186 *ctx = ctxt->userData;
27187 return (0);
27188}
27189
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027190
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027191/**
Daniel Veillard6927b102004-10-27 17:29:04 +000027192 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027193 * @ctxt: a schema validation context
27194 * @options: a combination of xmlSchemaValidOption
27195 *
27196 * Sets the options to be used during the validation.
27197 *
27198 * Returns 0 in case of success, -1 in case of an
27199 * API error.
27200 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027201int
27202xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27203 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027204
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027205{
27206 int i;
27207
27208 if (ctxt == NULL)
27209 return (-1);
27210 /*
27211 * WARNING: Change the start value if adding to the
27212 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027213 * TODO: Is there an other, more easy to maintain,
27214 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027215 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027216 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027217 if (options & 1<<i)
27218 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027219 }
27220 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027221 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027222}
27223
27224/**
Daniel Veillard6927b102004-10-27 17:29:04 +000027225 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027226 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027227 *
William M. Brack21e4ef22005-01-02 09:53:13 +000027228 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027229 *
William M. Brack21e4ef22005-01-02 09:53:13 +000027230 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027231 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027232int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027233xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027234
27235{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027236 if (ctxt == NULL)
27237 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027238 else
27239 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027240}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027241
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027242static int
27243xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27244{
27245 xmlAttrPtr attr;
27246 int ret = 0;
27247 xmlSchemaNodeInfoPtr ielem = NULL;
27248 xmlNodePtr node, valRoot;
27249 const xmlChar *nsName;
27250
27251 /* DOC VAL TODO: Move this to the start function. */
27252 valRoot = xmlDocGetRootElement(vctxt->doc);
27253 if (valRoot == NULL) {
27254 /* VAL TODO: Error code? */
27255 VERROR(1, NULL, "The document has no document element");
27256 return (1);
27257 }
27258 vctxt->depth = -1;
27259 vctxt->validationRoot = valRoot;
27260 node = valRoot;
27261 while (node != NULL) {
27262 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27263 goto next_sibling;
27264 if (node->type == XML_ELEMENT_NODE) {
27265
27266 /*
27267 * Init the node-info.
27268 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000027269 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027270 if (xmlSchemaValidatorPushElem(vctxt) == -1)
27271 goto internal_error;
27272 ielem = vctxt->inode;
27273 ielem->node = node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027274 ielem->nodeLine = node->line;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027275 ielem->localName = node->name;
27276 if (node->ns != NULL)
27277 ielem->nsName = node->ns->href;
27278 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27279 /*
27280 * Register attributes.
27281 * DOC VAL TODO: We do not register namespace declaration
27282 * attributes yet.
27283 */
27284 vctxt->nbAttrInfos = 0;
27285 if (node->properties != NULL) {
27286 attr = node->properties;
27287 do {
27288 if (attr->ns != NULL)
27289 nsName = attr->ns->href;
27290 else
27291 nsName = NULL;
27292 ret = xmlSchemaValidatorPushAttribute(vctxt,
27293 (xmlNodePtr) attr,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027294 /*
27295 * Note that we give it the line number of the
27296 * parent element.
27297 */
27298 ielem->nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027299 attr->name, nsName, 0,
27300 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27301 if (ret == -1) {
27302 VERROR_INT("xmlSchemaDocWalk",
27303 "calling xmlSchemaValidatorPushAttribute()");
27304 goto internal_error;
27305 }
27306 attr = attr->next;
27307 } while (attr);
27308 }
27309 /*
27310 * Validate the element.
27311 */
27312 ret = xmlSchemaValidateElem(vctxt);
27313 if (ret != 0) {
27314 if (ret == -1) {
27315 VERROR_INT("xmlSchemaDocWalk",
27316 "calling xmlSchemaValidateElem()");
27317 goto internal_error;
27318 }
27319 /*
27320 * Don't stop validation; just skip the content
27321 * of this element.
27322 */
27323 goto leave_node;
27324 }
27325 if ((vctxt->skipDepth != -1) &&
27326 (vctxt->depth >= vctxt->skipDepth))
27327 goto leave_node;
27328 } else if ((node->type == XML_TEXT_NODE) ||
27329 (node->type == XML_CDATA_SECTION_NODE)) {
27330 /*
27331 * Process character content.
27332 */
27333 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27334 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27335 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27336 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27337 if (ret < 0) {
27338 VERROR_INT("xmlSchemaVDocWalk",
27339 "calling xmlSchemaVPushText()");
27340 goto internal_error;
27341 }
27342 /*
27343 * DOC VAL TODO: Should we skip further validation of the
27344 * element content here?
27345 */
27346 } else if ((node->type == XML_ENTITY_NODE) ||
27347 (node->type == XML_ENTITY_REF_NODE)) {
27348 /*
27349 * DOC VAL TODO: What to do with entities?
27350 */
27351 TODO
27352 } else {
27353 goto leave_node;
27354 /*
27355 * DOC VAL TODO: XInclude nodes, etc.
27356 */
27357 }
27358 /*
27359 * Walk the doc.
27360 */
27361 if (node->children != NULL) {
27362 node = node->children;
27363 continue;
27364 }
27365leave_node:
27366 if (node->type == XML_ELEMENT_NODE) {
27367 /*
27368 * Leaving the scope of an element.
27369 */
27370 if (node != vctxt->inode->node) {
27371 VERROR_INT("xmlSchemaVDocWalk",
27372 "element position mismatch");
27373 goto internal_error;
27374 }
27375 ret = xmlSchemaValidatorPopElem(vctxt);
27376 if (ret != 0) {
27377 if (ret < 0) {
27378 VERROR_INT("xmlSchemaVDocWalk",
27379 "calling xmlSchemaValidatorPopElem()");
27380 goto internal_error;
27381 }
27382 }
27383 if (node == valRoot)
27384 goto exit;
27385 }
27386next_sibling:
27387 if (node->next != NULL)
27388 node = node->next;
27389 else {
27390 node = node->parent;
27391 goto leave_node;
27392 }
27393 }
27394
27395exit:
27396 return (ret);
27397internal_error:
27398 return (-1);
27399}
27400
27401static int
Daniel Veillardf10ae122005-07-10 19:03:16 +000027402xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027403 /*
27404 * Some initialization.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027405 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027406 vctxt->err = 0;
27407 vctxt->nberrors = 0;
27408 vctxt->depth = -1;
27409 vctxt->skipDepth = -1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027410 vctxt->xsiAssemble = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027411 vctxt->hasKeyrefs = 0;
27412#ifdef ENABLE_IDC_NODE_TABLES
27413 vctxt->createIDCNodeTables = 1;
27414#else
27415 vctxt->createIDCNodeTables = 0;
27416#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027417 /*
27418 * Create a schema + parser if necessary.
27419 */
27420 if (vctxt->schema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027421 xmlSchemaParserCtxtPtr pctxt;
27422
27423 vctxt->xsiAssemble = 1;
27424 /*
27425 * If not schema was given then we will create a schema
27426 * dynamically using XSI schema locations.
27427 *
27428 * Create the schema parser context.
27429 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027430 if ((vctxt->pctxt == NULL) &&
27431 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
27432 return (-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027433 pctxt = vctxt->pctxt;
27434 pctxt->xsiAssemble = 1;
27435 /*
27436 * Create the schema.
27437 */
27438 vctxt->schema = xmlSchemaNewSchema(pctxt);
27439 if (vctxt->schema == NULL)
27440 return (-1);
27441 /*
27442 * Create the schema construction context.
27443 */
27444 pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
27445 if (pctxt->constructor == NULL)
27446 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000027447 pctxt->constructor->mainSchema = vctxt->schema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027448 /*
27449 * Take ownership of the constructor to be able to free it.
27450 */
27451 pctxt->ownsConstructor = 1;
27452 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027453 /*
27454 * Augment the IDC definitions.
27455 */
27456 if (vctxt->schema->idcDef != NULL) {
27457 xmlHashScan(vctxt->schema->idcDef,
27458 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
27459 }
Daniel Veillardf10ae122005-07-10 19:03:16 +000027460 return(0);
27461}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027462
Daniel Veillardf10ae122005-07-10 19:03:16 +000027463static void
27464xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027465 if (vctxt->xsiAssemble) {
27466 if (vctxt->schema != NULL) {
27467 xmlSchemaFree(vctxt->schema);
27468 vctxt->schema = NULL;
27469 }
27470 }
27471 xmlSchemaClearValidCtxt(vctxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +000027472}
27473
27474static int
27475xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
27476{
27477 int ret = 0;
27478
27479 if (xmlSchemaPreRun(vctxt) < 0)
27480 return(-1);
27481
27482 if (vctxt->doc != NULL) {
27483 /*
27484 * Tree validation.
27485 */
27486 ret = xmlSchemaVDocWalk(vctxt);
27487#ifdef LIBXML_READER_ENABLED
27488 } else if (vctxt->reader != NULL) {
27489 /*
27490 * XML Reader validation.
27491 */
27492#ifdef XML_SCHEMA_READER_ENABLED
27493 ret = xmlSchemaVReaderWalk(vctxt);
27494#endif
27495#endif
27496 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
27497 /*
27498 * SAX validation.
27499 */
27500 ret = xmlParseDocument(vctxt->parserCtxt);
27501 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027502 VERROR_INT("xmlSchemaVStart",
Daniel Veillardf10ae122005-07-10 19:03:16 +000027503 "no instance to validate");
27504 ret = -1;
27505 }
27506
27507 xmlSchemaPostRun(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027508 if (ret == 0)
27509 ret = vctxt->err;
27510 return (ret);
27511}
27512
27513/**
27514 * xmlSchemaValidateOneElement:
27515 * @ctxt: a schema validation context
27516 * @elem: an element node
27517 *
27518 * Validate a branch of a tree, starting with the given @elem.
27519 *
27520 * Returns 0 if the element and its subtree is valid, a positive error
27521 * code number otherwise and -1 in case of an internal or API error.
27522 */
27523int
27524xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
27525{
27526 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
27527 return (-1);
27528
27529 if (ctxt->schema == NULL)
27530 return (-1);
27531
27532 ctxt->doc = elem->doc;
27533 ctxt->node = elem;
27534 ctxt->validationRoot = elem;
27535 return(xmlSchemaVStart(ctxt));
27536}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027537
Daniel Veillard259f0df2004-08-18 09:13:18 +000027538/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027539 * xmlSchemaValidateDoc:
27540 * @ctxt: a schema validation context
27541 * @doc: a parsed document tree
27542 *
27543 * Validate a document tree in memory.
27544 *
27545 * Returns 0 if the document is schemas valid, a positive error code
27546 * number otherwise and -1 in case of internal or API error.
27547 */
27548int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027549xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
27550{
Daniel Veillard4255d502002-04-16 15:50:10 +000027551 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027552 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000027553
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027554 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027555 ctxt->node = xmlDocGetRootElement(doc);
27556 if (ctxt->node == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027557 xmlSchemaCustomErr(ACTXT_CAST ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027558 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
27559 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027560 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027561 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027562 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027563 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027564 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000027565}
27566
Daniel Veillardcdc82732005-07-08 15:04:06 +000027567
27568/************************************************************************
27569 * *
27570 * Function and data for SAX streaming API *
27571 * *
27572 ************************************************************************/
27573typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
27574typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
27575
27576struct _xmlSchemaSplitSAXData {
27577 xmlSAXHandlerPtr user_sax;
27578 void *user_data;
27579 xmlSchemaValidCtxtPtr ctxt;
27580 xmlSAXHandlerPtr schemas_sax;
27581};
27582
Daniel Veillard971771e2005-07-09 17:32:57 +000027583#define XML_SAX_PLUG_MAGIC 0xdc43ba21
27584
27585struct _xmlSchemaSAXPlug {
27586 unsigned int magic;
27587
27588 /* the original callbacks informations */
27589 xmlSAXHandlerPtr *user_sax_ptr;
27590 xmlSAXHandlerPtr user_sax;
27591 void **user_data_ptr;
27592 void *user_data;
27593
27594 /* the block plugged back and validation informations */
27595 xmlSAXHandler schemas_sax;
27596 xmlSchemaValidCtxtPtr ctxt;
27597};
27598
Daniel Veillardcdc82732005-07-08 15:04:06 +000027599/* All those functions just bounces to the user provided SAX handlers */
27600static void
27601internalSubsetSplit(void *ctx, const xmlChar *name,
27602 const xmlChar *ExternalID, const xmlChar *SystemID)
27603{
Daniel Veillard971771e2005-07-09 17:32:57 +000027604 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027605 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27606 (ctxt->user_sax->internalSubset != NULL))
27607 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
27608 SystemID);
27609}
27610
27611static int
27612isStandaloneSplit(void *ctx)
27613{
Daniel Veillard971771e2005-07-09 17:32:57 +000027614 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027615 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27616 (ctxt->user_sax->isStandalone != NULL))
27617 return(ctxt->user_sax->isStandalone(ctxt->user_data));
27618 return(0);
27619}
27620
27621static int
27622hasInternalSubsetSplit(void *ctx)
27623{
Daniel Veillard971771e2005-07-09 17:32:57 +000027624 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027625 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27626 (ctxt->user_sax->hasInternalSubset != NULL))
27627 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
27628 return(0);
27629}
27630
27631static int
27632hasExternalSubsetSplit(void *ctx)
27633{
Daniel Veillard971771e2005-07-09 17:32:57 +000027634 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027635 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27636 (ctxt->user_sax->hasExternalSubset != NULL))
27637 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
27638 return(0);
27639}
27640
27641static void
27642externalSubsetSplit(void *ctx, const xmlChar *name,
27643 const xmlChar *ExternalID, const xmlChar *SystemID)
27644{
Daniel Veillard971771e2005-07-09 17:32:57 +000027645 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027646 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27647 (ctxt->user_sax->internalSubset != NULL))
27648 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
27649 SystemID);
27650}
27651
27652static xmlParserInputPtr
27653resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
27654{
Daniel Veillard971771e2005-07-09 17:32:57 +000027655 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027656 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27657 (ctxt->user_sax->resolveEntity != NULL))
27658 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
27659 systemId));
27660 return(NULL);
27661}
27662
27663static xmlEntityPtr
27664getEntitySplit(void *ctx, const xmlChar *name)
27665{
Daniel Veillard971771e2005-07-09 17:32:57 +000027666 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027667 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27668 (ctxt->user_sax->getEntity != NULL))
27669 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
27670 return(NULL);
27671}
27672
27673static xmlEntityPtr
27674getParameterEntitySplit(void *ctx, const xmlChar *name)
27675{
Daniel Veillard971771e2005-07-09 17:32:57 +000027676 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027677 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27678 (ctxt->user_sax->getParameterEntity != NULL))
27679 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
27680 return(NULL);
27681}
27682
27683
27684static void
27685entityDeclSplit(void *ctx, const xmlChar *name, int type,
27686 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
27687{
Daniel Veillard971771e2005-07-09 17:32:57 +000027688 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027689 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27690 (ctxt->user_sax->entityDecl != NULL))
27691 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
27692 systemId, content);
27693}
27694
27695static void
27696attributeDeclSplit(void *ctx, const xmlChar * elem,
27697 const xmlChar * name, int type, int def,
27698 const xmlChar * defaultValue, xmlEnumerationPtr tree)
27699{
Daniel Veillard971771e2005-07-09 17:32:57 +000027700 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027701 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27702 (ctxt->user_sax->attributeDecl != NULL)) {
27703 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
27704 def, defaultValue, tree);
27705 } else {
27706 xmlFreeEnumeration(tree);
27707 }
27708}
27709
27710static void
27711elementDeclSplit(void *ctx, const xmlChar *name, int type,
27712 xmlElementContentPtr content)
27713{
Daniel Veillard971771e2005-07-09 17:32:57 +000027714 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027715 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27716 (ctxt->user_sax->elementDecl != NULL))
27717 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
27718}
27719
27720static void
27721notationDeclSplit(void *ctx, const xmlChar *name,
27722 const xmlChar *publicId, const xmlChar *systemId)
27723{
Daniel Veillard971771e2005-07-09 17:32:57 +000027724 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027725 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27726 (ctxt->user_sax->notationDecl != NULL))
27727 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
27728 systemId);
27729}
27730
27731static void
27732unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
27733 const xmlChar *publicId, const xmlChar *systemId,
27734 const xmlChar *notationName)
27735{
Daniel Veillard971771e2005-07-09 17:32:57 +000027736 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027737 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27738 (ctxt->user_sax->unparsedEntityDecl != NULL))
27739 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
27740 systemId, notationName);
27741}
27742
27743static void
27744setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
27745{
Daniel Veillard971771e2005-07-09 17:32:57 +000027746 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027747 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27748 (ctxt->user_sax->setDocumentLocator != NULL))
27749 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
27750}
27751
27752static void
27753startDocumentSplit(void *ctx)
27754{
Daniel Veillard971771e2005-07-09 17:32:57 +000027755 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027756 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27757 (ctxt->user_sax->startDocument != NULL))
27758 ctxt->user_sax->startDocument(ctxt->user_data);
27759}
27760
27761static void
27762endDocumentSplit(void *ctx)
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->endDocument != NULL))
27767 ctxt->user_sax->endDocument(ctxt->user_data);
27768}
27769
27770static void
27771processingInstructionSplit(void *ctx, const xmlChar *target,
27772 const xmlChar *data)
27773{
Daniel Veillard971771e2005-07-09 17:32:57 +000027774 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027775 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27776 (ctxt->user_sax->processingInstruction != NULL))
27777 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
27778}
27779
27780static void
27781commentSplit(void *ctx, const xmlChar *value)
27782{
Daniel Veillard971771e2005-07-09 17:32:57 +000027783 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027784 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27785 (ctxt->user_sax->comment != NULL))
27786 ctxt->user_sax->comment(ctxt->user_data, value);
27787}
27788
27789/*
27790 * Varargs error callbacks to the user application, harder ...
27791 */
27792
Daniel Veillardffa3c742005-07-21 13:24:09 +000027793static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027794warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027795 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027796 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27797 (ctxt->user_sax->warning != NULL)) {
27798 TODO
27799 }
27800}
Daniel Veillardffa3c742005-07-21 13:24:09 +000027801static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027802errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027803 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027804 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27805 (ctxt->user_sax->error != NULL)) {
27806 TODO
27807 }
27808}
Daniel Veillardffa3c742005-07-21 13:24:09 +000027809static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027810fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027811 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027812 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27813 (ctxt->user_sax->fatalError != NULL)) {
27814 TODO
27815 }
27816}
27817
27818/*
27819 * Those are function where both the user handler and the schemas handler
27820 * need to be called.
27821 */
27822static void
27823charactersSplit(void *ctx, const xmlChar *ch, int len)
27824{
Daniel Veillard971771e2005-07-09 17:32:57 +000027825 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027826 if (ctxt == NULL)
27827 return;
27828 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
27829 ctxt->user_sax->characters(ctxt->user_data, ch, len);
27830 if (ctxt->ctxt != NULL)
27831 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
27832}
27833
27834static void
27835ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
27836{
Daniel Veillard971771e2005-07-09 17:32:57 +000027837 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027838 if (ctxt == NULL)
27839 return;
27840 if ((ctxt->user_sax != NULL) &&
27841 (ctxt->user_sax->ignorableWhitespace != NULL))
27842 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
27843 if (ctxt->ctxt != NULL)
27844 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
27845}
27846
27847static void
27848cdataBlockSplit(void *ctx, const xmlChar *value, int len)
27849{
Daniel Veillard971771e2005-07-09 17:32:57 +000027850 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027851 if (ctxt == NULL)
27852 return;
27853 if ((ctxt->user_sax != NULL) &&
27854 (ctxt->user_sax->ignorableWhitespace != NULL))
27855 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, value, len);
27856 if (ctxt->ctxt != NULL)
27857 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
27858}
27859
27860static void
27861referenceSplit(void *ctx, const xmlChar *name)
27862{
Daniel Veillard971771e2005-07-09 17:32:57 +000027863 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027864 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27865 (ctxt->user_sax->reference != NULL))
27866 ctxt->user_sax->reference(ctxt->user_data, name);
27867 if (ctxt->ctxt != NULL)
27868 xmlSchemaSAXHandleReference(ctxt->user_data, name);
27869}
27870
27871static void
27872startElementNsSplit(void *ctx, const xmlChar * localname,
27873 const xmlChar * prefix, const xmlChar * URI,
27874 int nb_namespaces, const xmlChar ** namespaces,
27875 int nb_attributes, int nb_defaulted,
27876 const xmlChar ** attributes) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027877 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027878 if (ctxt == NULL)
27879 return;
27880 if ((ctxt->user_sax != NULL) &&
27881 (ctxt->user_sax->startElementNs != NULL))
27882 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
27883 URI, nb_namespaces, namespaces,
27884 nb_attributes, nb_defaulted,
27885 attributes);
27886 if (ctxt->ctxt != NULL)
27887 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
27888 URI, nb_namespaces, namespaces,
27889 nb_attributes, nb_defaulted,
27890 attributes);
27891}
27892
27893static void
27894endElementNsSplit(void *ctx, const xmlChar * localname,
27895 const xmlChar * prefix, const xmlChar * URI) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027896 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027897 if (ctxt == NULL)
27898 return;
27899 if ((ctxt->user_sax != NULL) &&
27900 (ctxt->user_sax->endElementNs != NULL))
27901 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
27902 if (ctxt->ctxt != NULL)
27903 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
27904}
27905
Daniel Veillard4255d502002-04-16 15:50:10 +000027906/**
Daniel Veillard971771e2005-07-09 17:32:57 +000027907 * xmlSchemaSAXPlug:
27908 * @ctxt: a schema validation context
Daniel Veillard1f33c4d2005-07-10 21:38:31 +000027909 * @sax: a pointer to the original xmlSAXHandlerPtr
27910 * @user_data: a pointer to the original SAX user data pointer
Daniel Veillard971771e2005-07-09 17:32:57 +000027911 *
27912 * Plug a SAX based validation layer in a SAX parsing event flow.
27913 * The original @saxptr and @dataptr data are replaced by new pointers
27914 * but the calls to the original will be maintained.
27915 *
27916 * Returns a pointer to a data structure needed to unplug the validation layer
27917 * or NULL in case of errors.
27918 */
27919xmlSchemaSAXPlugPtr
27920xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
27921 xmlSAXHandlerPtr *sax, void **user_data)
27922{
27923 xmlSchemaSAXPlugPtr ret;
27924 xmlSAXHandlerPtr old_sax;
27925
27926 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
27927 return(NULL);
27928
27929 /*
27930 * We only allow to plug into SAX2 event streams
27931 */
27932 old_sax = *sax;
27933 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
27934 return(NULL);
27935 if ((old_sax != NULL) &&
27936 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
27937 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
27938 return(NULL);
27939
27940 /*
27941 * everything seems right allocate the local data needed for that layer
27942 */
27943 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
27944 if (ret == NULL) {
27945 return(NULL);
27946 }
27947 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
27948 ret->magic = XML_SAX_PLUG_MAGIC;
27949 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
27950 ret->ctxt = ctxt;
27951 ret->user_sax_ptr = sax;
27952 ret->user_sax = old_sax;
27953 if (old_sax == NULL) {
27954 /*
27955 * go direct, no need for the split block and functions.
27956 */
27957 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
27958 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
27959 /*
27960 * Note that we use the same text-function for both, to prevent
27961 * the parser from testing for ignorable whitespace.
27962 */
27963 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
27964 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
27965
27966 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
27967 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
27968
27969 ret->user_data = ctxt;
27970 *user_data = ctxt;
27971 } else {
27972 /*
27973 * for each callback unused by Schemas initialize it to the Split
27974 * routine only if non NULL in the user block, this can speed up
27975 * things at the SAX level.
27976 */
27977 if (old_sax->internalSubset != NULL)
27978 ret->schemas_sax.internalSubset = internalSubsetSplit;
27979 if (old_sax->isStandalone != NULL)
27980 ret->schemas_sax.isStandalone = isStandaloneSplit;
27981 if (old_sax->hasInternalSubset != NULL)
27982 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
27983 if (old_sax->hasExternalSubset != NULL)
27984 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
27985 if (old_sax->resolveEntity != NULL)
27986 ret->schemas_sax.resolveEntity = resolveEntitySplit;
27987 if (old_sax->getEntity != NULL)
27988 ret->schemas_sax.getEntity = getEntitySplit;
27989 if (old_sax->entityDecl != NULL)
27990 ret->schemas_sax.entityDecl = entityDeclSplit;
27991 if (old_sax->notationDecl != NULL)
27992 ret->schemas_sax.notationDecl = notationDeclSplit;
27993 if (old_sax->attributeDecl != NULL)
27994 ret->schemas_sax.attributeDecl = attributeDeclSplit;
27995 if (old_sax->elementDecl != NULL)
27996 ret->schemas_sax.elementDecl = elementDeclSplit;
27997 if (old_sax->unparsedEntityDecl != NULL)
27998 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
27999 if (old_sax->setDocumentLocator != NULL)
28000 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28001 if (old_sax->startDocument != NULL)
28002 ret->schemas_sax.startDocument = startDocumentSplit;
28003 if (old_sax->endDocument != NULL)
28004 ret->schemas_sax.endDocument = endDocumentSplit;
28005 if (old_sax->processingInstruction != NULL)
28006 ret->schemas_sax.processingInstruction = processingInstructionSplit;
28007 if (old_sax->comment != NULL)
28008 ret->schemas_sax.comment = commentSplit;
28009 if (old_sax->warning != NULL)
28010 ret->schemas_sax.warning = warningSplit;
28011 if (old_sax->error != NULL)
28012 ret->schemas_sax.error = errorSplit;
28013 if (old_sax->fatalError != NULL)
28014 ret->schemas_sax.fatalError = fatalErrorSplit;
28015 if (old_sax->getParameterEntity != NULL)
28016 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28017 if (old_sax->externalSubset != NULL)
28018 ret->schemas_sax.externalSubset = externalSubsetSplit;
28019
28020 /*
28021 * the 6 schemas callback have to go to the splitter functions
28022 * Note that we use the same text-function for ignorableWhitespace
28023 * if possible, to prevent the parser from testing for ignorable
28024 * whitespace.
28025 */
28026 ret->schemas_sax.characters = charactersSplit;
28027 if ((old_sax->ignorableWhitespace != NULL) &&
28028 (old_sax->ignorableWhitespace != old_sax->characters))
28029 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28030 else
28031 ret->schemas_sax.ignorableWhitespace = charactersSplit;
28032 ret->schemas_sax.cdataBlock = cdataBlockSplit;
28033 ret->schemas_sax.reference = referenceSplit;
28034 ret->schemas_sax.startElementNs = startElementNsSplit;
28035 ret->schemas_sax.endElementNs = endElementNsSplit;
28036
28037 ret->user_data_ptr = user_data;
28038 ret->user_data = *user_data;
28039 *user_data = ret;
28040 }
28041
28042 /*
28043 * plug the pointers back.
28044 */
28045 *sax = &(ret->schemas_sax);
Daniel Veillardf10ae122005-07-10 19:03:16 +000028046 ctxt->sax = *sax;
28047 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28048 xmlSchemaPreRun(ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000028049 return(ret);
28050}
28051
28052/**
28053 * xmlSchemaSAXUnplug:
28054 * @plug: a data structure returned by xmlSchemaSAXPlug
28055 *
28056 * Unplug a SAX based validation layer in a SAX parsing event flow.
28057 * The original pointers used in the call are restored.
28058 *
28059 * Returns 0 in case of success and -1 in case of failure.
28060 */
28061int
28062xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28063{
28064 xmlSAXHandlerPtr *sax;
28065 void **user_data;
28066
28067 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28068 return(-1);
28069 plug->magic = 0;
28070
Daniel Veillardf10ae122005-07-10 19:03:16 +000028071 xmlSchemaPostRun(plug->ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000028072 /* restore the data */
28073 sax = plug->user_sax_ptr;
28074 *sax = plug->user_sax;
28075 if (plug->user_sax != NULL) {
28076 user_data = plug->user_data_ptr;
28077 *user_data = plug->user_data;
28078 }
28079
28080 /* free and return */
28081 xmlFree(plug);
28082 return(0);
28083}
28084
28085/**
Daniel Veillard4255d502002-04-16 15:50:10 +000028086 * xmlSchemaValidateStream:
28087 * @ctxt: a schema validation context
28088 * @input: the input to use for reading the data
28089 * @enc: an optional encoding information
28090 * @sax: a SAX handler for the resulting events
28091 * @user_data: the context to provide to the SAX handler.
28092 *
Daniel Veillardcdc82732005-07-08 15:04:06 +000028093 * Validate an input based on a flow of SAX event from the parser
28094 * and forward the events to the @sax handler with the provided @user_data
28095 * the user provided @sax handler must be a SAX2 one.
Daniel Veillard4255d502002-04-16 15:50:10 +000028096 *
28097 * Returns 0 if the document is schemas valid, a positive error code
28098 * number otherwise and -1 in case of internal or API error.
28099 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028100int
Daniel Veillard4255d502002-04-16 15:50:10 +000028101xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028102 xmlParserInputBufferPtr input, xmlCharEncoding enc,
28103 xmlSAXHandlerPtr sax, void *user_data)
28104{
Daniel Veillard971771e2005-07-09 17:32:57 +000028105 xmlSchemaSAXPlugPtr plug = NULL;
28106 xmlSAXHandlerPtr old_sax = NULL;
28107 xmlParserCtxtPtr pctxt = NULL;
28108 xmlParserInputPtr inputStream = NULL;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028109 int ret;
28110
Daniel Veillard4255d502002-04-16 15:50:10 +000028111 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028112 return (-1);
Daniel Veillardcdc82732005-07-08 15:04:06 +000028113
Daniel Veillardcdc82732005-07-08 15:04:06 +000028114 /*
28115 * prepare the parser
28116 */
28117 pctxt = xmlNewParserCtxt();
28118 if (pctxt == NULL)
28119 return (-1);
28120 old_sax = pctxt->sax;
Daniel Veillard971771e2005-07-09 17:32:57 +000028121 pctxt->sax = sax;
28122 pctxt->userData = user_data;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028123#if 0
28124 if (options)
28125 xmlCtxtUseOptions(pctxt, options);
28126#endif
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000028127 pctxt->linenumbers = 1;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028128
Daniel Veillardf0af8ec2005-07-08 17:27:33 +000028129 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028130 if (inputStream == NULL) {
28131 ret = -1;
28132 goto done;
28133 }
28134 inputPush(pctxt, inputStream);
28135 ctxt->parserCtxt = pctxt;
28136 ctxt->input = input;
28137
28138 /*
Daniel Veillard971771e2005-07-09 17:32:57 +000028139 * Plug the validation and launch the parsing
Daniel Veillardcdc82732005-07-08 15:04:06 +000028140 */
Daniel Veillard971771e2005-07-09 17:32:57 +000028141 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28142 if (plug == NULL) {
28143 ret = -1;
28144 goto done;
28145 }
28146 ctxt->input = input;
28147 ctxt->enc = enc;
28148 ctxt->sax = pctxt->sax;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028149 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28150 ret = xmlSchemaVStart(ctxt);
28151
28152 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28153 ret = ctxt->parserCtxt->errNo;
28154 if (ret == 0)
28155 ret = 1;
28156 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028157
28158done:
Daniel Veillard971771e2005-07-09 17:32:57 +000028159 ctxt->parserCtxt = NULL;
28160 ctxt->sax = NULL;
28161 ctxt->input = NULL;
28162 if (plug != NULL) {
28163 xmlSchemaSAXUnplug(plug);
28164 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028165 /* cleanup */
Daniel Veillard971771e2005-07-09 17:32:57 +000028166 if (pctxt != NULL) {
28167 pctxt->sax = old_sax;
28168 xmlFreeParserCtxt(pctxt);
28169 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028170 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000028171}
28172
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028173/**
28174 * xmlSchemaValidateFile:
28175 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000028176 * @filename: the URI of the instance
28177 * @options: a future set of options, currently unused
28178 *
28179 * Do a schemas validation of the given resource, it will use the
28180 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028181 *
28182 * Returns 0 if the document is valid, a positive error code
28183 * number otherwise and -1 in case of an internal or API error.
28184 */
28185int
28186xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000028187 const char * filename,
28188 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028189{
28190 int ret;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028191 xmlParserInputBufferPtr input;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028192
28193 if ((ctxt == NULL) || (filename == NULL))
28194 return (-1);
28195
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028196 input = xmlParserInputBufferCreateFilename(filename,
28197 XML_CHAR_ENCODING_NONE);
28198 if (input == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028199 return (-1);
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028200 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28201 NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028202 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000028203}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028204
Daniel Veillard5d4644e2005-04-01 13:11:58 +000028205#define bottom_xmlschemas
28206#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000028207#endif /* LIBXML_SCHEMAS_ENABLED */