blob: ac499febe8a4e5ef81360fb9a02610f3c702f654 [file] [log] [blame]
Daniel Veillard4255d502002-04-16 15:50:10 +00001/*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <veillard@redhat.com>
8 */
9
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010/*
Daniel Veillardb0f397e2003-12-23 23:30:53 +000011 * TODO:
12 * - when types are redefined in includes, check that all
13 * types in the redef list are equal
14 * -> need a type equality operation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015 * - if we don't intend to use the schema for schemas, we
Daniel Veillard01fa6152004-06-29 17:04:39 +000016 * need to validate all schema attributes (ref, type, name)
17 * against their types.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018 * - Eliminate item creation for: ??
19 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020 * URGENT TODO:
21 * - For xsi-driven schema acquisition, augment the IDCs after every
22 * acquisition episode (xmlSchemaAugmentIDC).
23 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000024 * NOTES:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025 * - Elimated item creation for: <restriction>, <extension>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026 * <simpleContent>, <complexContent>, <list>, <union>
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000028 * PROBLEMS:
29 * - http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0337.html
30 * IDC XPath expression and chameleon includes: the targetNamespace is changed, so
31 * XPath will have trouble to resolve to this namespace, since not known.
32 *
33 *
34 * CONSTRAINTS:
35 *
36 * Schema Component Constraint:
37 * All Group Limited (cos-all-limited)
38 * Status: complete
39 * (1.2)
40 * In xmlSchemaGroupDefReferenceTermFixup() and
41 * (2)
42 * In xmlSchemaParseModelGroup()
43 * TODO: Actually this should go to component-level checks,
44 * but is done here due to performance. Move it to an other layer
45 * is schema construction via an API is implemented.
Daniel Veillardb0f397e2003-12-23 23:30:53 +000046 */
Daniel Veillard4255d502002-04-16 15:50:10 +000047#define IN_LIBXML
48#include "libxml.h"
49
50#ifdef LIBXML_SCHEMAS_ENABLED
51
52#include <string.h>
53#include <libxml/xmlmemory.h>
54#include <libxml/parser.h>
55#include <libxml/parserInternals.h>
56#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000057#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000058#include <libxml/xmlschemas.h>
59#include <libxml/schemasInternals.h>
60#include <libxml/xmlschemastypes.h>
61#include <libxml/xmlautomata.h>
62#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000063#include <libxml/dict.h>
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000064#include <libxml/encoding.h>
65#include <libxml/xmlIO.h>
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000066#ifdef LIBXML_PATTERN_ENABLED
67#include <libxml/pattern.h>
68#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000069#ifdef LIBXML_READER_ENABLED
70#include <libxml/xmlreader.h>
71#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000072
Daniel Veillarda84c0b32003-06-02 16:58:46 +000073/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000074
Daniel Veillard82bbbd42003-05-11 20:16:09 +000075/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000076
Daniel Veillard82bbbd42003-05-11 20:16:09 +000077/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000078
Daniel Veillard118aed72002-09-24 14:13:13 +000079/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000080
Daniel Veillard4255d502002-04-16 15:50:10 +000081/* #define DEBUG_AUTOMATA 1 */
82
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000083/* #define DEBUG_IDC */
84
85/* #define DEBUG_IDC_NODE_TABLE */
86
87#ifdef DEBUG_IDC
88 #ifndef DEBUG_IDC_NODE_TABLE
89 #define DEBUG_IDC_NODE_TABLE
90 #endif
91#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000092
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000093/* #define ENABLE_PARTICLE_RESTRICTION 1 */
94
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000095#define ENABLE_REDEFINE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000096
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000097/* #define ENABLE_NAMED_LOCALS */
98
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000099/* #define ENABLE_IDC_NODE_TABLES_TEST */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000100
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000101#define DUMP_CONTENT_MODEL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000102
103#ifdef LIBXML_READER_ENABLED
104/* #define XML_SCHEMA_READER_ENABLED */
105#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +0000106
Daniel Veillard4255d502002-04-16 15:50:10 +0000107#define UNBOUNDED (1 << 30)
108#define TODO \
109 xmlGenericError(xmlGenericErrorContext, \
110 "Unimplemented block at %s:%d\n", \
111 __FILE__, __LINE__);
112
William M. Brack2f2a6632004-08-20 23:09:47 +0000113#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +0000114
Daniel Veillard4255d502002-04-16 15:50:10 +0000115/*
116 * The XML Schemas namespaces
117 */
118static const xmlChar *xmlSchemaNs = (const xmlChar *)
119 "http://www.w3.org/2001/XMLSchema";
120
121static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
122 "http://www.w3.org/2001/XMLSchema-instance";
123
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000124static const xmlChar *xmlNamespaceNs = (const xmlChar *)
125 "http://www.w3.org/2000/xmlns/";
126
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000127/*
128* Come casting macros.
129*/
130#define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +0000131#define PCTXT_CAST (xmlSchemaParserCtxtPtr)
132#define VCTXT_CAST (xmlSchemaValidCtxtPtr)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000133#define WXS_BASIC_CAST (xmlSchemaBasicItemPtr)
134#define WXS_TREE_CAST (xmlSchemaTreeItemPtr)
135#define WXS_PTC_CAST (xmlSchemaParticlePtr)
136#define WXS_TYPE_CAST (xmlSchemaTypePtr)
137#define WXS_ELEM_CAST (xmlSchemaElementPtr)
138#define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr)
139#define WXS_ATTR_CAST (xmlSchemaAttributePtr)
140#define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr)
141#define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr)
142#define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr)
143#define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr)
144#define WXS_IDC_CAST (xmlSchemaIDCPtr)
145#define WXS_QNAME_CAST (xmlSchemaQNameRefPtr)
146#define WXS_LIST_CAST (xmlSchemaItemListPtr)
Daniel Veillardc0826a72004-08-10 14:17:33 +0000147
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000148/*
149* Macros to query common properties of components.
150*/
151#define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i))
Daniel Veillard4255d502002-04-16 15:50:10 +0000152
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000153#define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i))
154/*
155* Macros for element declarations.
156*/
157#define WXS_ELEM_TYPEDEF(e) (e)->subtypes
Daniel Veillardc0826a72004-08-10 14:17:33 +0000158
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000159#define WXS_SUBST_HEAD(item) (item)->refDecl
160/*
161* Macros for attribute declarations.
162*/
163#define WXS_ATTR_TYPEDEF(a) (a)->subtypes
164/*
165* Macros for attribute uses.
166*/
167#define WXS_ATTRUSE_DECL(au) WXS_ATTR_CAST (WXS_ATTR_USE_CAST (au))->attrDecl
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000168
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000169#define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000170
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000171#define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name
172
173#define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace
174/*
175* Macros for attribute groups.
176*/
177#define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)
178#define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)
179/*
180* Macros for particles.
181*/
182#define WXS_PARTICLE(p) WXS_PTC_CAST (p)
183
184#define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children
185
186#define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
187/*
188* Macros for model groups definitions.
189*/
190#define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
191/*
192* Macros for model groups.
193*/
194#define WXS_IS_MODEL_GROUP(i) \
195 (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
196 ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
197 ((i)->type == XML_SCHEMA_TYPE_ALL))
198
199#define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
200/*
201* Macros for schema buckets.
202*/
203#define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
204 ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
205
206#define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
207 ((t) == XML_SCHEMA_SCHEMA_IMPORT))
208
209#define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
210
211#define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
212/*
213* Macros for complex/simple types.
214*/
215#define WXS_IS_ANYTYPE(i) \
216 (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
217 ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
218
219#define WXS_IS_COMPLEX(i) \
220 (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
221 ((i)->builtInType == XML_SCHEMAS_ANYTYPE))
222
223#define WXS_IS_SIMPLE(item) \
224 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
225 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000226 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000227
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000228#define WXS_IS_ANY_SIMPLE_TYPE(i) \
229 (((i)->type == XML_SCHEMA_TYPE_BASIC) && \
230 ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000231
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000232#define WXS_IS_RESTRICTION(t) \
233 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000234
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000235#define WXS_IS_EXTENSION(t) \
236 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
237
238#define WXS_IS_TYPE_NOT_FIXED(i) \
239 (((i)->type != XML_SCHEMA_TYPE_BASIC) && \
240 (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
241
242#define WXS_IS_TYPE_NOT_FIXED_1(item) \
243 (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000244 (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000245/*
246* Macros for exclusively for complex types.
247*/
248#define WXS_HAS_COMPLEX_CONTENT(item) \
249 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
250 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000251 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
252
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000253#define WXS_HAS_SIMPLE_CONTENT(item) \
254 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000255 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
256
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000257#define WXS_HAS_MIXED_CONTENT(item) \
258 (item->contentType == XML_SCHEMA_CONTENT_MIXED)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000259
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000260#define WXS_EMPTIABLE(t) \
261 (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000262
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000263#define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000264
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000265#define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000266
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000267#define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
268/*
269* Macros for exclusively for simple types.
270*/
271#define WXS_LIST_ITEMTYPE(t) (t)->subtypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000272
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000273#define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000274
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000275#define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000276
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000277#define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
278/*
279* Misc parser context macros.
280*/
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000281#define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
282
283#define WXS_HAS_BUCKETS(ctx) \
284( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
285(WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
286
287#define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
288
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000289#define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000290
291#define WXS_SCHEMA(ctx) (ctx)->schema
292
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000293#define WXS_ADD_LOCAL(ctx, item) \
294 xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000295
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000296#define WXS_ADD_GLOBAL(ctx, item) \
297 xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000298
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000299#define WXS_ADD_PENDING(ctx, item) \
300 xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
301/*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000302* xmlSchemaItemList macros.
303*/
304#define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0))
305/*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000306* Misc macros.
307*/
308#define IS_SCHEMA(node, type) \
309 ((node != NULL) && (node->ns != NULL) && \
310 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
311 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000312
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000313#define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000314
315/*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000316* Since we put the default/fixed values into the dict, we can
317* use pointer comparison for those values.
318* REMOVED: (xmlStrEqual((v1), (v2)))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000319*/
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000320#define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000321
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000322#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000323
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000324#define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000325
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000326#define HFAILURE if (res == -1) goto exit_failure;
327
328#define HERROR if (res != 0) goto exit_error;
329
330#define HSTOP(ctx) if ((ctx)->stop) goto exit;
331/*
332* Some flags used for various schema constraints.
333*/
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000334#define SUBSET_RESTRICTION 1<<0
335#define SUBSET_EXTENSION 1<<1
336#define SUBSET_SUBSTITUTION 1<<2
337#define SUBSET_LIST 1<<3
338#define SUBSET_UNION 1<<4
339
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000340typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
341typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000342
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000343typedef struct _xmlSchemaItemList xmlSchemaItemList;
344typedef xmlSchemaItemList *xmlSchemaItemListPtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000345struct _xmlSchemaItemList {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000346 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000347 int nbItems; /* used for dynamic addition of schemata */
348 int sizeItems; /* used for dynamic addition of schemata */
349};
350
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000351#define XML_SCHEMA_CTXT_PARSER 1
352#define XML_SCHEMA_CTXT_VALIDATOR 2
353
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000354typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
355typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
356struct _xmlSchemaAbstractCtxt {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000357 int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000358};
359
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000360typedef struct _xmlSchemaBucket xmlSchemaBucket;
361typedef xmlSchemaBucket *xmlSchemaBucketPtr;
362
363#define XML_SCHEMA_SCHEMA_MAIN 0
364#define XML_SCHEMA_SCHEMA_IMPORT 1
365#define XML_SCHEMA_SCHEMA_INCLUDE 2
366#define XML_SCHEMA_SCHEMA_REDEFINE 3
367
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000368/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000369 * xmlSchemaSchemaRelation:
370 *
371 * Used to create a graph of schema relationships.
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000372 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000373typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
374typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
375struct _xmlSchemaSchemaRelation {
376 xmlSchemaSchemaRelationPtr next;
377 int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
378 const xmlChar *importNamespace;
379 xmlSchemaBucketPtr bucket;
380};
381
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000382#define XML_SCHEMA_BUCKET_MARKED 1<<0
383#define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1
384
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000385struct _xmlSchemaBucket {
386 int type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000387 int flags;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000388 const xmlChar *schemaLocation;
389 const xmlChar *origTargetNamespace;
390 const xmlChar *targetNamespace;
391 xmlDocPtr doc;
392 xmlSchemaSchemaRelationPtr relations;
393 int located;
394 int parsed;
395 int imported;
396 int preserveDoc;
397 xmlSchemaItemListPtr globals; /* Global components. */
398 xmlSchemaItemListPtr locals; /* Local components. */
399};
400
401/**
402 * xmlSchemaImport:
403 * (extends xmlSchemaBucket)
404 *
405 * Reflects a schema. Holds some information
406 * about the schema and its toplevel components. Duplicate
407 * toplevel components are not checked at this level.
408 */
409typedef struct _xmlSchemaImport xmlSchemaImport;
410typedef xmlSchemaImport *xmlSchemaImportPtr;
411struct _xmlSchemaImport {
412 int type; /* Main OR import OR include. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000413 int flags;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000414 const xmlChar *schemaLocation; /* The URI of the schema document. */
415 /* For chameleon includes, @origTargetNamespace will be NULL */
416 const xmlChar *origTargetNamespace;
417 /*
418 * For chameleon includes, @targetNamespace will be the
419 * targetNamespace of the including schema.
420 */
421 const xmlChar *targetNamespace;
422 xmlDocPtr doc; /* The schema node-tree. */
423 /* @relations will hold any included/imported/redefined schemas. */
424 xmlSchemaSchemaRelationPtr relations;
425 int located;
426 int parsed;
427 int imported;
428 int preserveDoc;
429 xmlSchemaItemListPtr globals;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000430 xmlSchemaItemListPtr locals;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000431 /* The imported schema. */
432 xmlSchemaPtr schema;
433};
434
435/*
436* (extends xmlSchemaBucket)
437*/
438typedef struct _xmlSchemaInclude xmlSchemaInclude;
439typedef xmlSchemaInclude *xmlSchemaIncludePtr;
440struct _xmlSchemaInclude {
441 int type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000442 int flags;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000443 const xmlChar *schemaLocation;
444 const xmlChar *origTargetNamespace;
445 const xmlChar *targetNamespace;
446 xmlDocPtr doc;
447 xmlSchemaSchemaRelationPtr relations;
448 int located;
449 int parsed;
450 int imported;
451 int preserveDoc;
452 xmlSchemaItemListPtr globals; /* Global components. */
453 xmlSchemaItemListPtr locals; /* Local components. */
454
455 /* The owning main or import schema bucket. */
456 xmlSchemaImportPtr ownerImport;
457};
458
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000459/**
460 * xmlSchemaBasicItem:
461 *
462 * The abstract base type for schema components.
463 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000464typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
465typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
466struct _xmlSchemaBasicItem {
467 xmlSchemaTypeType type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000468};
469
470/**
471 * xmlSchemaAnnotItem:
472 *
473 * The abstract base type for annotated schema components.
474 * (Extends xmlSchemaBasicItem)
475 */
476typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
477typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
478struct _xmlSchemaAnnotItem {
479 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000480 xmlSchemaAnnotPtr annot;
481};
482
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000483/**
484 * xmlSchemaTreeItem:
485 *
486 * The abstract base type for tree-like structured schema components.
487 * (Extends xmlSchemaAnnotItem)
488 */
489typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
490typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
491struct _xmlSchemaTreeItem {
492 xmlSchemaTypeType type;
493 xmlSchemaAnnotPtr annot;
494 xmlSchemaTreeItemPtr next;
495 xmlSchemaTreeItemPtr children;
496};
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000497
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000498
499#define XML_SCHEMA_ATTR_USE_FIXED 1<<0
500/**
501 * xmlSchemaAttributeUsePtr:
502 *
503 * The abstract base type for tree-like structured schema components.
504 * (Extends xmlSchemaTreeItem)
505 */
506typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
507typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
508struct _xmlSchemaAttributeUse {
509 xmlSchemaTypeType type;
510 xmlSchemaAnnotPtr annot;
511 xmlSchemaAttributeUsePtr next; /* The next attr. use. */
512 /*
513 * The attr. decl. OR a QName-ref. to an attr. decl. OR
514 * a QName-ref. to an attribute group definition.
515 */
516 xmlSchemaAttributePtr attrDecl;
517
518 int flags;
519 xmlNodePtr node;
520 int occurs; /* required, optional */
521 const xmlChar * defValue;
522 xmlSchemaValPtr defVal;
523};
524
525/**
526 * xmlSchemaAttributeUseProhibPtr:
527 *
528 * A helper component to reflect attribute prohibitions.
529 * (Extends xmlSchemaBasicItem)
530 */
531typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
532typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
533struct _xmlSchemaAttributeUseProhib {
534 xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
535 xmlNodePtr node;
536 const xmlChar *name;
537 const xmlChar *targetNamespace;
538 int isRef;
539};
540
541/**
542 * xmlSchemaRedef:
543 */
544typedef struct _xmlSchemaRedef xmlSchemaRedef;
545typedef xmlSchemaRedef *xmlSchemaRedefPtr;
546struct _xmlSchemaRedef {
547 xmlSchemaRedefPtr next;
548 xmlSchemaBasicItemPtr item; /* The redefining component. */
549 xmlSchemaBasicItemPtr reference; /* The referencing component. */
550 xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
551 const xmlChar *refName; /* The name of the to-be-redefined component. */
552 const xmlChar *refTargetNs; /* The target namespace of the
553 to-be-redefined comp. */
554 xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
555};
556
557/**
558 * xmlSchemaConstructionCtxt:
559 */
560typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
561typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
562struct _xmlSchemaConstructionCtxt {
563 xmlSchemaPtr mainSchema; /* The main schema. */
564 xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
565 xmlDictPtr dict;
566 xmlSchemaItemListPtr buckets; /* List of schema buckets. */
567 /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
568 xmlSchemaBucketPtr bucket; /* The current schema bucket */
569 xmlSchemaItemListPtr pending; /* All Components of all schemas that
570 need to be fixed. */
571 xmlHashTablePtr substGroups;
572 xmlSchemaRedefPtr redefs;
573 xmlSchemaRedefPtr lastRedef;
574};
575
576#define XML_SCHEMAS_PARSE_ERROR 1
577#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
578
579struct _xmlSchemaParserCtxt {
580 int type;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +0000581 void *errCtxt; /* user specific error context */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000582 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
583 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Kasimier T. Buchcikdfbc33a2006-01-03 10:51:59 +0000584 int err;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000585 int nberrors;
586 xmlStructuredErrorFunc serror;
587
588 xmlSchemaConstructionCtxtPtr constructor;
589 int ownsConstructor; /* TODO: Move this to parser *flags*. */
590
591 /* xmlSchemaPtr topschema; */
592 /* xmlHashTablePtr namespaces; */
593
594 xmlSchemaPtr schema; /* The main schema in use */
595 int counter;
596
597 const xmlChar *URL;
598 xmlDocPtr doc;
599 int preserve; /* Whether the doc should be freed */
600
601 const char *buffer;
602 int size;
603
604 /*
605 * Used to build complex element content models
606 */
607 xmlAutomataPtr am;
608 xmlAutomataStatePtr start;
609 xmlAutomataStatePtr end;
610 xmlAutomataStatePtr state;
611
612 xmlDictPtr dict; /* dictionnary for interned string names */
613 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
614 int options;
615 xmlSchemaValidCtxtPtr vctxt;
616 int isS4S;
617 int isRedefine;
618 int xsiAssemble;
619 int stop; /* If the parser should stop; i.e. a critical error. */
620 const xmlChar *targetNamespace;
621 xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
622
623 xmlSchemaRedefPtr redef; /* Used for redefinitions. */
624 int redefCounter; /* Used for redefinitions. */
625 xmlSchemaItemListPtr attrProhibs;
626};
627
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000628/**
629 * xmlSchemaQNameRef:
630 *
631 * A component reference item (not a schema component)
632 * (Extends xmlSchemaBasicItem)
633 */
634typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
635typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
636struct _xmlSchemaQNameRef {
637 xmlSchemaTypeType type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000638 xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000639 xmlSchemaTypeType itemType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000640 const xmlChar *name;
641 const xmlChar *targetNamespace;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000642 xmlNodePtr node;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000643};
644
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000645/**
646 * xmlSchemaParticle:
647 *
648 * A particle component.
649 * (Extends xmlSchemaTreeItem)
650 */
651typedef struct _xmlSchemaParticle xmlSchemaParticle;
652typedef xmlSchemaParticle *xmlSchemaParticlePtr;
653struct _xmlSchemaParticle {
654 xmlSchemaTypeType type;
655 xmlSchemaAnnotPtr annot;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000656 xmlSchemaTreeItemPtr next; /* next particle */
657 xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
658 a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
659 etc.) */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000660 int minOccurs;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000661 int maxOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000662 xmlNodePtr node;
663};
664
665/**
666 * xmlSchemaModelGroup:
667 *
668 * A model group component.
669 * (Extends xmlSchemaTreeItem)
670 */
671typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
672typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
673struct _xmlSchemaModelGroup {
674 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
675 xmlSchemaAnnotPtr annot;
676 xmlSchemaTreeItemPtr next; /* not used */
677 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
678 xmlNodePtr node;
679};
680
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000681#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000682#define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000683/**
684 * xmlSchemaModelGroupDef:
685 *
686 * A model group definition component.
687 * (Extends xmlSchemaTreeItem)
688 */
689typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
690typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
691struct _xmlSchemaModelGroupDef {
692 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
693 xmlSchemaAnnotPtr annot;
694 xmlSchemaTreeItemPtr next; /* not used */
695 xmlSchemaTreeItemPtr children; /* the "model group" */
696 const xmlChar *name;
697 const xmlChar *targetNamespace;
698 xmlNodePtr node;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000699 int flags;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000700};
701
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000702typedef struct _xmlSchemaIDC xmlSchemaIDC;
703typedef xmlSchemaIDC *xmlSchemaIDCPtr;
704
705/**
706 * xmlSchemaIDCSelect:
707 *
708 * The identity-constraint "field" and "selector" item, holding the
709 * XPath expression.
710 */
711typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
712typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000713struct _xmlSchemaIDCSelect {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000714 xmlSchemaIDCSelectPtr next;
715 xmlSchemaIDCPtr idc;
716 int index; /* an index position if significant for IDC key-sequences */
717 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000718 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000719};
720
721/**
722 * xmlSchemaIDC:
723 *
724 * The identity-constraint definition component.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000725 * (Extends xmlSchemaAnnotItem)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000726 */
727
728struct _xmlSchemaIDC {
729 xmlSchemaTypeType type;
730 xmlSchemaAnnotPtr annot;
731 xmlSchemaIDCPtr next;
732 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000733 const xmlChar *name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000734 const xmlChar *targetNamespace;
735 xmlSchemaIDCSelectPtr selector;
736 xmlSchemaIDCSelectPtr fields;
737 int nbFields;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000738 xmlSchemaQNameRefPtr ref;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000739};
740
741/**
742 * xmlSchemaIDCAug:
743 *
744 * The augmented IDC information used for validation.
745 */
746typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
747typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
748struct _xmlSchemaIDCAug {
749 xmlSchemaIDCAugPtr next; /* next in a list */
750 xmlSchemaIDCPtr def; /* the IDC definition */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000751 int keyrefDepth; /* the lowest tree level to which IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000752 tables need to be bubbled upwards */
753};
754
755/**
756 * xmlSchemaPSVIIDCKeySequence:
757 *
758 * The key sequence of a node table item.
759 */
760typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
761typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
762struct _xmlSchemaPSVIIDCKey {
763 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000764 xmlSchemaValPtr val;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000765};
766
767/**
768 * xmlSchemaPSVIIDCNode:
769 *
770 * The node table item of a node table.
771 */
772typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
773typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
774struct _xmlSchemaPSVIIDCNode {
775 xmlNodePtr node;
776 xmlSchemaPSVIIDCKeyPtr *keys;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000777 int nodeLine;
778 int nodeQNameID;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000779
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000780};
781
782/**
783 * xmlSchemaPSVIIDCBinding:
784 *
785 * The identity-constraint binding item of the [identity-constraint table].
786 */
787typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
788typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
789struct _xmlSchemaPSVIIDCBinding {
790 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
791 xmlSchemaIDCPtr definition; /* the IDC definition */
792 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
793 int nbNodes; /* number of entries in the node table */
794 int sizeNodes; /* size of the node table */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000795 xmlSchemaItemListPtr dupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000796};
797
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000798
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000799#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
800#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
801
802#define XPATH_STATE_OBJ_MATCHES -2
803#define XPATH_STATE_OBJ_BLOCKED -3
804
805typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
806typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
807
808/**
809 * xmlSchemaIDCStateObj:
810 *
811 * The state object used to evaluate XPath expressions.
812 */
813typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
814typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
815struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000816 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000817 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000818 int depth; /* depth of creation */
819 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000820 int nbHistory;
821 int sizeHistory;
822 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
823 matcher */
824 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000825 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000826};
827
828#define IDC_MATCHER 0
829
830/**
831 * xmlSchemaIDCMatcher:
832 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000833 * Used to evaluate IDC selectors (and fields).
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000834 */
835struct _xmlSchemaIDCMatcher {
836 int type;
837 int depth; /* the tree depth at creation time */
838 xmlSchemaIDCMatcherPtr next; /* next in the list */
839 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000840 int idcType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000841 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
842 elements */
843 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000844 int targetDepth;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000845 xmlSchemaItemListPtr targets; /* list of target-node
846 (xmlSchemaPSVIIDCNodePtr) entries */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000847};
848
849/*
850* Element info flags.
851*/
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000852#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
853#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
854#define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
855#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
856
857#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
858#define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
859#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
860
861#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
862#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
863#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
864#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000865
866/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000867 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000868 *
869 * Holds information of an element node.
870 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000871struct _xmlSchemaNodeInfo {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000872 int nodeType;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000873 xmlNodePtr node;
874 int nodeLine;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000875 const xmlChar *localName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000876 const xmlChar *nsName;
877 const xmlChar *value;
878 xmlSchemaValPtr val; /* the pre-computed value if any */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000879 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000880
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000881 int flags; /* combination of node info flags */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000882
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000883 int valNeeded;
884 int normVal;
885
886 xmlSchemaElementPtr decl; /* the element/attribute declaration */
887 int depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000888 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
889 for the scope element*/
890 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
891 element */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000892 xmlRegExecCtxtPtr regexCtxt;
893
894 const xmlChar **nsBindings; /* Namespace bindings on this element */
895 int nbNsBindings;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000896 int sizeNsBindings;
897
898 int hasKeyrefs;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +0000899 int appliedXPath; /* Indicates that an XPath has been applied. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000900};
901
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000902#define XML_SCHEMAS_ATTR_UNKNOWN 1
903#define XML_SCHEMAS_ATTR_ASSESSED 2
904#define XML_SCHEMAS_ATTR_PROHIBITED 3
905#define XML_SCHEMAS_ATTR_ERR_MISSING 4
906#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
907#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
908#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
909#define XML_SCHEMAS_ATTR_DEFAULT 8
910#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
911#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
912#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
913#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
914#define XML_SCHEMAS_ATTR_WILD_SKIP 13
915#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
916#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
917#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
918#define XML_SCHEMAS_ATTR_META 17
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000919/*
920* @metaType values of xmlSchemaAttrInfo.
921*/
922#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
923#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
924#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
925#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
926#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000927
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000928typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
929typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
930struct _xmlSchemaAttrInfo {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000931 int nodeType;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000932 xmlNodePtr node;
933 int nodeLine;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000934 const xmlChar *localName;
935 const xmlChar *nsName;
936 const xmlChar *value;
937 xmlSchemaValPtr val; /* the pre-computed value if any */
938 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
939 int flags; /* combination of node info flags */
940
941 xmlSchemaAttributePtr decl; /* the attribute declaration */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000942 xmlSchemaAttributeUsePtr use; /* the attribute use */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000943 int state;
944 int metaType;
945 const xmlChar *vcValue; /* the value constraint value */
946 xmlSchemaNodeInfoPtr parent;
947};
948
949
950#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
Daniel Veillard4255d502002-04-16 15:50:10 +0000951/**
952 * xmlSchemaValidCtxt:
953 *
954 * A Schemas validation context
955 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000956struct _xmlSchemaValidCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000957 int type;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +0000958 void *errCtxt; /* user specific data block */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000959 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000960 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000961 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000962
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000963 xmlSchemaPtr schema; /* The schema in use */
964 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000965 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000966 xmlCharEncoding enc;
967 xmlSAXHandlerPtr sax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000968 xmlParserCtxtPtr parserCtxt;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000969 void *user_data; /* TODO: What is this for? */
Daniel Veillard4255d502002-04-16 15:50:10 +0000970
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000971 int err;
972 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000973
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000974 xmlNodePtr node;
975 xmlNodePtr cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000976 /* xmlSchemaTypePtr type; */
Daniel Veillard4255d502002-04-16 15:50:10 +0000977
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000978 xmlRegExecCtxtPtr regexp;
979 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000980
Daniel Veillardc0826a72004-08-10 14:17:33 +0000981 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000982 int options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000983 xmlNodePtr validationRoot;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000984 xmlSchemaParserCtxtPtr pctxt;
985 int xsiAssemble;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000986
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000987 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000988 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000989 int sizeElemInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000990 xmlSchemaNodeInfoPtr inode; /* the current element information */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000991
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000992 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
993
994 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
995 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000996
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000997 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
998 int nbIdcNodes;
999 int sizeIdcNodes;
1000
1001 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1002 int nbIdcKeys;
1003 int sizeIdcKeys;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001004
1005 int flags;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001006
1007 xmlDictPtr dict;
1008
Daniel Veillard39e5c892005-07-03 22:48:50 +00001009#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001010 xmlTextReaderPtr reader;
Daniel Veillard39e5c892005-07-03 22:48:50 +00001011#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001012
1013 xmlSchemaAttrInfoPtr *attrInfos;
1014 int nbAttrInfos;
1015 int sizeAttrInfos;
1016
1017 int skipDepth;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00001018 xmlSchemaItemListPtr nodeQNames;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00001019 int hasKeyrefs;
1020 int createIDCNodeTables;
1021 int psviExposeIDCNodeTables;
Daniel Veillard4255d502002-04-16 15:50:10 +00001022};
1023
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00001024/**
1025 * xmlSchemaSubstGroup:
1026 *
1027 *
1028 */
1029typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1030typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1031struct _xmlSchemaSubstGroup {
1032 xmlSchemaElementPtr head;
1033 xmlSchemaItemListPtr members;
1034};
1035
Daniel Veillard4255d502002-04-16 15:50:10 +00001036/************************************************************************
1037 * *
1038 * Some predeclarations *
1039 * *
1040 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001041
Daniel Veillardbd2904b2003-11-25 15:38:59 +00001042static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1043 xmlSchemaPtr schema,
1044 xmlNodePtr node);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00001045static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1046 xmlSchemaPtr schema,
1047 xmlNodePtr node);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001048static int
1049xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +00001050 xmlSchemaAbstractCtxtPtr ctxt);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001051static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +00001052xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1053static int
William M. Brack2f2a6632004-08-20 23:09:47 +00001054xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1055 xmlNodePtr node);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001056static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001057xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1058 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +00001059static void
1060xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001061static xmlSchemaWhitespaceValueType
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001062xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001063static xmlSchemaTreeItemPtr
1064xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1065 xmlNodePtr node, xmlSchemaTypeType type,
1066 int withParticle);
1067static const xmlChar *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001068xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001069static xmlSchemaTypeLinkPtr
1070xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001071static void
1072xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1073 const char *funcName,
1074 const char *message);
1075static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +00001076xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001077 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001078 xmlSchemaTypePtr baseType,
1079 int subset);
1080static void
1081xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001082 xmlSchemaParserCtxtPtr ctxt);
1083static void
1084xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001085static xmlSchemaQNameRefPtr
1086xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1087 xmlSchemaPtr schema,
1088 xmlNodePtr node);
William M. Brack87640d52004-04-17 14:58:15 +00001089
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001090/************************************************************************
1091 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001092 * Helper functions *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001093 * *
1094 ************************************************************************/
1095
1096/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001097 * xmlSchemaItemTypeToStr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001098 * @type: the type of the schema item
1099 *
1100 * Returns the component name of a schema item.
1101 */
1102static const xmlChar *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001103xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001104{
1105 switch (type) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001106 case XML_SCHEMA_TYPE_BASIC:
1107 return(BAD_CAST "simple type definition");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001108 case XML_SCHEMA_TYPE_SIMPLE:
1109 return(BAD_CAST "simple type definition");
1110 case XML_SCHEMA_TYPE_COMPLEX:
1111 return(BAD_CAST "complex type definition");
1112 case XML_SCHEMA_TYPE_ELEMENT:
1113 return(BAD_CAST "element declaration");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001114 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1115 return(BAD_CAST "attribute use");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001116 case XML_SCHEMA_TYPE_ATTRIBUTE:
1117 return(BAD_CAST "attribute declaration");
1118 case XML_SCHEMA_TYPE_GROUP:
1119 return(BAD_CAST "model group definition");
1120 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1121 return(BAD_CAST "attribute group definition");
1122 case XML_SCHEMA_TYPE_NOTATION:
1123 return(BAD_CAST "notation declaration");
1124 case XML_SCHEMA_TYPE_SEQUENCE:
1125 return(BAD_CAST "model group (sequence)");
1126 case XML_SCHEMA_TYPE_CHOICE:
1127 return(BAD_CAST "model group (choice)");
1128 case XML_SCHEMA_TYPE_ALL:
1129 return(BAD_CAST "model group (all)");
1130 case XML_SCHEMA_TYPE_PARTICLE:
1131 return(BAD_CAST "particle");
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001132 case XML_SCHEMA_TYPE_IDC_UNIQUE:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001133 return(BAD_CAST "unique identity-constraint");
1134 /* return(BAD_CAST "IDC (unique)"); */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001135 case XML_SCHEMA_TYPE_IDC_KEY:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001136 return(BAD_CAST "key identity-constraint");
1137 /* return(BAD_CAST "IDC (key)"); */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001138 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001139 return(BAD_CAST "keyref identity-constraint");
1140 /* return(BAD_CAST "IDC (keyref)"); */
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00001141 case XML_SCHEMA_TYPE_ANY:
1142 return(BAD_CAST "wildcard (any)");
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001143 case XML_SCHEMA_EXTRA_QNAMEREF:
1144 return(BAD_CAST "[helper component] QName reference");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001145 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1146 return(BAD_CAST "[helper component] attribute use prohibition");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001147 default:
1148 return(BAD_CAST "Not a schema component");
1149 }
1150}
1151
1152/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001153 * xmlSchemaGetComponentTypeStr:
1154 * @type: the type of the schema item
1155 *
1156 * Returns the component name of a schema item.
1157 */
1158static const xmlChar *
1159xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1160{
1161 switch (item->type) {
1162 case XML_SCHEMA_TYPE_BASIC:
1163 if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1164 return(BAD_CAST "complex type definition");
1165 else
1166 return(BAD_CAST "simple type definition");
1167 default:
1168 return(xmlSchemaItemTypeToStr(item->type));
1169 }
1170}
1171
1172/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001173 * xmlSchemaGetComponentNode:
1174 * @item: a schema component
1175 *
1176 * Returns node associated with the schema component.
1177 * NOTE that such a node need not be available; plus, a component's
1178 * node need not to reflect the component directly, since there is no
1179 * one-to-one relationship between the XML Schema representation and
1180 * the component representation.
1181 */
1182static xmlNodePtr
1183xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1184{
1185 switch (item->type) {
1186 case XML_SCHEMA_TYPE_ELEMENT:
1187 return (((xmlSchemaElementPtr) item)->node);
1188 case XML_SCHEMA_TYPE_ATTRIBUTE:
1189 return (((xmlSchemaAttributePtr) item)->node);
1190 case XML_SCHEMA_TYPE_COMPLEX:
1191 case XML_SCHEMA_TYPE_SIMPLE:
1192 return (((xmlSchemaTypePtr) item)->node);
1193 case XML_SCHEMA_TYPE_ANY:
1194 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1195 return (((xmlSchemaWildcardPtr) item)->node);
1196 case XML_SCHEMA_TYPE_PARTICLE:
1197 return (((xmlSchemaParticlePtr) item)->node);
1198 case XML_SCHEMA_TYPE_SEQUENCE:
1199 case XML_SCHEMA_TYPE_CHOICE:
1200 case XML_SCHEMA_TYPE_ALL:
1201 return (((xmlSchemaModelGroupPtr) item)->node);
1202 case XML_SCHEMA_TYPE_GROUP:
1203 return (((xmlSchemaModelGroupDefPtr) item)->node);
1204 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1205 return (((xmlSchemaAttributeGroupPtr) item)->node);
1206 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1207 case XML_SCHEMA_TYPE_IDC_KEY:
1208 case XML_SCHEMA_TYPE_IDC_KEYREF:
1209 return (((xmlSchemaIDCPtr) item)->node);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001210 case XML_SCHEMA_EXTRA_QNAMEREF:
1211 return(((xmlSchemaQNameRefPtr) item)->node);
1212 /* TODO: What to do with NOTATIONs?
1213 case XML_SCHEMA_TYPE_NOTATION:
1214 return (((xmlSchemaNotationPtr) item)->node);
1215 */
1216 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1217 return (((xmlSchemaAttributeUsePtr) item)->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001218 default:
1219 return (NULL);
1220 }
1221}
1222
1223#if 0
1224/**
1225 * xmlSchemaGetNextComponent:
1226 * @item: a schema component
1227 *
1228 * Returns the next sibling of the schema component.
1229 */
1230static xmlSchemaBasicItemPtr
1231xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1232{
1233 switch (item->type) {
1234 case XML_SCHEMA_TYPE_ELEMENT:
1235 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1236 case XML_SCHEMA_TYPE_ATTRIBUTE:
1237 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1238 case XML_SCHEMA_TYPE_COMPLEX:
1239 case XML_SCHEMA_TYPE_SIMPLE:
1240 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1241 case XML_SCHEMA_TYPE_ANY:
1242 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1243 return (NULL);
1244 case XML_SCHEMA_TYPE_PARTICLE:
1245 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1246 case XML_SCHEMA_TYPE_SEQUENCE:
1247 case XML_SCHEMA_TYPE_CHOICE:
1248 case XML_SCHEMA_TYPE_ALL:
1249 return (NULL);
1250 case XML_SCHEMA_TYPE_GROUP:
1251 return (NULL);
1252 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1253 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1254 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1255 case XML_SCHEMA_TYPE_IDC_KEY:
1256 case XML_SCHEMA_TYPE_IDC_KEYREF:
1257 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1258 default:
1259 return (NULL);
1260 }
1261}
1262#endif
1263
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001264
1265/**
1266 * xmlSchemaFormatQName:
1267 * @buf: the string buffer
1268 * @namespaceName: the namespace name
1269 * @localName: the local name
1270 *
1271 * Returns the given QName in the format "{namespaceName}localName" or
1272 * just "localName" if @namespaceName is NULL.
1273 *
1274 * Returns the localName if @namespaceName is NULL, a formatted
1275 * string otherwise.
1276 */
1277static const xmlChar*
1278xmlSchemaFormatQName(xmlChar **buf,
1279 const xmlChar *namespaceName,
1280 const xmlChar *localName)
1281{
1282 FREE_AND_NULL(*buf)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001283 if (namespaceName != NULL) {
1284 *buf = xmlStrdup(BAD_CAST "{");
1285 *buf = xmlStrcat(*buf, namespaceName);
1286 *buf = xmlStrcat(*buf, BAD_CAST "}");
1287 }
1288 if (localName != NULL) {
1289 if (namespaceName == NULL)
1290 return(localName);
1291 *buf = xmlStrcat(*buf, localName);
1292 } else {
1293 *buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
1294 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001295 return ((const xmlChar *) *buf);
1296}
1297
1298static const xmlChar*
1299xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1300{
1301 if (ns != NULL)
1302 return (xmlSchemaFormatQName(buf, ns->href, localName));
1303 else
1304 return (xmlSchemaFormatQName(buf, NULL, localName));
1305}
1306
1307static const xmlChar *
1308xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1309{
1310 switch (item->type) {
1311 case XML_SCHEMA_TYPE_ELEMENT:
1312 return (((xmlSchemaElementPtr) item)->name);
1313 case XML_SCHEMA_TYPE_ATTRIBUTE:
1314 return (((xmlSchemaAttributePtr) item)->name);
1315 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1316 return (((xmlSchemaAttributeGroupPtr) item)->name);
1317 case XML_SCHEMA_TYPE_BASIC:
1318 case XML_SCHEMA_TYPE_SIMPLE:
1319 case XML_SCHEMA_TYPE_COMPLEX:
1320 return (((xmlSchemaTypePtr) item)->name);
1321 case XML_SCHEMA_TYPE_GROUP:
1322 return (((xmlSchemaModelGroupDefPtr) item)->name);
1323 case XML_SCHEMA_TYPE_IDC_KEY:
1324 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1325 case XML_SCHEMA_TYPE_IDC_KEYREF:
1326 return (((xmlSchemaIDCPtr) item)->name);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001327 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1328 if (WXS_ATTRUSE_DECL(item) != NULL) {
1329 return(xmlSchemaGetComponentName(
1330 WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1331 } else
1332 return(NULL);
1333 case XML_SCHEMA_EXTRA_QNAMEREF:
1334 return (((xmlSchemaQNameRefPtr) item)->name);
1335 case XML_SCHEMA_TYPE_NOTATION:
1336 return (((xmlSchemaNotationPtr) item)->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001337 default:
1338 /*
1339 * Other components cannot have names.
1340 */
1341 break;
1342 }
1343 return (NULL);
1344}
1345
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001346#define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1347#define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1348/*
1349static const xmlChar *
1350xmlSchemaGetQNameRefName(void *ref)
1351{
1352 return(((xmlSchemaQNameRefPtr) ref)->name);
1353}
1354
1355static const xmlChar *
1356xmlSchemaGetQNameRefTargetNs(void *ref)
1357{
1358 return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1359}
1360*/
1361
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001362static const xmlChar *
1363xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1364{
1365 switch (item->type) {
1366 case XML_SCHEMA_TYPE_ELEMENT:
1367 return (((xmlSchemaElementPtr) item)->targetNamespace);
1368 case XML_SCHEMA_TYPE_ATTRIBUTE:
1369 return (((xmlSchemaAttributePtr) item)->targetNamespace);
1370 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1371 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1372 case XML_SCHEMA_TYPE_BASIC:
1373 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1374 case XML_SCHEMA_TYPE_SIMPLE:
1375 case XML_SCHEMA_TYPE_COMPLEX:
1376 return (((xmlSchemaTypePtr) item)->targetNamespace);
1377 case XML_SCHEMA_TYPE_GROUP:
1378 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1379 case XML_SCHEMA_TYPE_IDC_KEY:
1380 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1381 case XML_SCHEMA_TYPE_IDC_KEYREF:
1382 return (((xmlSchemaIDCPtr) item)->targetNamespace);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001383 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1384 if (WXS_ATTRUSE_DECL(item) != NULL) {
1385 return(xmlSchemaGetComponentTargetNs(
1386 WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1387 }
1388 /* TODO: Will returning NULL break something? */
1389 break;
1390 case XML_SCHEMA_EXTRA_QNAMEREF:
1391 return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1392 case XML_SCHEMA_TYPE_NOTATION:
1393 return (((xmlSchemaNotationPtr) item)->targetNamespace);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001394 default:
1395 /*
1396 * Other components cannot have names.
1397 */
1398 break;
1399 }
1400 return (NULL);
1401}
1402
1403static const xmlChar*
1404xmlSchemaGetComponentQName(xmlChar **buf,
1405 void *item)
1406{
1407 return (xmlSchemaFormatQName(buf,
1408 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1409 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1410}
1411
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001412static const xmlChar*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001413xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001414{
1415 xmlChar *str = NULL;
1416
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001417 *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001418 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001419 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1420 (xmlSchemaBasicItemPtr) item));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001421 *buf = xmlStrcat(*buf, BAD_CAST "'");
1422 FREE_AND_NULL(str);
1423 return(*buf);
1424}
1425
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001426static const xmlChar*
1427xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1428{
1429 return(xmlSchemaGetComponentDesignation(buf, idc));
1430}
1431
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001432/**
1433 * xmlSchemaWildcardPCToString:
1434 * @pc: the type of processContents
1435 *
1436 * Returns a string representation of the type of
1437 * processContents.
1438 */
1439static const xmlChar *
1440xmlSchemaWildcardPCToString(int pc)
1441{
1442 switch (pc) {
1443 case XML_SCHEMAS_ANY_SKIP:
1444 return (BAD_CAST "skip");
1445 case XML_SCHEMAS_ANY_LAX:
1446 return (BAD_CAST "lax");
1447 case XML_SCHEMAS_ANY_STRICT:
1448 return (BAD_CAST "strict");
1449 default:
1450 return (BAD_CAST "invalid process contents");
1451 }
1452}
1453
1454/**
1455 * xmlSchemaGetCanonValueWhtspExt:
1456 * @val: the precomputed value
1457 * @retValue: the returned value
1458 * @ws: the whitespace type of the value
1459 *
1460 * Get a the cononical representation of the value.
1461 * The caller has to free the returned retValue.
1462 *
1463 * Returns 0 if the value could be built and -1 in case of
1464 * API errors or if the value type is not supported yet.
1465 */
1466static int
1467xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1468 xmlSchemaWhitespaceValueType ws,
1469 xmlChar **retValue)
1470{
1471 int list;
1472 xmlSchemaValType valType;
1473 const xmlChar *value, *value2 = NULL;
1474
1475
1476 if ((retValue == NULL) || (val == NULL))
1477 return (-1);
1478 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1479 *retValue = NULL;
1480 do {
1481 value = NULL;
1482 valType = xmlSchemaGetValType(val);
1483 switch (valType) {
1484 case XML_SCHEMAS_STRING:
1485 case XML_SCHEMAS_NORMSTRING:
1486 case XML_SCHEMAS_ANYSIMPLETYPE:
1487 value = xmlSchemaValueGetAsString(val);
1488 if (value != NULL) {
1489 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1490 value2 = xmlSchemaCollapseString(value);
1491 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1492 value2 = xmlSchemaWhiteSpaceReplace(value);
1493 if (value2 != NULL)
1494 value = value2;
1495 }
1496 break;
1497 default:
1498 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1499 if (value2 != NULL)
1500 xmlFree((xmlChar *) value2);
1501 goto internal_error;
1502 }
1503 value = value2;
1504 }
1505 if (*retValue == NULL)
1506 if (value == NULL) {
1507 if (! list)
1508 *retValue = xmlStrdup(BAD_CAST "");
1509 } else
1510 *retValue = xmlStrdup(value);
1511 else if (value != NULL) {
1512 /* List. */
1513 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1514 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1515 }
1516 FREE_AND_NULL(value2)
1517 val = xmlSchemaValueGetNext(val);
1518 } while (val != NULL);
1519
1520 return (0);
1521internal_error:
1522 if (*retValue != NULL)
1523 xmlFree((xmlChar *) (*retValue));
1524 if (value2 != NULL)
1525 xmlFree((xmlChar *) value2);
1526 return (-1);
1527}
1528
1529/**
1530 * xmlSchemaFormatItemForReport:
1531 * @buf: the string buffer
1532 * @itemDes: the designation of the item
1533 * @itemName: the name of the item
1534 * @item: the item as an object
1535 * @itemNode: the node of the item
1536 * @local: the local name
1537 * @parsing: if the function is used during the parse
1538 *
1539 * Returns a representation of the given item used
1540 * for error reports.
1541 *
1542 * The following order is used to build the resulting
1543 * designation if the arguments are not NULL:
1544 * 1a. If itemDes not NULL -> itemDes
1545 * 1b. If (itemDes not NULL) and (itemName not NULL)
1546 * -> itemDes + itemName
1547 * 2. If the preceding was NULL and (item not NULL) -> item
1548 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1549 *
1550 * If the itemNode is an attribute node, the name of the attribute
1551 * will be appended to the result.
1552 *
1553 * Returns the formatted string and sets @buf to the resulting value.
1554 */
1555static xmlChar*
1556xmlSchemaFormatItemForReport(xmlChar **buf,
1557 const xmlChar *itemDes,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001558 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001559 xmlNodePtr itemNode)
1560{
1561 xmlChar *str = NULL;
1562 int named = 1;
1563
1564 if (*buf != NULL) {
1565 xmlFree(*buf);
1566 *buf = NULL;
1567 }
1568
1569 if (itemDes != NULL) {
1570 *buf = xmlStrdup(itemDes);
1571 } else if (item != NULL) {
1572 switch (item->type) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001573 case XML_SCHEMA_TYPE_BASIC: {
1574 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1575
1576 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001577 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001578 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001579 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001580 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001581 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1582 else
1583 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001584 *buf = xmlStrcat(*buf, type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001585 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001586 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001587 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001588 case XML_SCHEMA_TYPE_SIMPLE: {
1589 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1590
1591 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001592 *buf = xmlStrdup(BAD_CAST"");
1593 } else {
1594 *buf = xmlStrdup(BAD_CAST "local ");
1595 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001596 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001597 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001598 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001599 *buf = xmlStrcat(*buf, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001600 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001601 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1602 else
1603 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001604 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001605 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001606 *buf = xmlStrcat(*buf, type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001607 *buf = xmlStrcat(*buf, BAD_CAST "'");
1608 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001609 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001610 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001611 case XML_SCHEMA_TYPE_COMPLEX: {
1612 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1613
1614 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001615 *buf = xmlStrdup(BAD_CAST "");
1616 else
1617 *buf = xmlStrdup(BAD_CAST "local ");
1618 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001619 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001620 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001621 *buf = xmlStrcat(*buf, type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001622 *buf = xmlStrcat(*buf, BAD_CAST "'");
1623 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001624 }
1625 break;
1626 case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1627 xmlSchemaAttributeUsePtr ause;
1628
1629 ause = WXS_ATTR_USE_CAST item;
1630 *buf = xmlStrdup(BAD_CAST "attribute use ");
1631 if (WXS_ATTRUSE_DECL(ause) != NULL) {
1632 *buf = xmlStrcat(*buf, BAD_CAST "'");
1633 *buf = xmlStrcat(*buf,
1634 xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1635 FREE_AND_NULL(str)
1636 *buf = xmlStrcat(*buf, BAD_CAST "'");
1637 } else {
1638 *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1639 }
1640 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001641 break;
1642 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1643 xmlSchemaAttributePtr attr;
1644
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001645 attr = (xmlSchemaAttributePtr) item;
1646 *buf = xmlStrdup(BAD_CAST "attribute decl.");
1647 *buf = xmlStrcat(*buf, BAD_CAST " '");
1648 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1649 attr->targetNamespace, attr->name));
1650 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001651 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001652 }
1653 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001654 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1655 xmlSchemaGetComponentDesignation(buf, item);
1656 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001657 case XML_SCHEMA_TYPE_ELEMENT: {
1658 xmlSchemaElementPtr elem;
1659
1660 elem = (xmlSchemaElementPtr) item;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001661 *buf = xmlStrdup(BAD_CAST "element decl.");
1662 *buf = xmlStrcat(*buf, BAD_CAST " '");
1663 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1664 elem->targetNamespace, elem->name));
1665 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001666 }
1667 break;
1668 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1669 case XML_SCHEMA_TYPE_IDC_KEY:
1670 case XML_SCHEMA_TYPE_IDC_KEYREF:
1671 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1672 *buf = xmlStrdup(BAD_CAST "unique '");
1673 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1674 *buf = xmlStrdup(BAD_CAST "key '");
1675 else
1676 *buf = xmlStrdup(BAD_CAST "keyRef '");
1677 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1678 *buf = xmlStrcat(*buf, BAD_CAST "'");
1679 break;
1680 case XML_SCHEMA_TYPE_ANY:
1681 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1682 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1683 ((xmlSchemaWildcardPtr) item)->processContents));
1684 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1685 break;
1686 case XML_SCHEMA_FACET_MININCLUSIVE:
1687 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1688 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1689 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1690 case XML_SCHEMA_FACET_TOTALDIGITS:
1691 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1692 case XML_SCHEMA_FACET_PATTERN:
1693 case XML_SCHEMA_FACET_ENUMERATION:
1694 case XML_SCHEMA_FACET_WHITESPACE:
1695 case XML_SCHEMA_FACET_LENGTH:
1696 case XML_SCHEMA_FACET_MAXLENGTH:
1697 case XML_SCHEMA_FACET_MINLENGTH:
1698 *buf = xmlStrdup(BAD_CAST "facet '");
1699 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1700 *buf = xmlStrcat(*buf, BAD_CAST "'");
1701 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001702 case XML_SCHEMA_TYPE_GROUP: {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001703 *buf = xmlStrdup(BAD_CAST "model group def.");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001704 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001705 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001706 *buf = xmlStrcat(*buf, BAD_CAST "'");
1707 FREE_AND_NULL(str)
1708 }
1709 break;
1710 case XML_SCHEMA_TYPE_SEQUENCE:
1711 case XML_SCHEMA_TYPE_CHOICE:
1712 case XML_SCHEMA_TYPE_ALL:
1713 case XML_SCHEMA_TYPE_PARTICLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001714 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1715 break;
1716 case XML_SCHEMA_TYPE_NOTATION: {
1717 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1718 *buf = xmlStrcat(*buf, BAD_CAST " '");
1719 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1720 *buf = xmlStrcat(*buf, BAD_CAST "'");
1721 FREE_AND_NULL(str);
1722 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001723 default:
1724 named = 0;
1725 }
1726 } else
1727 named = 0;
1728
1729 if ((named == 0) && (itemNode != NULL)) {
1730 xmlNodePtr elem;
1731
1732 if (itemNode->type == XML_ATTRIBUTE_NODE)
1733 elem = itemNode->parent;
1734 else
1735 elem = itemNode;
1736 *buf = xmlStrdup(BAD_CAST "Element '");
1737 if (elem->ns != NULL) {
1738 *buf = xmlStrcat(*buf,
1739 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1740 FREE_AND_NULL(str)
1741 } else
1742 *buf = xmlStrcat(*buf, elem->name);
1743 *buf = xmlStrcat(*buf, BAD_CAST "'");
1744
1745 }
1746 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1747 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1748 if (itemNode->ns != NULL) {
1749 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1750 itemNode->ns->href, itemNode->name));
1751 FREE_AND_NULL(str)
1752 } else
1753 *buf = xmlStrcat(*buf, itemNode->name);
1754 *buf = xmlStrcat(*buf, BAD_CAST "'");
1755 }
1756 FREE_AND_NULL(str)
1757
1758 return (*buf);
1759}
1760
1761/**
1762 * xmlSchemaFormatFacetEnumSet:
1763 * @buf: the string buffer
1764 * @type: the type holding the enumeration facets
1765 *
1766 * Builds a string consisting of all enumeration elements.
1767 *
1768 * Returns a string of all enumeration elements.
1769 */
1770static const xmlChar *
1771xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1772 xmlChar **buf, xmlSchemaTypePtr type)
1773{
1774 xmlSchemaFacetPtr facet;
1775 xmlSchemaWhitespaceValueType ws;
1776 xmlChar *value = NULL;
1777 int res;
1778
1779 if (*buf != NULL)
1780 xmlFree(*buf);
1781 *buf = NULL;
1782
1783 do {
1784 /*
1785 * Use the whitespace type of the base type.
1786 */
1787 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1788 for (facet = type->facets; facet != NULL; facet = facet->next) {
1789 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1790 continue;
1791 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1792 ws, &value);
1793 if (res == -1) {
1794 xmlSchemaInternalErr(actxt,
1795 "xmlSchemaFormatFacetEnumSet",
1796 "compute the canonical lexical representation");
1797 if (*buf != NULL)
1798 xmlFree(*buf);
1799 *buf = NULL;
1800 return (NULL);
1801 }
1802 if (*buf == NULL)
1803 *buf = xmlStrdup(BAD_CAST "'");
1804 else
1805 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1806 *buf = xmlStrcat(*buf, BAD_CAST value);
1807 *buf = xmlStrcat(*buf, BAD_CAST "'");
1808 if (value != NULL) {
1809 xmlFree((xmlChar *)value);
1810 value = NULL;
1811 }
1812 }
1813 type = type->baseType;
1814 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1815
1816 return ((const xmlChar *) *buf);
1817}
1818
1819/************************************************************************
1820 * *
1821 * Error functions *
1822 * *
1823 ************************************************************************/
1824
1825#if 0
1826static void
1827xmlSchemaErrMemory(const char *msg)
1828{
1829 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1830 msg);
1831}
1832#endif
1833
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001834static void
1835xmlSchemaPSimpleErr(const char *msg)
1836{
1837 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1838 msg);
1839}
1840
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001841/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001842 * xmlSchemaPErrMemory:
1843 * @node: a context node
1844 * @extra: extra informations
1845 *
1846 * Handle an out of memory condition
1847 */
1848static void
1849xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1850 const char *extra, xmlNodePtr node)
1851{
1852 if (ctxt != NULL)
1853 ctxt->nberrors++;
1854 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1855 extra);
1856}
1857
1858/**
1859 * xmlSchemaPErr:
1860 * @ctxt: the parsing context
1861 * @node: the context node
1862 * @error: the error code
1863 * @msg: the error message
1864 * @str1: extra data
1865 * @str2: extra data
1866 *
1867 * Handle a parser error
1868 */
1869static void
1870xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1871 const char *msg, const xmlChar * str1, const xmlChar * str2)
1872{
1873 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001874 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001875 void *data = NULL;
1876
1877 if (ctxt != NULL) {
1878 ctxt->nberrors++;
Kasimier T. Buchcik940ab0c2005-10-19 17:00:53 +00001879 ctxt->err = error;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001880 channel = ctxt->error;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00001881 data = ctxt->errCtxt;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001882 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001883 }
Daniel Veillard659e71e2003-10-10 14:10:40 +00001884 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001885 error, XML_ERR_ERROR, NULL, 0,
1886 (const char *) str1, (const char *) str2, NULL, 0, 0,
1887 msg, str1, str2);
1888}
1889
1890/**
1891 * xmlSchemaPErr2:
1892 * @ctxt: the parsing context
1893 * @node: the context node
1894 * @node: the current child
1895 * @error: the error code
1896 * @msg: the error message
1897 * @str1: extra data
1898 * @str2: extra data
1899 *
1900 * Handle a parser error
1901 */
1902static void
1903xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1904 xmlNodePtr child, int error,
1905 const char *msg, const xmlChar * str1, const xmlChar * str2)
1906{
1907 if (child != NULL)
1908 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1909 else
1910 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1911}
1912
Daniel Veillard01fa6152004-06-29 17:04:39 +00001913
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001914/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001915 * xmlSchemaPErrExt:
1916 * @ctxt: the parsing context
1917 * @node: the context node
1918 * @error: the error code
1919 * @strData1: extra data
1920 * @strData2: extra data
1921 * @strData3: extra data
1922 * @msg: the message
1923 * @str1: extra parameter for the message display
1924 * @str2: extra parameter for the message display
1925 * @str3: extra parameter for the message display
1926 * @str4: extra parameter for the message display
1927 * @str5: extra parameter for the message display
1928 *
1929 * Handle a parser error
1930 */
1931static void
1932xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1933 const xmlChar * strData1, const xmlChar * strData2,
1934 const xmlChar * strData3, const char *msg, const xmlChar * str1,
1935 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1936 const xmlChar * str5)
1937{
1938
1939 xmlGenericErrorFunc channel = NULL;
1940 xmlStructuredErrorFunc schannel = NULL;
1941 void *data = NULL;
1942
1943 if (ctxt != NULL) {
1944 ctxt->nberrors++;
Kasimier T. Buchcik940ab0c2005-10-19 17:00:53 +00001945 ctxt->err = error;
Daniel Veillard3646d642004-06-02 19:19:14 +00001946 channel = ctxt->error;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00001947 data = ctxt->errCtxt;
Daniel Veillard3646d642004-06-02 19:19:14 +00001948 schannel = ctxt->serror;
1949 }
1950 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1951 error, XML_ERR_ERROR, NULL, 0,
1952 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +00001953 (const char *) strData3, 0, 0, msg, str1, str2,
1954 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +00001955}
Daniel Veillard01fa6152004-06-29 17:04:39 +00001956
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001957/************************************************************************
1958 * *
1959 * Allround error functions *
1960 * *
1961 ************************************************************************/
Daniel Veillard3646d642004-06-02 19:19:14 +00001962
1963/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001964 * xmlSchemaVTypeErrMemory:
1965 * @node: a context node
1966 * @extra: extra informations
1967 *
1968 * Handle an out of memory condition
1969 */
1970static void
1971xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1972 const char *extra, xmlNodePtr node)
1973{
1974 if (ctxt != NULL) {
1975 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001976 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001977 }
1978 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1979 extra);
1980}
1981
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001982static void
1983xmlSchemaPSimpleInternalErr(xmlNodePtr node,
1984 const char *msg, const xmlChar *str)
1985{
1986 __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
1987 msg, (const char *) str);
1988}
1989
1990#define WXS_ERROR_TYPE_ERROR 1
1991#define WXS_ERROR_TYPE_WARNING 2
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001992/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001993 * xmlSchemaErr3:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001994 * @ctxt: the validation context
1995 * @node: the context node
1996 * @error: the error code
1997 * @msg: the error message
1998 * @str1: extra data
1999 * @str2: extra data
2000 * @str3: extra data
2001 *
2002 * Handle a validation error
2003 */
2004static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002005xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002006 xmlErrorLevel errorLevel,
2007 int error, xmlNodePtr node, int line, const char *msg,
2008 const xmlChar *str1, const xmlChar *str2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002009 const xmlChar *str3, const xmlChar *str4)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002010{
Daniel Veillard659e71e2003-10-10 14:10:40 +00002011 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002012 xmlGenericErrorFunc channel = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002013 void *data = NULL;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002014
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002015 if (ctxt != NULL) {
2016 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2017 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
Daniel Veillard971771e2005-07-09 17:32:57 +00002018 const char *file = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002019 if (errorLevel != XML_ERR_WARNING) {
2020 vctxt->nberrors++;
2021 vctxt->err = error;
2022 channel = vctxt->error;
2023 } else {
2024 channel = vctxt->warning;
2025 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002026 schannel = vctxt->serror;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00002027 data = vctxt->errCtxt;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002028
2029 /*
2030 * Error node. If we specify a line number, then
2031 * do not channel any node to the error function.
2032 */
2033 if (line == 0) {
2034 if ((node == NULL) &&
2035 (vctxt->depth >= 0) &&
2036 (vctxt->inode != NULL)) {
2037 node = vctxt->inode->node;
2038 }
2039 /*
2040 * Get filename and line if no node-tree.
2041 */
2042 if ((node == NULL) &&
2043 (vctxt->parserCtxt != NULL) &&
2044 (vctxt->parserCtxt->input != NULL)) {
2045 file = vctxt->parserCtxt->input->filename;
2046 line = vctxt->parserCtxt->input->line;
2047 }
2048 } else {
2049 /*
2050 * Override the given node's (if any) position
2051 * and channel only the given line number.
2052 */
2053 node = NULL;
2054 /*
2055 * Get filename.
2056 */
2057 if (vctxt->doc != NULL)
2058 file = (const char *) vctxt->doc->URL;
2059 else if ((vctxt->parserCtxt != NULL) &&
2060 (vctxt->parserCtxt->input != NULL))
2061 file = vctxt->parserCtxt->input->filename;
2062 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002063 __xmlRaiseError(schannel, channel, data, ctxt,
2064 node, XML_FROM_SCHEMASV,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002065 error, errorLevel, file, line,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002066 (const char *) str1, (const char *) str2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002067 (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002068
2069 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2070 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002071 if (errorLevel != XML_ERR_WARNING) {
2072 pctxt->nberrors++;
2073 pctxt->err = error;
2074 channel = pctxt->error;
2075 } else {
2076 channel = pctxt->warning;
2077 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002078 schannel = pctxt->serror;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00002079 data = pctxt->errCtxt;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002080 __xmlRaiseError(schannel, channel, data, ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002081 node, XML_FROM_SCHEMASP, error,
2082 errorLevel, NULL, 0,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002083 (const char *) str1, (const char *) str2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002084 (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002085 } else {
2086 TODO
2087 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002088 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002089}
2090
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002091/**
2092 * xmlSchemaErr3:
2093 * @ctxt: the validation context
2094 * @node: the context node
2095 * @error: the error code
2096 * @msg: the error message
2097 * @str1: extra data
2098 * @str2: extra data
2099 * @str3: extra data
2100 *
2101 * Handle a validation error
2102 */
2103static void
2104xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2105 int error, xmlNodePtr node, const char *msg,
2106 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2107{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002108 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2109 msg, str1, str2, str3, NULL);
2110}
2111
2112static void
2113xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2114 int error, xmlNodePtr node, const char *msg,
2115 const xmlChar *str1, const xmlChar *str2,
2116 const xmlChar *str3, const xmlChar *str4)
2117{
2118 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2119 msg, str1, str2, str3, str4);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002120}
2121
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002122static void
2123xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2124 int error, xmlNodePtr node, const char *msg,
2125 const xmlChar *str1, const xmlChar *str2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002126{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002127 xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002128}
2129
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002130static xmlChar *
2131xmlSchemaFormatNodeForError(xmlChar ** msg,
2132 xmlSchemaAbstractCtxtPtr actxt,
2133 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002134{
2135 xmlChar *str = NULL;
2136
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002137 *msg = NULL;
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +00002138 if ((node != NULL) &&
2139 (node->type != XML_ELEMENT_NODE) &&
2140 (node->type != XML_ATTRIBUTE_NODE))
2141 {
2142 /*
2143 * Don't try to format other nodes than element and
2144 * attribute nodes.
2145 * Play save and return an empty string.
2146 */
2147 *msg = xmlStrdup(BAD_CAST "");
2148 return(*msg);
2149 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002150 if (node != NULL) {
2151 /*
2152 * Work on tree nodes.
2153 */
2154 if (node->type == XML_ATTRIBUTE_NODE) {
2155 xmlNodePtr elem = node->parent;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002156
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002157 *msg = xmlStrdup(BAD_CAST "Element '");
2158 if (elem->ns != NULL)
2159 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2160 elem->ns->href, elem->name));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002161 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002162 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2163 NULL, elem->name));
2164 FREE_AND_NULL(str);
2165 *msg = xmlStrcat(*msg, BAD_CAST "', ");
2166 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2167 } else {
2168 *msg = xmlStrdup(BAD_CAST "Element '");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002169 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002170 if (node->ns != NULL)
2171 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2172 node->ns->href, node->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002173 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002174 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2175 NULL, node->name));
2176 FREE_AND_NULL(str);
2177 *msg = xmlStrcat(*msg, BAD_CAST "': ");
2178 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2179 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2180 /*
2181 * Work on node infos.
2182 */
2183 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2184 xmlSchemaNodeInfoPtr ielem =
2185 vctxt->elemInfos[vctxt->depth];
2186
2187 *msg = xmlStrdup(BAD_CAST "Element '");
2188 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2189 ielem->nsName, ielem->localName));
2190 FREE_AND_NULL(str);
2191 *msg = xmlStrcat(*msg, BAD_CAST "', ");
2192 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2193 } else {
2194 *msg = xmlStrdup(BAD_CAST "Element '");
2195 }
2196 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2197 vctxt->inode->nsName, vctxt->inode->localName));
2198 FREE_AND_NULL(str);
2199 *msg = xmlStrcat(*msg, BAD_CAST "': ");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002200 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2201 /*
2202 * Hmm, no node while parsing?
2203 * Return an empty string, in case NULL will break something.
2204 */
2205 *msg = xmlStrdup(BAD_CAST "");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002206 } else {
2207 TODO
2208 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002209 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002210 /*
2211 * VAL TODO: The output of the given schema component is currently
2212 * disabled.
2213 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002214#if 0
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002215 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2216 *msg = xmlStrcat(*msg, BAD_CAST " [");
2217 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2218 NULL, type, NULL, 0));
2219 FREE_AND_NULL(str)
2220 *msg = xmlStrcat(*msg, BAD_CAST "]");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002221 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002222#endif
2223 return (*msg);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002224}
2225
Daniel Veillardc0826a72004-08-10 14:17:33 +00002226static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002227xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002228 const char *funcName,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002229 const char *message,
2230 const xmlChar *str1,
2231 const xmlChar *str2)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002232{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002233 xmlChar *msg = NULL;
2234
2235 msg = xmlStrdup(BAD_CAST "Internal error: ");
2236 msg = xmlStrcat(msg, BAD_CAST funcName);
2237 msg = xmlStrcat(msg, BAD_CAST ", ");
2238 msg = xmlStrcat(msg, BAD_CAST message);
2239 msg = xmlStrcat(msg, BAD_CAST ".\n");
2240
2241 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2242 xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002243 (const char *) msg, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002244
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002245 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002246 xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002247 (const char *) msg, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002248
2249 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002250}
2251
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002252static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002253xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2254 const char *funcName,
2255 const char *message)
2256{
2257 xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2258}
2259
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002260#if 0
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002261static void
2262xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2263 const char *funcName,
2264 const char *message,
2265 const xmlChar *str1,
2266 const xmlChar *str2)
2267{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002268 xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002269 str1, str2);
2270}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002271#endif
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002272
2273static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002274xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2275 xmlParserErrors error,
2276 xmlNodePtr node,
2277 xmlSchemaBasicItemPtr item,
2278 const char *message,
2279 const xmlChar *str1, const xmlChar *str2,
2280 const xmlChar *str3, const xmlChar *str4)
2281{
2282 xmlChar *msg = NULL;
2283
2284 if ((node == NULL) && (item != NULL) &&
2285 (actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2286 node = WXS_ITEM_NODE(item);
2287 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2288 msg = xmlStrcat(msg, BAD_CAST ": ");
2289 } else
2290 xmlSchemaFormatNodeForError(&msg, actxt, node);
2291 msg = xmlStrcat(msg, (const xmlChar *) message);
2292 msg = xmlStrcat(msg, BAD_CAST ".\n");
2293 xmlSchemaErr4(actxt, error, node,
2294 (const char *) msg, str1, str2, str3, str4);
2295 FREE_AND_NULL(msg)
2296}
2297
2298static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002299xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2300 xmlParserErrors error,
2301 xmlNodePtr node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002302 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002303 const char *message,
2304 const xmlChar *str1,
2305 const xmlChar *str2)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002306{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002307 xmlSchemaCustomErr4(actxt, error, node, item,
2308 message, str1, str2, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002309}
2310
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002311
2312
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002313static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002314xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2315 xmlParserErrors error,
2316 xmlNodePtr node,
2317 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2318 const char *message,
2319 const xmlChar *str1,
2320 const xmlChar *str2,
2321 const xmlChar *str3)
2322{
2323 xmlChar *msg = NULL;
2324
2325 xmlSchemaFormatNodeForError(&msg, actxt, node);
2326 msg = xmlStrcat(msg, (const xmlChar *) message);
2327 msg = xmlStrcat(msg, BAD_CAST ".\n");
2328
2329 /* URGENT TODO: Set the error code to something sane. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002330 xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2331 (const char *) msg, str1, str2, str3, NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002332
2333 FREE_AND_NULL(msg)
2334}
2335
2336
2337
2338static void
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002339xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2340 xmlParserErrors error,
2341 xmlSchemaPSVIIDCNodePtr idcNode,
2342 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2343 const char *message,
2344 const xmlChar *str1,
2345 const xmlChar *str2)
2346{
2347 xmlChar *msg = NULL, *qname = NULL;
2348
2349 msg = xmlStrdup(BAD_CAST "Element '%s': ");
2350 msg = xmlStrcat(msg, (const xmlChar *) message);
2351 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002352 xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002353 error, NULL, idcNode->nodeLine, (const char *) msg,
2354 xmlSchemaFormatQName(&qname,
2355 vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2356 vctxt->nodeQNames->items[idcNode->nodeQNameID]),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002357 str1, str2, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002358 FREE_AND_NULL(qname);
2359 FREE_AND_NULL(msg);
2360}
2361
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002362static int
2363xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2364 xmlNodePtr node)
2365{
2366 if (node != NULL)
2367 return (node->type);
2368 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2369 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2370 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2371 return (-1);
2372}
2373
2374static int
2375xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2376{
2377 switch (item->type) {
2378 case XML_SCHEMA_TYPE_COMPLEX:
2379 case XML_SCHEMA_TYPE_SIMPLE:
2380 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2381 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002382 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002383 case XML_SCHEMA_TYPE_GROUP:
2384 return (1);
2385 case XML_SCHEMA_TYPE_ELEMENT:
2386 if ( ((xmlSchemaElementPtr) item)->flags &
2387 XML_SCHEMAS_ELEM_GLOBAL)
2388 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002389 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002390 case XML_SCHEMA_TYPE_ATTRIBUTE:
2391 if ( ((xmlSchemaAttributePtr) item)->flags &
2392 XML_SCHEMAS_ATTR_GLOBAL)
2393 return(1);
2394 break;
2395 /* Note that attribute groups are always global. */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002396 default:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002397 return(1);
2398 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002399 return (0);
2400}
2401
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002402static void
2403xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2404 xmlParserErrors error,
2405 xmlNodePtr node,
2406 const xmlChar *value,
2407 xmlSchemaTypePtr type,
2408 int displayValue)
2409{
2410 xmlChar *msg = NULL;
2411
2412 xmlSchemaFormatNodeForError(&msg, actxt, node);
2413
2414 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2415 XML_ATTRIBUTE_NODE))
2416 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2417 else
2418 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2419 "value of ");
2420
2421 if (! xmlSchemaIsGlobalItem(type))
2422 msg = xmlStrcat(msg, BAD_CAST "the local ");
2423 else
2424 msg = xmlStrcat(msg, BAD_CAST "the ");
2425
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002426 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002427 msg = xmlStrcat(msg, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002428 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002429 msg = xmlStrcat(msg, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002430 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002431 msg = xmlStrcat(msg, BAD_CAST "union type");
2432
2433 if (xmlSchemaIsGlobalItem(type)) {
2434 xmlChar *str = NULL;
2435 msg = xmlStrcat(msg, BAD_CAST " '");
2436 if (type->builtInType != 0) {
2437 msg = xmlStrcat(msg, BAD_CAST "xs:");
2438 msg = xmlStrcat(msg, type->name);
2439 } else
2440 msg = xmlStrcat(msg,
2441 xmlSchemaFormatQName(&str,
2442 type->targetNamespace, type->name));
2443 msg = xmlStrcat(msg, BAD_CAST "'");
2444 FREE_AND_NULL(str);
2445 }
2446 msg = xmlStrcat(msg, BAD_CAST ".\n");
2447 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2448 XML_ATTRIBUTE_NODE))
2449 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2450 else
2451 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2452 FREE_AND_NULL(msg)
2453}
2454
Daniel Veillardc0826a72004-08-10 14:17:33 +00002455static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002456xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2457 xmlSchemaNodeInfoPtr ni,
2458 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002459{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002460 if (node != NULL) {
2461 if (node->ns != NULL)
2462 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2463 else
2464 return (xmlSchemaFormatQName(str, NULL, node->name));
2465 } else if (ni != NULL)
2466 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2467 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002468}
2469
Daniel Veillardc0826a72004-08-10 14:17:33 +00002470static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002471xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2472 xmlParserErrors error,
2473 xmlSchemaAttrInfoPtr ni,
2474 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002475{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002476 xmlChar *msg = NULL, *str = NULL;
2477
2478 xmlSchemaFormatNodeForError(&msg, actxt, node);
2479 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2480 xmlSchemaErr(actxt, error, node, (const char *) msg,
2481 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2482 NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002483 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002484 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002485}
2486
Daniel Veillardc0826a72004-08-10 14:17:33 +00002487static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002488xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2489 xmlParserErrors error,
2490 xmlNodePtr node,
2491 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002492 const char *message,
2493 int nbval,
2494 int nbneg,
2495 xmlChar **values)
2496{
2497 xmlChar *str = NULL, *msg = NULL;
2498 xmlChar *localName, *nsName;
2499 const xmlChar *cur, *end;
Daniel Veillard6a0baa02005-12-10 11:11:12 +00002500 int i;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002501
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002502 xmlSchemaFormatNodeForError(&msg, actxt, node);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002503 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002504 msg = xmlStrcat(msg, BAD_CAST ".");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002505 /*
2506 * Note that is does not make sense to report that we have a
2507 * wildcard here, since the wildcard might be unfolded into
2508 * multiple transitions.
2509 */
2510 if (nbval + nbneg > 0) {
2511 if (nbval + nbneg > 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002512 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002513 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002514 str = xmlStrdup(BAD_CAST " Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002515 nsName = NULL;
2516
2517 for (i = 0; i < nbval + nbneg; i++) {
2518 cur = values[i];
Daniel Veillard77005e62005-07-19 16:26:18 +00002519 if (cur == NULL)
2520 continue;
2521 if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2522 (cur[3] == ' ')) {
Daniel Veillard77005e62005-07-19 16:26:18 +00002523 cur += 4;
Daniel Veillard6e65e152005-08-09 11:09:52 +00002524 str = xmlStrcat(str, BAD_CAST "##other");
Daniel Veillard77005e62005-07-19 16:26:18 +00002525 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002526 /*
2527 * Get the local name.
2528 */
2529 localName = NULL;
2530
2531 end = cur;
2532 if (*end == '*') {
2533 localName = xmlStrdup(BAD_CAST "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00002534 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002535 } else {
2536 while ((*end != 0) && (*end != '|'))
2537 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002538 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002539 }
2540 if (*end != 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00002541 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002542 /*
2543 * Skip "*|*" if they come with negated expressions, since
2544 * they represent the same negated wildcard.
2545 */
2546 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2547 /*
2548 * Get the namespace name.
2549 */
2550 cur = end;
2551 if (*end == '*') {
2552 nsName = xmlStrdup(BAD_CAST "{*}");
2553 } else {
2554 while (*end != 0)
2555 end++;
2556
2557 if (i >= nbval)
2558 nsName = xmlStrdup(BAD_CAST "{##other:");
2559 else
2560 nsName = xmlStrdup(BAD_CAST "{");
2561
2562 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2563 nsName = xmlStrcat(nsName, BAD_CAST "}");
2564 }
2565 str = xmlStrcat(str, BAD_CAST nsName);
2566 FREE_AND_NULL(nsName)
2567 } else {
2568 FREE_AND_NULL(localName);
2569 continue;
2570 }
2571 }
2572 str = xmlStrcat(str, BAD_CAST localName);
2573 FREE_AND_NULL(localName);
2574
2575 if (i < nbval + nbneg -1)
2576 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00002577 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002578 str = xmlStrcat(str, BAD_CAST " ).\n");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002579 msg = xmlStrcat(msg, BAD_CAST str);
2580 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002581 } else
2582 msg = xmlStrcat(msg, BAD_CAST "\n");
2583 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002584 xmlFree(msg);
2585}
2586
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002587static void
2588xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2589 xmlParserErrors error,
2590 xmlNodePtr node,
2591 const xmlChar *value,
2592 unsigned long length,
2593 xmlSchemaTypePtr type,
2594 xmlSchemaFacetPtr facet,
2595 const char *message,
2596 const xmlChar *str1,
2597 const xmlChar *str2)
2598{
2599 xmlChar *str = NULL, *msg = NULL;
2600 xmlSchemaTypeType facetType;
2601 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2602
2603 xmlSchemaFormatNodeForError(&msg, actxt, node);
2604 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2605 facetType = XML_SCHEMA_FACET_ENUMERATION;
2606 /*
2607 * If enumerations are validated, one must not expect the
2608 * facet to be given.
2609 */
2610 } else
2611 facetType = facet->type;
2612 msg = xmlStrcat(msg, BAD_CAST "[");
2613 msg = xmlStrcat(msg, BAD_CAST "facet '");
2614 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2615 msg = xmlStrcat(msg, BAD_CAST "'] ");
2616 if (message == NULL) {
2617 /*
2618 * Use a default message.
2619 */
2620 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2621 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2622 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2623
2624 char len[25], actLen[25];
2625
2626 /* FIXME, TODO: What is the max expected string length of the
2627 * this value?
2628 */
2629 if (nodeType == XML_ATTRIBUTE_NODE)
2630 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2631 else
2632 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2633
2634 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2635 snprintf(actLen, 24, "%lu", length);
2636
2637 if (facetType == XML_SCHEMA_FACET_LENGTH)
2638 msg = xmlStrcat(msg,
2639 BAD_CAST "this differs from the allowed length of '%s'.\n");
2640 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2641 msg = xmlStrcat(msg,
2642 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2643 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2644 msg = xmlStrcat(msg,
2645 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2646
2647 if (nodeType == XML_ATTRIBUTE_NODE)
2648 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2649 value, (const xmlChar *) actLen, (const xmlChar *) len);
2650 else
2651 xmlSchemaErr(actxt, error, node, (const char *) msg,
2652 (const xmlChar *) actLen, (const xmlChar *) len);
2653
2654 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2655 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2656 "of the set {%s}.\n");
2657 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2658 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2659 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2660 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2661 "by the pattern '%s'.\n");
2662 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2663 facet->value);
2664 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2665 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2666 "minimum value allowed ('%s').\n");
2667 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2668 facet->value);
2669 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2670 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2671 "maximum value allowed ('%s').\n");
2672 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2673 facet->value);
2674 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00002675 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002676 "'%s'.\n");
2677 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2678 facet->value);
2679 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00002680 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002681 "'%s'.\n");
2682 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2683 facet->value);
2684 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2685 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2686 "digits than are allowed ('%s').\n");
2687 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2688 facet->value);
2689 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2690 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2691 "digits than are allowed ('%s').\n");
2692 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2693 facet->value);
2694 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2695 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2696 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2697 } else {
2698 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2699 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2700 }
2701 } else {
2702 msg = xmlStrcat(msg, (const xmlChar *) message);
2703 msg = xmlStrcat(msg, BAD_CAST ".\n");
2704 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2705 }
2706 FREE_AND_NULL(str)
2707 xmlFree(msg);
2708}
2709
2710#define VERROR(err, type, msg) \
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002711 xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002712
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002713#define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002714
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002715#define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2716#define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002717
2718#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2719
2720
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002721/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00002722 * xmlSchemaPMissingAttrErr:
2723 * @ctxt: the schema validation context
2724 * @ownerDes: the designation of the owner
2725 * @ownerName: the name of the owner
2726 * @ownerItem: the owner as a schema object
2727 * @ownerElem: the owner as an element node
2728 * @node: the parent element node of the missing attribute node
2729 * @type: the corresponding type of the attribute node
2730 *
2731 * Reports an illegal attribute.
2732 */
2733static void
2734xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002735 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002736 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002737 xmlNodePtr ownerElem,
2738 const char *name,
2739 const char *message)
2740{
2741 xmlChar *des = NULL;
2742
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002743 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2744
Daniel Veillardc0826a72004-08-10 14:17:33 +00002745 if (message != NULL)
2746 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002747 else
2748 xmlSchemaPErr(ctxt, ownerElem, error,
2749 "%s: The attribute '%s' is required but missing.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002750 BAD_CAST des, BAD_CAST name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002751 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002752}
2753
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002754
Daniel Veillardc0826a72004-08-10 14:17:33 +00002755/**
2756 * xmlSchemaPResCompAttrErr:
2757 * @ctxt: the schema validation context
2758 * @error: the error code
2759 * @ownerDes: the designation of the owner
2760 * @ownerItem: the owner as a schema object
2761 * @ownerElem: the owner as an element node
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002762 * @name: the name of the attribute holding the QName
Daniel Veillardc0826a72004-08-10 14:17:33 +00002763 * @refName: the referenced local name
2764 * @refURI: the referenced namespace URI
2765 * @message: optional message
2766 *
2767 * Used to report QName attribute values that failed to resolve
2768 * to schema components.
2769 */
2770static void
2771xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002772 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002773 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002774 xmlNodePtr ownerElem,
2775 const char *name,
2776 const xmlChar *refName,
2777 const xmlChar *refURI,
2778 xmlSchemaTypeType refType,
2779 const char *refTypeStr)
2780{
2781 xmlChar *des = NULL, *strA = NULL;
2782
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002783 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002784 if (refTypeStr == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002785 refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002786 xmlSchemaPErrExt(ctxt, ownerElem, error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002787 NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002788 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2789 "%s.\n", BAD_CAST des, BAD_CAST name,
2790 xmlSchemaFormatQName(&strA, refURI, refName),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002791 BAD_CAST refTypeStr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002792 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002793 FREE_AND_NULL(strA)
2794}
2795
William M. Brack2f2a6632004-08-20 23:09:47 +00002796/**
2797 * xmlSchemaPCustomAttrErr:
2798 * @ctxt: the schema parser context
2799 * @error: the error code
2800 * @ownerDes: the designation of the owner
2801 * @ownerItem: the owner as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002802 * @attr: the illegal attribute node
William M. Brack2f2a6632004-08-20 23:09:47 +00002803 *
2804 * Reports an illegal attribute during the parse.
2805 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002806static void
2807xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002808 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002809 xmlChar **ownerDes,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002810 xmlSchemaBasicItemPtr ownerItem,
William M. Brack2f2a6632004-08-20 23:09:47 +00002811 xmlAttrPtr attr,
2812 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002813{
2814 xmlChar *des = NULL;
2815
2816 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002817 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002818 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002819 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002820 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002821 } else
2822 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002823 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002824 "%s, attribute '%s': %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002825 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2826 if (ownerDes == NULL)
2827 FREE_AND_NULL(des);
2828}
2829
2830/**
2831 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002832 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002833 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002834 * @ownerDes: the designation of the attribute's owner
2835 * @ownerItem: the attribute's owner item
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002836 * @attr: the illegal attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00002837 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002838 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002839 */
2840static void
2841xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002842 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002843 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002844 xmlAttrPtr attr)
2845{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002846 xmlChar *strA = NULL, *strB = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002847
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002848 xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2849 xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2850 "%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2851 xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2852 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002853 FREE_AND_NULL(strA);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002854 FREE_AND_NULL(strB);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002855}
2856
William M. Brack2f2a6632004-08-20 23:09:47 +00002857/**
2858 * xmlSchemaPCustomErr:
2859 * @ctxt: the schema parser context
2860 * @error: the error code
2861 * @itemDes: the designation of the schema item
2862 * @item: the schema item
2863 * @itemElem: the node of the schema item
2864 * @message: the error message
2865 * @str1: an optional param for the error message
2866 * @str2: an optional param for the error message
2867 * @str3: an optional param for the error message
2868 *
2869 * Reports an error during parsing.
2870 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002871static void
2872xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002873 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002874 xmlSchemaBasicItemPtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002875 xmlNodePtr itemElem,
2876 const char *message,
2877 const xmlChar *str1,
2878 const xmlChar *str2,
2879 const xmlChar *str3)
2880{
2881 xmlChar *des = NULL, *msg = NULL;
2882
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002883 xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002884 msg = xmlStrdup(BAD_CAST "%s: ");
2885 msg = xmlStrcat(msg, (const xmlChar *) message);
2886 msg = xmlStrcat(msg, BAD_CAST ".\n");
2887 if ((itemElem == NULL) && (item != NULL))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002888 itemElem = WXS_ITEM_NODE(item);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002889 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002890 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002891 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002892 FREE_AND_NULL(msg);
2893}
2894
William M. Brack2f2a6632004-08-20 23:09:47 +00002895/**
2896 * xmlSchemaPCustomErr:
2897 * @ctxt: the schema parser context
2898 * @error: the error code
2899 * @itemDes: the designation of the schema item
2900 * @item: the schema item
2901 * @itemElem: the node of the schema item
2902 * @message: the error message
2903 * @str1: the optional param for the error message
2904 *
2905 * Reports an error during parsing.
2906 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002907static void
2908xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002909 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002910 xmlSchemaBasicItemPtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002911 xmlNodePtr itemElem,
2912 const char *message,
2913 const xmlChar *str1)
2914{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002915 xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002916 str1, NULL, NULL);
2917}
2918
William M. Brack2f2a6632004-08-20 23:09:47 +00002919/**
2920 * xmlSchemaPAttrUseErr:
2921 * @ctxt: the schema parser context
2922 * @error: the error code
2923 * @itemDes: the designation of the schema type
2924 * @item: the schema type
2925 * @itemElem: the node of the schema type
2926 * @attr: the invalid schema attribute
2927 * @message: the error message
2928 * @str1: the optional param for the error message
2929 *
2930 * Reports an attribute use error during parsing.
2931 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002932static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002933xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002934 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002935 xmlNodePtr node,
2936 xmlSchemaBasicItemPtr ownerItem,
2937 const xmlSchemaAttributeUsePtr attruse,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002938 const char *message,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002939 const xmlChar *str1, const xmlChar *str2,
2940 const xmlChar *str3,const xmlChar *str4)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002941{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002942 xmlChar *str = NULL, *msg = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002943
2944 xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
2945 msg = xmlStrcat(msg, BAD_CAST ", ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002946 msg = xmlStrcat(msg,
2947 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002948 WXS_BASIC_CAST attruse, NULL));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002949 FREE_AND_NULL(str);
2950 msg = xmlStrcat(msg, BAD_CAST ": ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002951 msg = xmlStrcat(msg, (const xmlChar *) message);
2952 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002953 xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
2954 (const char *) msg, str1, str2, str3, str4);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002955 xmlFree(msg);
2956}
2957
William M. Brack2f2a6632004-08-20 23:09:47 +00002958/**
2959 * xmlSchemaPIllegalFacetAtomicErr:
2960 * @ctxt: the schema parser context
2961 * @error: the error code
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002962 * @type: the schema type
2963 * @baseType: the base type of type
William M. Brack2f2a6632004-08-20 23:09:47 +00002964 * @facet: the illegal facet
2965 *
2966 * Reports an illegal facet for atomic simple types.
2967 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002968static void
2969xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002970 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002971 xmlSchemaTypePtr type,
2972 xmlSchemaTypePtr baseType,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002973 xmlSchemaFacetPtr facet)
2974{
2975 xmlChar *des = NULL, *strT = NULL;
2976
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002977 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
2978 xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002979 "%s: The facet '%s' is not allowed on types derived from the "
2980 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002981 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002982 xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002983 NULL, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002984 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002985 FREE_AND_NULL(strT);
2986}
2987
William M. Brack2f2a6632004-08-20 23:09:47 +00002988/**
2989 * xmlSchemaPIllegalFacetListUnionErr:
2990 * @ctxt: the schema parser context
2991 * @error: the error code
2992 * @itemDes: the designation of the schema item involved
2993 * @item: the schema item involved
2994 * @facet: the illegal facet
2995 *
2996 * Reports an illegal facet for <list> and <union>.
2997 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002998static void
2999xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003000 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003001 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003002 xmlSchemaFacetPtr facet)
3003{
3004 xmlChar *des = NULL, *strT = NULL;
3005
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003006 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3007 type->node);
3008 xmlSchemaPErr(ctxt, type->node, error,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003009 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00003010 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003011 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003012 FREE_AND_NULL(strT);
3013}
3014
3015/**
3016 * xmlSchemaPMutualExclAttrErr:
3017 * @ctxt: the schema validation context
3018 * @error: the error code
3019 * @elemDes: the designation of the parent element node
3020 * @attr: the bad attribute node
3021 * @type: the corresponding type of the attribute node
3022 *
3023 * Reports an illegal attribute.
3024 */
3025static void
3026xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3027 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003028 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003029 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003030 const char *name1,
3031 const char *name2)
3032{
3033 xmlChar *des = NULL;
3034
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003035 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003036 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003037 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003038 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003039 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003040}
3041
3042/**
3043 * xmlSchemaPSimpleTypeErr:
3044 * @ctxt: the schema validation context
3045 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00003046 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00003047 * @ownerDes: the designation of the owner
3048 * @ownerItem: the schema object if existent
3049 * @node: the validated node
3050 * @value: the validated value
3051 *
3052 * Reports a simple type validation error.
3053 * TODO: Should this report the value of an element as well?
3054 */
3055static void
3056xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3057 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003058 xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003059 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00003060 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003061 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003062 const xmlChar *value,
3063 const char *message,
3064 const xmlChar *str1,
3065 const xmlChar *str2)
3066{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003067 xmlChar *msg = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003068
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003069 xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003070 if (message == NULL) {
3071 /*
3072 * Use default messages.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003073 */
3074 if (type != NULL) {
3075 if (node->type == XML_ATTRIBUTE_NODE)
3076 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3077 else
3078 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3079 "valid value of ");
3080 if (! xmlSchemaIsGlobalItem(type))
3081 msg = xmlStrcat(msg, BAD_CAST "the local ");
3082 else
3083 msg = xmlStrcat(msg, BAD_CAST "the ");
3084
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003085 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003086 msg = xmlStrcat(msg, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003087 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003088 msg = xmlStrcat(msg, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003089 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003090 msg = xmlStrcat(msg, BAD_CAST "union type");
3091
3092 if (xmlSchemaIsGlobalItem(type)) {
3093 xmlChar *str = NULL;
3094 msg = xmlStrcat(msg, BAD_CAST " '");
3095 if (type->builtInType != 0) {
3096 msg = xmlStrcat(msg, BAD_CAST "xs:");
3097 msg = xmlStrcat(msg, type->name);
3098 } else
3099 msg = xmlStrcat(msg,
3100 xmlSchemaFormatQName(&str,
3101 type->targetNamespace, type->name));
3102 msg = xmlStrcat(msg, BAD_CAST "'.");
3103 FREE_AND_NULL(str);
3104 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003105 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003106 if (node->type == XML_ATTRIBUTE_NODE)
3107 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3108 else
3109 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3110 "valid.");
3111 }
3112 if (expected) {
3113 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3114 msg = xmlStrcat(msg, BAD_CAST expected);
3115 msg = xmlStrcat(msg, BAD_CAST "'.\n");
3116 } else
3117 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00003118 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003119 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3120 else
3121 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3122 } else {
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00003123 msg = xmlStrcat(msg, BAD_CAST message);
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00003124 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003125 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00003126 (const char*) msg, str1, str2, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003127 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003128 /* Cleanup. */
3129 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003130}
3131
William M. Brack2f2a6632004-08-20 23:09:47 +00003132/**
3133 * xmlSchemaPContentErr:
3134 * @ctxt: the schema parser context
3135 * @error: the error code
3136 * @onwerDes: the designation of the holder of the content
3137 * @ownerItem: the owner item of the holder of the content
3138 * @ownerElem: the node of the holder of the content
3139 * @child: the invalid child node
3140 * @message: the optional error message
3141 * @content: the optional string describing the correct content
3142 *
3143 * Reports an error concerning the content of a schema element.
3144 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00003145static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003146xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003147 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003148 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003149 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003150 xmlNodePtr child,
3151 const char *message,
3152 const char *content)
3153{
3154 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003155
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003156 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003157 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003158 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3159 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003160 BAD_CAST des, BAD_CAST message);
3161 else {
3162 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003163 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3164 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003165 BAD_CAST des, BAD_CAST content);
3166 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003167 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3168 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003169 BAD_CAST des, NULL);
3170 }
3171 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003172 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003173}
3174
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003175/************************************************************************
3176 * *
3177 * Streamable error functions *
3178 * *
3179 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00003180
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003181
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003182
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003183
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003184/************************************************************************
3185 * *
3186 * Validation helper functions *
3187 * *
3188 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003189
Daniel Veillardc0826a72004-08-10 14:17:33 +00003190
Daniel Veillard4255d502002-04-16 15:50:10 +00003191/************************************************************************
3192 * *
3193 * Allocation functions *
3194 * *
3195 ************************************************************************/
3196
3197/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003198 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00003199 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00003200 *
3201 * Allocate a new Schema structure.
3202 *
3203 * Returns the newly allocated structure or NULL in case or error
3204 */
3205static xmlSchemaPtr
3206xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3207{
3208 xmlSchemaPtr ret;
3209
3210 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3211 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003212 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003213 return (NULL);
3214 }
3215 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003216 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003217 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003218
3219 return (ret);
3220}
3221
3222/**
3223 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00003224 *
3225 * Allocate a new Facet structure.
3226 *
3227 * Returns the newly allocated structure or NULL in case or error
3228 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003229xmlSchemaFacetPtr
3230xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00003231{
3232 xmlSchemaFacetPtr ret;
3233
3234 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3235 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003236 return (NULL);
3237 }
3238 memset(ret, 0, sizeof(xmlSchemaFacet));
3239
3240 return (ret);
3241}
3242
3243/**
3244 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00003245 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00003246 * @node: a node
3247 *
3248 * Allocate a new annotation structure.
3249 *
3250 * Returns the newly allocated structure or NULL in case or error
3251 */
3252static xmlSchemaAnnotPtr
3253xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3254{
3255 xmlSchemaAnnotPtr ret;
3256
3257 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3258 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003259 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003260 return (NULL);
3261 }
3262 memset(ret, 0, sizeof(xmlSchemaAnnot));
3263 ret->content = node;
3264 return (ret);
3265}
3266
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003267static xmlSchemaItemListPtr
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003268xmlSchemaItemListCreate(void)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003269{
3270 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003271
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003272 ret = xmlMalloc(sizeof(xmlSchemaItemList));
3273 if (ret == NULL) {
3274 xmlSchemaPErrMemory(NULL,
3275 "allocating an item list structure", NULL);
3276 return (NULL);
3277 }
3278 memset(ret, 0, sizeof(xmlSchemaItemList));
3279 return (ret);
3280}
3281
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00003282static void
3283xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3284{
3285 if (list->items != NULL) {
3286 xmlFree(list->items);
3287 list->items = NULL;
3288 }
3289 list->nbItems = 0;
3290 list->sizeItems = 0;
3291}
3292
3293static int
3294xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3295{
3296 if (list->items == NULL) {
3297 list->items = (void **) xmlMalloc(
3298 20 * sizeof(void *));
3299 if (list->items == NULL) {
3300 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3301 return(-1);
3302 }
3303 list->sizeItems = 20;
3304 } else if (list->sizeItems <= list->nbItems) {
3305 list->sizeItems *= 2;
3306 list->items = (void **) xmlRealloc(list->items,
3307 list->sizeItems * sizeof(void *));
3308 if (list->items == NULL) {
3309 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3310 list->sizeItems = 0;
3311 return(-1);
3312 }
3313 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00003314 list->items[list->nbItems++] = item;
3315 return(0);
3316}
3317
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003318static int
3319xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3320 int initialSize,
3321 void *item)
3322{
3323 if (list->items == NULL) {
3324 if (initialSize <= 0)
3325 initialSize = 1;
3326 list->items = (void **) xmlMalloc(
3327 initialSize * sizeof(void *));
3328 if (list->items == NULL) {
3329 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3330 return(-1);
3331 }
3332 list->sizeItems = initialSize;
3333 } else if (list->sizeItems <= list->nbItems) {
3334 list->sizeItems *= 2;
3335 list->items = (void **) xmlRealloc(list->items,
3336 list->sizeItems * sizeof(void *));
3337 if (list->items == NULL) {
3338 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3339 list->sizeItems = 0;
3340 return(-1);
3341 }
3342 }
3343 list->items[list->nbItems++] = item;
3344 return(0);
3345}
3346
3347static int
3348xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3349{
3350 if (list->items == NULL) {
3351 list->items = (void **) xmlMalloc(
3352 20 * sizeof(void *));
3353 if (list->items == NULL) {
3354 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3355 return(-1);
3356 }
3357 list->sizeItems = 20;
3358 } else if (list->sizeItems <= list->nbItems) {
3359 list->sizeItems *= 2;
3360 list->items = (void **) xmlRealloc(list->items,
3361 list->sizeItems * sizeof(void *));
3362 if (list->items == NULL) {
3363 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3364 list->sizeItems = 0;
3365 return(-1);
3366 }
3367 }
3368 /*
3369 * Just append if the index is greater/equal than the item count.
3370 */
3371 if (idx >= list->nbItems) {
3372 list->items[list->nbItems++] = item;
3373 } else {
3374 int i;
3375 for (i = list->nbItems; i > idx; i--)
3376 list->items[i] = list->items[i-1];
3377 list->items[idx] = item;
3378 list->nbItems++;
3379 }
3380 return(0);
3381}
3382
3383#if 0 /* enable if ever needed */
3384static int
3385xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3386 int initialSize,
3387 void *item,
3388 int idx)
3389{
3390 if (list->items == NULL) {
3391 if (initialSize <= 0)
3392 initialSize = 1;
3393 list->items = (void **) xmlMalloc(
3394 initialSize * sizeof(void *));
3395 if (list->items == NULL) {
3396 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3397 return(-1);
3398 }
3399 list->sizeItems = initialSize;
3400 } else if (list->sizeItems <= list->nbItems) {
3401 list->sizeItems *= 2;
3402 list->items = (void **) xmlRealloc(list->items,
3403 list->sizeItems * sizeof(void *));
3404 if (list->items == NULL) {
3405 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3406 list->sizeItems = 0;
3407 return(-1);
3408 }
3409 }
3410 /*
3411 * Just append if the index is greater/equal than the item count.
3412 */
3413 if (idx >= list->nbItems) {
3414 list->items[list->nbItems++] = item;
3415 } else {
3416 int i;
3417 for (i = list->nbItems; i > idx; i--)
3418 list->items[i] = list->items[i-1];
3419 list->items[idx] = item;
3420 list->nbItems++;
3421 }
3422 return(0);
3423}
3424#endif
3425
3426static int
3427xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3428{
3429 int i;
3430 if ((list->items == NULL) || (idx >= list->nbItems)) {
3431 xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3432 "index error.\n");
3433 return(-1);
3434 }
3435
3436 if (list->nbItems == 1) {
3437 /* TODO: Really free the list? */
3438 xmlFree(list->items);
3439 list->items = NULL;
3440 list->nbItems = 0;
3441 list->sizeItems = 0;
3442 } else if (list->nbItems -1 == idx) {
3443 list->nbItems--;
3444 } else {
3445 for (i = idx; i < list->nbItems -1; i++)
3446 list->items[i] = list->items[i+1];
3447 list->nbItems--;
3448 }
3449 return(0);
3450}
3451
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003452/**
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003453 * xmlSchemaItemListFree:
3454 * @annot: a schema type structure
3455 *
3456 * Deallocate a annotation structure
3457 */
3458static void
3459xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3460{
3461 if (list == NULL)
3462 return;
3463 if (list->items != NULL)
3464 xmlFree(list->items);
3465 xmlFree(list);
3466}
3467
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003468static void
3469xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003470{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003471 if (bucket == NULL)
3472 return;
3473 if (bucket->globals != NULL) {
3474 xmlSchemaComponentListFree(bucket->globals);
3475 xmlSchemaItemListFree(bucket->globals);
3476 }
3477 if (bucket->locals != NULL) {
3478 xmlSchemaComponentListFree(bucket->locals);
3479 xmlSchemaItemListFree(bucket->locals);
3480 }
3481 if (bucket->relations != NULL) {
3482 xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3483 do {
3484 prev = cur;
3485 cur = cur->next;
3486 xmlFree(prev);
3487 } while (cur != NULL);
3488 }
3489 if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3490 xmlFreeDoc(bucket->doc);
3491 }
3492 if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003493 if (WXS_IMPBUCKET(bucket)->schema != NULL)
3494 xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003495 }
3496 xmlFree(bucket);
3497}
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003498
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003499static xmlSchemaBucketPtr
3500xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003501 int type, const xmlChar *targetNamespace)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003502{
3503 xmlSchemaBucketPtr ret;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003504 int size;
3505 xmlSchemaPtr mainSchema;
3506
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003507 if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003508 PERROR_INT("xmlSchemaBucketCreate",
3509 "no main schema on constructor");
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003510 return(NULL);
3511 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003512 mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003513 /* Create the schema bucket. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003514 if (WXS_IS_BUCKET_INCREDEF(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003515 size = sizeof(xmlSchemaInclude);
3516 else
3517 size = sizeof(xmlSchemaImport);
3518 ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3519 if (ret == NULL) {
3520 xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3521 return(NULL);
3522 }
3523 memset(ret, 0, size);
3524 ret->targetNamespace = targetNamespace;
3525 ret->type = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003526 ret->globals = xmlSchemaItemListCreate();
3527 if (ret->globals == NULL) {
3528 xmlFree(ret);
3529 return(NULL);
3530 }
3531 ret->locals = xmlSchemaItemListCreate();
3532 if (ret->locals == NULL) {
3533 xmlFree(ret);
3534 return(NULL);
3535 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003536 /*
3537 * The following will assure that only the first bucket is marked as
3538 * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3539 * For each following import buckets an xmlSchema will be created.
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003540 * An xmlSchema will be created for every distinct targetNamespace.
3541 * We assign the targetNamespace to the schemata here.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003542 */
3543 if (! WXS_HAS_BUCKETS(pctxt)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003544 if (WXS_IS_BUCKET_INCREDEF(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003545 PERROR_INT("xmlSchemaBucketCreate",
3546 "first bucket but it's an include or redefine");
3547 xmlSchemaBucketFree(ret);
3548 return(NULL);
3549 }
3550 /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3551 ret->type = XML_SCHEMA_SCHEMA_MAIN;
3552 /* Point to the *main* schema. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003553 WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3554 WXS_IMPBUCKET(ret)->schema = mainSchema;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003555 /*
3556 * Ensure that the main schema gets a targetNamespace.
3557 */
3558 mainSchema->targetNamespace = targetNamespace;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003559 } else {
3560 if (type == XML_SCHEMA_SCHEMA_MAIN) {
3561 PERROR_INT("xmlSchemaBucketCreate",
3562 "main bucket but it's not the first one");
3563 xmlSchemaBucketFree(ret);
3564 return(NULL);
3565 } else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3566 /*
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003567 * Create a schema for imports and assign the
3568 * targetNamespace.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003569 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003570 WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3571 if (WXS_IMPBUCKET(ret)->schema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003572 xmlSchemaBucketFree(ret);
3573 return(NULL);
3574 }
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003575 WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003576 }
3577 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003578 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003579 int res;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003580 /*
3581 * Imports go into the "schemasImports" slot of the main *schema*.
3582 * Note that we create an import entry for the main schema as well; i.e.,
3583 * even if there's only one schema, we'll get an import.
3584 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003585 if (mainSchema->schemasImports == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003586 mainSchema->schemasImports = xmlHashCreateDict(5,
3587 WXS_CONSTRUCTOR(pctxt)->dict);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003588 if (mainSchema->schemasImports == NULL) {
3589 xmlSchemaBucketFree(ret);
3590 return(NULL);
3591 }
3592 }
3593 if (targetNamespace == NULL)
3594 res = xmlHashAddEntry(mainSchema->schemasImports,
3595 XML_SCHEMAS_NO_NAMESPACE, ret);
3596 else
3597 res = xmlHashAddEntry(mainSchema->schemasImports,
3598 targetNamespace, ret);
3599 if (res != 0) {
3600 PERROR_INT("xmlSchemaBucketCreate",
3601 "failed to add the schema bucket to the hash");
3602 xmlSchemaBucketFree(ret);
3603 return(NULL);
3604 }
3605 } else {
3606 /* Set the @ownerImport of an include bucket. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003607 if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3608 WXS_INCBUCKET(ret)->ownerImport =
3609 WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003610 else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003611 WXS_INCBUCKET(ret)->ownerImport =
3612 WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003613
3614 /* Includes got into the "includes" slot of the *main* schema. */
3615 if (mainSchema->includes == NULL) {
3616 mainSchema->includes = xmlSchemaItemListCreate();
3617 if (mainSchema->includes == NULL) {
3618 xmlSchemaBucketFree(ret);
3619 return(NULL);
3620 }
3621 }
3622 xmlSchemaItemListAdd(mainSchema->includes, ret);
3623 }
3624 /*
3625 * Add to list of all buckets; this is used for lookup
3626 * during schema construction time only.
3627 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003628 if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003629 return(NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003630 return(ret);
3631}
3632
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003633static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003634xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003635{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003636 if (*list == NULL) {
3637 *list = xmlSchemaItemListCreate();
3638 if (*list == NULL)
3639 return(-1);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003640 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003641 xmlSchemaItemListAddSize(*list, initialSize, item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003642 return(0);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003643}
3644
3645/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00003646 * xmlSchemaFreeAnnot:
3647 * @annot: a schema type structure
3648 *
3649 * Deallocate a annotation structure
3650 */
3651static void
3652xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3653{
3654 if (annot == NULL)
3655 return;
Kasimier T. Buchcik004b5462005-08-08 12:43:09 +00003656 if (annot->next == NULL) {
3657 xmlFree(annot);
3658 } else {
3659 xmlSchemaAnnotPtr prev;
3660
3661 do {
3662 prev = annot;
3663 annot = annot->next;
3664 xmlFree(prev);
3665 } while (annot != NULL);
3666 }
Daniel Veillardfdc91562002-07-01 21:52:03 +00003667}
3668
3669/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003670 * xmlSchemaFreeNotation:
3671 * @schema: a schema notation structure
3672 *
3673 * Deallocate a Schema Notation structure.
3674 */
3675static void
3676xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3677{
3678 if (nota == NULL)
3679 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003680 xmlFree(nota);
3681}
3682
3683/**
3684 * xmlSchemaFreeAttribute:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003685 * @attr: an attribute declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00003686 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003687 * Deallocates an attribute declaration structure.
Daniel Veillard4255d502002-04-16 15:50:10 +00003688 */
3689static void
3690xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3691{
3692 if (attr == NULL)
3693 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003694 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003695 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003696 if (attr->defVal != NULL)
3697 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003698 xmlFree(attr);
3699}
3700
3701/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003702 * xmlSchemaFreeAttributeUse:
3703 * @use: an attribute use
3704 *
3705 * Deallocates an attribute use structure.
3706 */
3707static void
3708xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3709{
3710 if (use == NULL)
3711 return;
3712 if (use->annot != NULL)
3713 xmlSchemaFreeAnnot(use->annot);
3714 if (use->defVal != NULL)
3715 xmlSchemaFreeValue(use->defVal);
3716 xmlFree(use);
3717}
3718
3719/**
3720 * xmlSchemaFreeAttributeUseProhib:
3721 * @prohib: an attribute use prohibition
3722 *
3723 * Deallocates an attribute use structure.
3724 */
3725static void
3726xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3727{
3728 if (prohib == NULL)
3729 return;
3730 xmlFree(prohib);
3731}
3732
3733/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003734 * xmlSchemaFreeWildcardNsSet:
3735 * set: a schema wildcard namespace
3736 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003737 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00003738 */
3739static void
3740xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3741{
3742 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003743
Daniel Veillard3646d642004-06-02 19:19:14 +00003744 while (set != NULL) {
3745 next = set->next;
3746 xmlFree(set);
3747 set = next;
3748 }
3749}
3750
3751/**
3752 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003753 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00003754 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003755 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00003756 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003757void
Daniel Veillard3646d642004-06-02 19:19:14 +00003758xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3759{
3760 if (wildcard == NULL)
3761 return;
3762 if (wildcard->annot != NULL)
3763 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003764 if (wildcard->nsSet != NULL)
3765 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3766 if (wildcard->negNsSet != NULL)
3767 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00003768 xmlFree(wildcard);
3769}
3770
3771/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003772 * xmlSchemaFreeAttributeGroup:
3773 * @schema: a schema attribute group structure
3774 *
3775 * Deallocate a Schema Attribute Group structure.
3776 */
3777static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003778xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
Daniel Veillard4255d502002-04-16 15:50:10 +00003779{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003780 if (attrGr == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00003781 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003782 if (attrGr->annot != NULL)
3783 xmlSchemaFreeAnnot(attrGr->annot);
3784 if (attrGr->attrUses != NULL)
3785 xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3786 xmlFree(attrGr);
Daniel Veillard3646d642004-06-02 19:19:14 +00003787}
3788
3789/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003790 * xmlSchemaFreeQNameRef:
3791 * @item: a QName reference structure
3792 *
3793 * Deallocatea a QName reference structure.
3794 */
3795static void
3796xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3797{
3798 xmlFree(item);
3799}
3800
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003801/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003802 * xmlSchemaFreeTypeLinkList:
3803 * @alink: a type link
3804 *
3805 * Deallocate a list of types.
3806 */
3807static void
3808xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3809{
3810 xmlSchemaTypeLinkPtr next;
3811
3812 while (link != NULL) {
3813 next = link->next;
3814 xmlFree(link);
3815 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003816 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003817}
3818
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003819static void
3820xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3821{
3822 xmlSchemaIDCStateObjPtr next;
3823 while (sto != NULL) {
3824 next = sto->next;
3825 if (sto->history != NULL)
3826 xmlFree(sto->history);
3827 if (sto->xpathCtxt != NULL)
3828 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3829 xmlFree(sto);
3830 sto = next;
3831 }
3832}
3833
3834/**
3835 * xmlSchemaFreeIDC:
3836 * @idc: a identity-constraint definition
3837 *
3838 * Deallocates an identity-constraint definition.
3839 */
3840static void
3841xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3842{
3843 xmlSchemaIDCSelectPtr cur, prev;
3844
3845 if (idcDef == NULL)
3846 return;
3847 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003848 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003849 /* Selector */
3850 if (idcDef->selector != NULL) {
3851 if (idcDef->selector->xpathComp != NULL)
3852 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3853 xmlFree(idcDef->selector);
3854 }
3855 /* Fields */
3856 if (idcDef->fields != NULL) {
3857 cur = idcDef->fields;
3858 do {
3859 prev = cur;
3860 cur = cur->next;
3861 if (prev->xpathComp != NULL)
3862 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003863 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003864 } while (cur != NULL);
3865 }
3866 xmlFree(idcDef);
3867}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003868
Daniel Veillard01fa6152004-06-29 17:04:39 +00003869/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003870 * xmlSchemaFreeElement:
3871 * @schema: a schema element structure
3872 *
3873 * Deallocate a Schema Element structure.
3874 */
3875static void
3876xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3877{
3878 if (elem == NULL)
3879 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003880 if (elem->annot != NULL)
3881 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003882 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003883 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003884 if (elem->defVal != NULL)
3885 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003886 xmlFree(elem);
3887}
3888
3889/**
3890 * xmlSchemaFreeFacet:
3891 * @facet: a schema facet structure
3892 *
3893 * Deallocate a Schema Facet structure.
3894 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003895void
Daniel Veillard4255d502002-04-16 15:50:10 +00003896xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3897{
3898 if (facet == NULL)
3899 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003900 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003901 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003902 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003903 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003904 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003905 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003906 xmlFree(facet);
3907}
3908
3909/**
3910 * xmlSchemaFreeType:
3911 * @type: a schema type structure
3912 *
3913 * Deallocate a Schema Type structure.
3914 */
3915void
3916xmlSchemaFreeType(xmlSchemaTypePtr type)
3917{
3918 if (type == NULL)
3919 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003920 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003921 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003922 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003923 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003924
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003925 facet = type->facets;
3926 while (facet != NULL) {
3927 next = facet->next;
3928 xmlSchemaFreeFacet(facet);
3929 facet = next;
3930 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003931 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003932 if (type->attrUses != NULL)
3933 xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003934 if (type->memberTypes != NULL)
3935 xmlSchemaFreeTypeLinkList(type->memberTypes);
3936 if (type->facetSet != NULL) {
3937 xmlSchemaFacetLinkPtr next, link;
3938
3939 link = type->facetSet;
3940 do {
3941 next = link->next;
3942 xmlFree(link);
3943 link = next;
3944 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003945 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003946 if (type->contModel != NULL)
3947 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003948 xmlFree(type);
3949}
3950
3951/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003952 * xmlSchemaFreeModelGroupDef:
3953 * @item: a schema model group definition
3954 *
3955 * Deallocates a schema model group definition.
3956 */
3957static void
3958xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3959{
3960 if (item->annot != NULL)
3961 xmlSchemaFreeAnnot(item->annot);
3962 xmlFree(item);
3963}
3964
3965/**
3966 * xmlSchemaFreeModelGroup:
3967 * @item: a schema model group
3968 *
3969 * Deallocates a schema model group structure.
3970 */
3971static void
3972xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3973{
3974 if (item->annot != NULL)
3975 xmlSchemaFreeAnnot(item->annot);
3976 xmlFree(item);
3977}
3978
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003979static void
3980xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
3981{
3982 if ((list == NULL) || (list->nbItems == 0))
3983 return;
3984 {
3985 xmlSchemaTreeItemPtr item;
3986 xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
3987 int i;
3988
3989 for (i = 0; i < list->nbItems; i++) {
3990 item = items[i];
3991 if (item == NULL)
3992 continue;
3993 switch (item->type) {
3994 case XML_SCHEMA_TYPE_SIMPLE:
3995 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003996 xmlSchemaFreeType((xmlSchemaTypePtr) item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003997 break;
3998 case XML_SCHEMA_TYPE_ATTRIBUTE:
3999 xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004000 break;
4001 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4002 xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4003 break;
4004 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4005 xmlSchemaFreeAttributeUseProhib(
4006 (xmlSchemaAttributeUseProhibPtr) item);
4007 break;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004008 case XML_SCHEMA_TYPE_ELEMENT:
4009 xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4010 break;
4011 case XML_SCHEMA_TYPE_PARTICLE:
4012 if (item->annot != NULL)
4013 xmlSchemaFreeAnnot(item->annot);
4014 xmlFree(item);
4015 break;
4016 case XML_SCHEMA_TYPE_SEQUENCE:
4017 case XML_SCHEMA_TYPE_CHOICE:
4018 case XML_SCHEMA_TYPE_ALL:
4019 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4020 break;
4021 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4022 xmlSchemaFreeAttributeGroup(
4023 (xmlSchemaAttributeGroupPtr) item);
4024 break;
4025 case XML_SCHEMA_TYPE_GROUP:
4026 xmlSchemaFreeModelGroupDef(
4027 (xmlSchemaModelGroupDefPtr) item);
4028 break;
4029 case XML_SCHEMA_TYPE_ANY:
4030 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4031 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4032 break;
4033 case XML_SCHEMA_TYPE_IDC_KEY:
4034 case XML_SCHEMA_TYPE_IDC_UNIQUE:
4035 case XML_SCHEMA_TYPE_IDC_KEYREF:
4036 xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4037 break;
4038 case XML_SCHEMA_TYPE_NOTATION:
4039 xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4040 break;
4041 case XML_SCHEMA_EXTRA_QNAMEREF:
4042 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4043 break;
4044 default: {
4045 /* TODO: This should never be hit. */
4046 xmlSchemaPSimpleInternalErr(NULL,
4047 "Internal error: xmlSchemaComponentListFree, "
4048 "unexpected component type '%s'\n",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004049 (const xmlChar *) WXS_ITEM_TYPE_NAME(item));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004050 }
4051 break;
4052 }
4053 }
4054 list->nbItems = 0;
4055 }
4056}
4057
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004058/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004059 * xmlSchemaFree:
4060 * @schema: a schema structure
4061 *
4062 * Deallocate a Schema structure.
4063 */
4064void
4065xmlSchemaFree(xmlSchemaPtr schema)
4066{
4067 if (schema == NULL)
4068 return;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004069 /* @volatiles is not used anymore :-/ */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004070 if (schema->volatiles != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004071 TODO
4072 /*
4073 * Note that those slots are not responsible for freeing
4074 * schema components anymore; this will now be done by
4075 * the schema buckets.
4076 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004077 if (schema->notaDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004078 xmlHashFree(schema->notaDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004079 if (schema->attrDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004080 xmlHashFree(schema->attrDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004081 if (schema->attrgrpDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004082 xmlHashFree(schema->attrgrpDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004083 if (schema->elemDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004084 xmlHashFree(schema->elemDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004085 if (schema->typeDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004086 xmlHashFree(schema->typeDecl, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004087 if (schema->groupDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004088 xmlHashFree(schema->groupDecl, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004089 if (schema->idcDef != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004090 xmlHashFree(schema->idcDef, NULL);
4091
Daniel Veillard1d913862003-11-21 00:28:39 +00004092 if (schema->schemasImports != NULL)
4093 xmlHashFree(schema->schemasImports,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004094 (xmlHashDeallocator) xmlSchemaBucketFree);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004095 if (schema->includes != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004096 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4097 int i;
4098 for (i = 0; i < list->nbItems; i++) {
4099 xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4100 }
4101 xmlSchemaItemListFree(list);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004102 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004103 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004104 xmlSchemaFreeAnnot(schema->annot);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004105 /* Never free the doc here, since this will be done by the buckets. */
4106
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004107 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004108 xmlFree(schema);
4109}
4110
4111/************************************************************************
4112 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00004113 * Debug functions *
4114 * *
4115 ************************************************************************/
4116
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00004117#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004118
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004119static void
4120xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4121
Daniel Veillard4255d502002-04-16 15:50:10 +00004122/**
4123 * xmlSchemaElementDump:
4124 * @elem: an element
4125 * @output: the file output
4126 *
4127 * Dump the element
4128 */
4129static void
4130xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004131 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004132 const xmlChar * namespace ATTRIBUTE_UNUSED,
4133 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00004134{
4135 if (elem == NULL)
4136 return;
4137
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004138
4139 fprintf(output, "Element");
4140 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4141 fprintf(output, " (global)");
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004142 fprintf(output, ": '%s' ", elem->name);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004143 if (namespace != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004144 fprintf(output, "ns '%s'", namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004145 fprintf(output, "\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004146#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004147 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004148 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004149 if (elem->maxOccurs >= UNBOUNDED)
4150 fprintf(output, "max: unbounded\n");
4151 else if (elem->maxOccurs != 1)
4152 fprintf(output, "max: %d\n", elem->maxOccurs);
4153 else
4154 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00004155 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004156#endif
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004157 /*
4158 * Misc other properties.
4159 */
4160 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4161 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4162 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004163 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004164 fprintf(output, " props: ");
4165 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4166 fprintf(output, "[fixed] ");
4167 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4168 fprintf(output, "[default] ");
4169 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4170 fprintf(output, "[abstract] ");
4171 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4172 fprintf(output, "[nillable] ");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004173 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00004174 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004175 /*
4176 * Default/fixed value.
4177 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004178 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004179 fprintf(output, " value: '%s'\n", elem->value);
4180 /*
4181 * Type.
4182 */
4183 if (elem->namedType != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004184 fprintf(output, " type: '%s' ", elem->namedType);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004185 if (elem->namedTypeNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004186 fprintf(output, "ns '%s'\n", elem->namedTypeNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004187 else
4188 fprintf(output, "\n");
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004189 } else if (elem->subtypes != NULL) {
4190 /*
4191 * Dump local types.
4192 */
4193 xmlSchemaTypeDump(elem->subtypes, output);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004194 }
4195 /*
4196 * Substitution group.
4197 */
4198 if (elem->substGroup != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004199 fprintf(output, " substitutionGroup: '%s' ", elem->substGroup);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004200 if (elem->substGroupNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004201 fprintf(output, "ns '%s'\n", elem->substGroupNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004202 else
4203 fprintf(output, "\n");
4204 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004205}
4206
4207/**
4208 * xmlSchemaAnnotDump:
4209 * @output: the file output
4210 * @annot: a annotation
4211 *
4212 * Dump the annotation
4213 */
4214static void
4215xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4216{
4217 xmlChar *content;
4218
4219 if (annot == NULL)
4220 return;
4221
4222 content = xmlNodeGetContent(annot->content);
4223 if (content != NULL) {
4224 fprintf(output, " Annot: %s\n", content);
4225 xmlFree(content);
4226 } else
4227 fprintf(output, " Annot: empty\n");
4228}
4229
4230/**
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004231 * xmlSchemaContentModelDump:
4232 * @particle: the schema particle
4233 * @output: the file output
4234 * @depth: the depth used for intentation
Daniel Veillard4255d502002-04-16 15:50:10 +00004235 *
4236 * Dump a SchemaType structure
4237 */
4238static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004239xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4240{
4241 xmlChar *str = NULL;
4242 xmlSchemaTreeItemPtr term;
4243 char shift[100];
4244 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004245
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004246 if (particle == NULL)
4247 return;
4248 for (i = 0;((i < depth) && (i < 25));i++)
4249 shift[2 * i] = shift[2 * i + 1] = ' ';
4250 shift[2 * i] = shift[2 * i + 1] = 0;
4251 fprintf(output, shift);
4252 if (particle->children == NULL) {
4253 fprintf(output, "MISSING particle term\n");
4254 return;
4255 }
4256 term = particle->children;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004257 if (term == NULL) {
4258 fprintf(output, "(NULL)");
4259 } else {
4260 switch (term->type) {
4261 case XML_SCHEMA_TYPE_ELEMENT:
4262 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4263 ((xmlSchemaElementPtr)term)->targetNamespace,
4264 ((xmlSchemaElementPtr)term)->name));
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004265 FREE_AND_NULL(str);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004266 break;
4267 case XML_SCHEMA_TYPE_SEQUENCE:
4268 fprintf(output, "SEQUENCE");
4269 break;
4270 case XML_SCHEMA_TYPE_CHOICE:
4271 fprintf(output, "CHOICE");
4272 break;
4273 case XML_SCHEMA_TYPE_ALL:
4274 fprintf(output, "ALL");
4275 break;
4276 case XML_SCHEMA_TYPE_ANY:
4277 fprintf(output, "ANY");
4278 break;
4279 default:
4280 fprintf(output, "UNKNOWN\n");
4281 return;
4282 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004283 }
4284 if (particle->minOccurs != 1)
4285 fprintf(output, " min: %d", particle->minOccurs);
4286 if (particle->maxOccurs >= UNBOUNDED)
4287 fprintf(output, " max: unbounded");
4288 else if (particle->maxOccurs != 1)
4289 fprintf(output, " max: %d", particle->maxOccurs);
4290 fprintf(output, "\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004291 if (term &&
4292 ((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4293 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4294 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4295 (term->children != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004296 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4297 output, depth +1);
4298 }
4299 if (particle->next != NULL)
4300 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4301 output, depth);
4302}
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004303
4304/**
4305 * xmlSchemaAttrUsesDump:
4306 * @uses: attribute uses list
4307 * @output: the file output
4308 *
4309 * Dumps a list of attribute use components.
4310 */
4311static void
4312xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4313{
4314 xmlSchemaAttributeUsePtr use;
4315 xmlSchemaAttributeUseProhibPtr prohib;
4316 xmlSchemaQNameRefPtr ref;
4317 const xmlChar *name, *tns;
4318 xmlChar *str = NULL;
4319 int i;
4320
4321 if ((uses == NULL) || (uses->nbItems == 0))
4322 return;
4323
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004324 fprintf(output, " attributes:\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004325 for (i = 0; i < uses->nbItems; i++) {
4326 use = uses->items[i];
4327 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4328 fprintf(output, " [prohibition] ");
4329 prohib = (xmlSchemaAttributeUseProhibPtr) use;
4330 name = prohib->name;
4331 tns = prohib->targetNamespace;
4332 } else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4333 fprintf(output, " [reference] ");
4334 ref = (xmlSchemaQNameRefPtr) use;
4335 name = ref->name;
4336 tns = ref->targetNamespace;
4337 } else {
4338 fprintf(output, " [use] ");
4339 name = WXS_ATTRUSE_DECL_NAME(use);
4340 tns = WXS_ATTRUSE_DECL_TNS(use);
4341 }
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004342 fprintf(output, "'%s'\n",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004343 (const char *) xmlSchemaFormatQName(&str, tns, name));
4344 FREE_AND_NULL(str);
4345 }
4346}
4347
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004348/**
4349 * xmlSchemaTypeDump:
4350 * @output: the file output
4351 * @type: a type structure
4352 *
4353 * Dump a SchemaType structure
4354 */
4355static void
Daniel Veillard4255d502002-04-16 15:50:10 +00004356xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4357{
4358 if (type == NULL) {
4359 fprintf(output, "Type: NULL\n");
4360 return;
4361 }
4362 fprintf(output, "Type: ");
4363 if (type->name != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004364 fprintf(output, "'%s' ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004365 else
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004366 fprintf(output, "(no name) ");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004367 if (type->targetNamespace != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004368 fprintf(output, "ns '%s' ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004369 switch (type->type) {
4370 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004371 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004372 break;
4373 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004374 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004375 break;
4376 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004377 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004378 break;
4379 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004380 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004381 break;
4382 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004383 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004384 break;
4385 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004386 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004387 break;
4388 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004389 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004390 break;
4391 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004392 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004393 break;
4394 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004395 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004396 break;
4397 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004398 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00004399 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004400 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004401 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004402 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004403 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004404 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004405 break;
4406 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004407 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004408 break;
4409 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004410 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004411 break;
4412 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004413 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004414 break;
4415 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004416 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004417 break;
4418 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004419 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004420 break;
4421 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004422 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004423 break;
4424 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004425 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004426 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00004427 }
4428 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004429 if (type->base != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004430 fprintf(output, " base type: '%s'", type->base);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004431 if (type->baseNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004432 fprintf(output, " ns '%s'\n", type->baseNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004433 else
4434 fprintf(output, "\n");
4435 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004436 if (type->attrUses != NULL)
4437 xmlSchemaAttrUsesDump(type->attrUses, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00004438 if (type->annot != NULL)
4439 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004440#ifdef DUMP_CONTENT_MODEL
4441 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4442 (type->subtypes != NULL)) {
4443 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4444 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004445 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004446#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004447}
4448
4449/**
4450 * xmlSchemaDump:
4451 * @output: the file output
4452 * @schema: a schema structure
4453 *
4454 * Dump a Schema structure.
4455 */
4456void
4457xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4458{
Daniel Veillardce682bc2004-11-05 17:22:25 +00004459 if (output == NULL)
4460 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004461 if (schema == NULL) {
4462 fprintf(output, "Schemas: NULL\n");
4463 return;
4464 }
4465 fprintf(output, "Schemas: ");
4466 if (schema->name != NULL)
4467 fprintf(output, "%s, ", schema->name);
4468 else
4469 fprintf(output, "no name, ");
4470 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00004471 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004472 else
4473 fprintf(output, "no target namespace");
4474 fprintf(output, "\n");
4475 if (schema->annot != NULL)
4476 xmlSchemaAnnotDump(output, schema->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00004477 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
4478 output);
4479 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004480 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00004481}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004482
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004483#ifdef DEBUG_IDC_NODE_TABLE
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004484/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004485 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004486 * @vctxt: the WXS validation context
4487 *
4488 * Displays the current IDC table for debug purposes.
4489 */
4490static void
4491xmlSchemaDebugDumpIDCTable(FILE * output,
4492 const xmlChar *namespaceName,
4493 const xmlChar *localName,
4494 xmlSchemaPSVIIDCBindingPtr bind)
4495{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004496 xmlChar *str = NULL;
4497 const xmlChar *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004498 xmlSchemaPSVIIDCNodePtr tab;
4499 xmlSchemaPSVIIDCKeyPtr key;
4500 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004501
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004502 fprintf(output, "IDC: TABLES on '%s'\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004503 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004504 FREE_AND_NULL(str)
4505
4506 if (bind == NULL)
4507 return;
4508 do {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004509 fprintf(output, "IDC: BINDING '%s' (%d)\n",
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004510 xmlSchemaGetComponentQName(&str,
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004511 bind->definition), bind->nbNodes);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004512 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004513 for (i = 0; i < bind->nbNodes; i++) {
4514 tab = bind->nodeTable[i];
4515 fprintf(output, " ( ");
4516 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004517 key = tab->keys[j];
4518 if ((key != NULL) && (key->val != NULL)) {
4519 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004520 if (res >= 0)
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004521 fprintf(output, "'%s' ", value);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004522 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004523 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004524 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004525 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004526 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004527 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004528 else
4529 fprintf(output, "(key missing), ");
4530 }
4531 fprintf(output, ")\n");
4532 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004533 if (bind->dupls && bind->dupls->nbItems) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004534 fprintf(output, "IDC: dupls (%d):\n", bind->dupls->nbItems);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004535 for (i = 0; i < bind->dupls->nbItems; i++) {
4536 tab = bind->dupls->items[i];
4537 fprintf(output, " ( ");
4538 for (j = 0; j < bind->definition->nbFields; j++) {
4539 key = tab->keys[j];
4540 if ((key != NULL) && (key->val != NULL)) {
4541 res = xmlSchemaGetCanonValue(key->val, &value);
4542 if (res >= 0)
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004543 fprintf(output, "'%s' ", value);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004544 else
4545 fprintf(output, "CANON-VALUE-FAILED ");
4546 if (res == 0)
4547 FREE_AND_NULL(value)
4548 } else if (key != NULL)
4549 fprintf(output, "(no val), ");
4550 else
4551 fprintf(output, "(key missing), ");
4552 }
4553 fprintf(output, ")\n");
4554 }
4555 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004556 bind = bind->next;
4557 } while (bind != NULL);
4558}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00004559#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00004560#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00004561
4562/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004563 * *
4564 * Utilities *
4565 * *
4566 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004567
Daniel Veillardc0826a72004-08-10 14:17:33 +00004568/**
4569 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004570 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00004571 * @name: the name of the attribute
4572 *
4573 * Seeks an attribute with a name of @name in
4574 * no namespace.
4575 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004576 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00004577 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004578static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004579xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00004580{
4581 xmlAttrPtr prop;
4582
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004583 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004584 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004585 prop = node->properties;
4586 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004587 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004588 return(prop);
4589 prop = prop->next;
4590 }
4591 return (NULL);
4592}
4593
4594/**
4595 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004596 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00004597 * @uri: the uri
4598 * @name: the name of the attribute
4599 *
4600 * Seeks an attribute with a local name of @name and
4601 * a namespace URI of @uri.
4602 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004603 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00004604 */
4605static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004606xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00004607{
4608 xmlAttrPtr prop;
4609
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004610 if ((node == NULL) || (name == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004611 return(NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004612 prop = node->properties;
4613 while (prop != NULL) {
4614 if ((prop->ns != NULL) &&
4615 xmlStrEqual(prop->name, BAD_CAST name) &&
4616 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00004617 return(prop);
4618 prop = prop->next;
4619 }
4620 return (NULL);
4621}
4622
4623static const xmlChar *
4624xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4625{
4626 xmlChar *val;
4627 const xmlChar *ret;
4628
4629 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004630 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00004631 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00004632 ret = xmlDictLookup(ctxt->dict, val, -1);
4633 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004634 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004635}
4636
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004637static const xmlChar *
4638xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4639{
4640 return((const xmlChar*) xmlNodeGetContent(node));
4641}
4642
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004643/**
4644 * xmlSchemaGetProp:
4645 * @ctxt: the parser context
4646 * @node: the node
4647 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004648 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004649 * Read a attribute value and internalize the string
4650 *
4651 * Returns the string or NULL if not present.
4652 */
4653static const xmlChar *
4654xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4655 const char *name)
4656{
4657 xmlChar *val;
4658 const xmlChar *ret;
4659
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004660 val = xmlGetNoNsProp(node, BAD_CAST name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004661 if (val == NULL)
4662 return(NULL);
4663 ret = xmlDictLookup(ctxt->dict, val, -1);
4664 xmlFree(val);
4665 return(ret);
4666}
4667
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004668/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00004669 * *
4670 * Parsing functions *
4671 * *
4672 ************************************************************************/
4673
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004674#define WXS_FIND_GLOBAL_ITEM(slot) \
4675 if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4676 ret = xmlHashLookup(schema->slot, name); \
4677 if (ret != NULL) goto exit; \
4678 } \
4679 if (xmlHashSize(schema->schemasImports) > 1) { \
4680 xmlSchemaImportPtr import; \
4681 if (nsName == NULL) \
4682 import = xmlHashLookup(schema->schemasImports, \
4683 XML_SCHEMAS_NO_NAMESPACE); \
4684 else \
4685 import = xmlHashLookup(schema->schemasImports, nsName); \
4686 if (import == NULL) \
4687 goto exit; \
4688 ret = xmlHashLookup(import->schema->slot, name); \
4689 }
4690
Daniel Veillard4255d502002-04-16 15:50:10 +00004691/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004692 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004693 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004694 * @name: the element name
4695 * @ns: the element namespace
4696 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004697 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004698 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004699 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004700 */
4701static xmlSchemaElementPtr
4702xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004703 const xmlChar * nsName)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004704{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004705 xmlSchemaElementPtr ret = NULL;
4706
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004707 if ((name == NULL) || (schema == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004708 return(NULL);
4709 if (schema != NULL) {
4710 WXS_FIND_GLOBAL_ITEM(elemDecl)
4711 }
4712exit:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004713#ifdef DEBUG
4714 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004715 if (nsName == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004716 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004717 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004718 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004719 nsName);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004720 }
4721#endif
4722 return (ret);
4723}
4724
4725/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004726 * xmlSchemaGetType:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004727 * @schema: the main schema
4728 * @name: the type's name
4729 * nsName: the type's namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004730 *
4731 * Lookup a type in the schemas or the predefined types
4732 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004733 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00004734 */
4735static xmlSchemaTypePtr
4736xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004737 const xmlChar * nsName)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004738{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004739 xmlSchemaTypePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004740
4741 if (name == NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004742 return (NULL);
4743 /* First try the built-in types. */
4744 if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4745 ret = xmlSchemaGetPredefinedType(name, nsName);
4746 if (ret != NULL)
4747 goto exit;
4748 /*
4749 * Note that we try the parsed schemas as well here
4750 * since one might have parsed the S4S, which contain more
4751 * than the built-in types.
4752 * TODO: Can we optimize this?
4753 */
4754 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004755 if (schema != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004756 WXS_FIND_GLOBAL_ITEM(typeDecl)
4757 }
4758exit:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004759
Daniel Veillard4255d502002-04-16 15:50:10 +00004760#ifdef DEBUG
4761 if (ret == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004762 if (nsName == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004763 fprintf(stderr, "Unable to lookup type %s", name);
4764 else
4765 fprintf(stderr, "Unable to lookup type %s:%s", name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004766 nsName);
Daniel Veillard4255d502002-04-16 15:50:10 +00004767 }
4768#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004769 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004770}
4771
Daniel Veillard3646d642004-06-02 19:19:14 +00004772/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004773 * xmlSchemaGetAttributeDecl:
4774 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004775 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004776 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004777 *
4778 * Lookup a an attribute in the schema or imported schemas
4779 *
4780 * Returns the attribute declaration or NULL if not found.
4781 */
4782static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004783xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004784 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004785{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004786 xmlSchemaAttributePtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004787
4788 if ((name == NULL) || (schema == NULL))
4789 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004790 if (schema != NULL) {
4791 WXS_FIND_GLOBAL_ITEM(attrDecl)
Daniel Veillard3646d642004-06-02 19:19:14 +00004792 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004793exit:
Daniel Veillard3646d642004-06-02 19:19:14 +00004794#ifdef DEBUG
4795 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004796 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004797 fprintf(stderr, "Unable to lookup attribute %s", name);
4798 else
4799 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004800 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004801 }
4802#endif
4803 return (ret);
4804}
4805
4806/**
4807 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004808 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004809 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004810 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004811 *
4812 * Lookup a an attribute group in the schema or imported schemas
4813 *
4814 * Returns the attribute group definition or NULL if not found.
4815 */
4816static xmlSchemaAttributeGroupPtr
4817xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004818 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004819{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004820 xmlSchemaAttributeGroupPtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004821
4822 if ((name == NULL) || (schema == NULL))
4823 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004824 if (schema != NULL) {
4825 WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4826 }
4827exit:
4828 /* TODO:
4829 if ((ret != NULL) && (ret->redef != NULL)) {
4830 * Return the last redefinition. *
4831 ret = ret->redef;
Daniel Veillard3646d642004-06-02 19:19:14 +00004832 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004833 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004834#ifdef DEBUG
4835 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004836 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004837 fprintf(stderr, "Unable to lookup attribute group %s", name);
4838 else
4839 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004840 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004841 }
4842#endif
4843 return (ret);
4844}
4845
4846/**
4847 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004848 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004849 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004850 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004851 *
4852 * Lookup a group in the schema or imported schemas
4853 *
4854 * Returns the group definition or NULL if not found.
4855 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004856static xmlSchemaModelGroupDefPtr
Daniel Veillard3646d642004-06-02 19:19:14 +00004857xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004858 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004859{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004860 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004861
4862 if ((name == NULL) || (schema == NULL))
4863 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004864 if (schema != NULL) {
4865 WXS_FIND_GLOBAL_ITEM(groupDecl)
Daniel Veillard3646d642004-06-02 19:19:14 +00004866 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004867exit:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004868
Daniel Veillard3646d642004-06-02 19:19:14 +00004869#ifdef DEBUG
4870 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004871 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004872 fprintf(stderr, "Unable to lookup group %s", name);
4873 else
4874 fprintf(stderr, "Unable to lookup group %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004875 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004876 }
4877#endif
4878 return (ret);
4879}
4880
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004881static xmlSchemaNotationPtr
4882xmlSchemaGetNotation(xmlSchemaPtr schema,
4883 const xmlChar *name,
4884 const xmlChar *nsName)
4885{
4886 xmlSchemaNotationPtr ret = NULL;
4887
4888 if ((name == NULL) || (schema == NULL))
4889 return (NULL);
4890 if (schema != NULL) {
4891 WXS_FIND_GLOBAL_ITEM(notaDecl)
4892 }
4893exit:
4894 return (ret);
4895}
4896
4897static xmlSchemaIDCPtr
4898xmlSchemaGetIDC(xmlSchemaPtr schema,
4899 const xmlChar *name,
4900 const xmlChar *nsName)
4901{
4902 xmlSchemaIDCPtr ret = NULL;
4903
4904 if ((name == NULL) || (schema == NULL))
4905 return (NULL);
4906 if (schema != NULL) {
4907 WXS_FIND_GLOBAL_ITEM(idcDef)
4908 }
4909exit:
4910 return (ret);
4911}
4912
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004913/**
4914 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004915 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004916 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004917 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004918 *
4919 * Lookup a group in the schema or imported schemas
4920 *
4921 * Returns the group definition or NULL if not found.
4922 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004923static xmlSchemaBasicItemPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004924xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4925 xmlSchemaTypeType itemType,
4926 const xmlChar *name,
4927 const xmlChar *targetNs)
4928{
4929 switch (itemType) {
4930 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004931 return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004932 name, targetNs));
4933 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004934 return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004935 name, targetNs));
4936 default:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004937 TODO
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004938 return (NULL);
4939 }
4940}
4941
Daniel Veillard4255d502002-04-16 15:50:10 +00004942/************************************************************************
4943 * *
4944 * Parsing functions *
4945 * *
4946 ************************************************************************/
4947
4948#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004949 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00004950
4951/**
4952 * xmlSchemaIsBlank:
4953 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004954 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00004955 *
4956 * Check if a string is ignorable
4957 *
4958 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4959 */
4960static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004961xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004962{
Daniel Veillard4255d502002-04-16 15:50:10 +00004963 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004964 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004965 if (len < 0) {
4966 while (*str != 0) {
4967 if (!(IS_BLANK_CH(*str)))
4968 return (0);
4969 str++;
4970 }
4971 } else while ((*str != 0) && (len != 0)) {
4972 if (!(IS_BLANK_CH(*str)))
4973 return (0);
4974 str++;
4975 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00004976 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004977
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004978 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004979}
4980
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004981#define WXS_COMP_NAME(c, t) ((t) (c))->name
4982#define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
4983/*
4984* xmlSchemaFindRedefCompInGraph:
4985* ATTENTION TODO: This uses pointer comp. for strings.
4986*/
4987static xmlSchemaBasicItemPtr
4988xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
4989 xmlSchemaTypeType type,
4990 const xmlChar *name,
4991 const xmlChar *nsName)
4992{
4993 xmlSchemaBasicItemPtr ret;
4994 int i;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004995
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004996 if ((bucket == NULL) || (name == NULL))
4997 return(NULL);
4998 if ((bucket->globals == NULL) ||
4999 (bucket->globals->nbItems == 0))
5000 goto subschemas;
5001 /*
5002 * Search in global components.
5003 */
5004 for (i = 0; i < bucket->globals->nbItems; i++) {
5005 ret = bucket->globals->items[i];
5006 if (ret->type == type) {
5007 switch (type) {
5008 case XML_SCHEMA_TYPE_COMPLEX:
5009 case XML_SCHEMA_TYPE_SIMPLE:
5010 if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5011 (WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5012 nsName))
5013 {
5014 return(ret);
5015 }
5016 break;
5017 case XML_SCHEMA_TYPE_GROUP:
5018 if ((WXS_COMP_NAME(ret,
5019 xmlSchemaModelGroupDefPtr) == name) &&
5020 (WXS_COMP_TNS(ret,
5021 xmlSchemaModelGroupDefPtr) == nsName))
5022 {
5023 return(ret);
5024 }
5025 break;
5026 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5027 if ((WXS_COMP_NAME(ret,
5028 xmlSchemaAttributeGroupPtr) == name) &&
5029 (WXS_COMP_TNS(ret,
5030 xmlSchemaAttributeGroupPtr) == nsName))
5031 {
5032 return(ret);
5033 }
Kasimier T. Buchcik5d2998b2005-11-22 17:36:01 +00005034 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005035 default:
5036 /* Should not be hit. */
5037 return(NULL);
5038 }
5039 }
5040 }
5041subschemas:
5042 /*
5043 * Process imported/included schemas.
5044 */
5045 if (bucket->relations != NULL) {
5046 xmlSchemaSchemaRelationPtr rel = bucket->relations;
5047
5048 /*
5049 * TODO: Marking the bucket will not avoid multiple searches
5050 * in the same schema, but avoids at least circularity.
5051 */
5052 bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5053 do {
5054 if ((rel->bucket != NULL) &&
5055 ((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5056 ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5057 type, name, nsName);
5058 if (ret != NULL)
5059 return(ret);
5060 }
5061 rel = rel->next;
5062 } while (rel != NULL);
5063 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5064 }
5065 return(NULL);
5066}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005067
5068/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005069 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005070 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005071 * @schema: the schema being built
5072 * @name: the item name
5073 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005074 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00005075 * *WARNING* this interface is highly subject to change
5076 *
5077 * Returns the new struture or NULL in case of error
5078 */
5079static xmlSchemaNotationPtr
5080xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005081 const xmlChar *name, const xmlChar *nsName,
5082 xmlNodePtr node ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00005083{
5084 xmlSchemaNotationPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005085
5086 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5087 return (NULL);
5088
Daniel Veillard4255d502002-04-16 15:50:10 +00005089 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5090 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005091 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005092 return (NULL);
5093 }
5094 memset(ret, 0, sizeof(xmlSchemaNotation));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005095 ret->type = XML_SCHEMA_TYPE_NOTATION;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005096 ret->name = name;
5097 ret->targetNamespace = nsName;
5098 /* TODO: do we need the node to be set?
5099 * ret->node = node;*/
5100 WXS_ADD_GLOBAL(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005101 return (ret);
5102}
5103
Daniel Veillard4255d502002-04-16 15:50:10 +00005104/**
5105 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005106 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005107 * @schema: the schema being built
5108 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005109 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005110 *
5111 * Add an XML schema Attrribute declaration
5112 * *WARNING* this interface is highly subject to change
5113 *
5114 * Returns the new struture or NULL in case of error
5115 */
5116static xmlSchemaAttributePtr
5117xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005118 const xmlChar * name, const xmlChar * nsName,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005119 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005120{
5121 xmlSchemaAttributePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005122
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005123 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005124 return (NULL);
5125
5126 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5127 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005128 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005129 return (NULL);
5130 }
5131 memset(ret, 0, sizeof(xmlSchemaAttribute));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005132 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5133 ret->node = node;
5134 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005135 ret->targetNamespace = nsName;
5136
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005137 if (topLevel)
5138 WXS_ADD_GLOBAL(ctxt, ret);
5139 else
5140 WXS_ADD_LOCAL(ctxt, ret);
5141 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005142 return (ret);
5143}
5144
5145/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005146 * xmlSchemaAddAttributeUse:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005147 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005148 * @schema: the schema being built
5149 * @name: the item name
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005150 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005151 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005152 * Add an XML schema Attrribute declaration
5153 * *WARNING* this interface is highly subject to change
5154 *
5155 * Returns the new struture or NULL in case of error
5156 */
5157static xmlSchemaAttributeUsePtr
5158xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5159 xmlNodePtr node)
5160{
5161 xmlSchemaAttributeUsePtr ret = NULL;
5162
5163 if (pctxt == NULL)
5164 return (NULL);
5165
5166 ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5167 if (ret == NULL) {
5168 xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5169 return (NULL);
5170 }
5171 memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5172 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5173 ret->node = node;
5174
5175 WXS_ADD_LOCAL(pctxt, ret);
5176 return (ret);
5177}
5178
5179/*
5180* xmlSchemaAddRedef:
5181*
5182* Adds a redefinition information. This is used at a later stage to:
5183* resolve references to the redefined components and to check constraints.
5184*/
5185static xmlSchemaRedefPtr
5186xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5187 xmlSchemaBucketPtr targetBucket,
5188 void *item,
5189 const xmlChar *refName,
5190 const xmlChar *refTargetNs)
5191{
5192 xmlSchemaRedefPtr ret;
5193
5194 ret = (xmlSchemaRedefPtr)
5195 xmlMalloc(sizeof(xmlSchemaRedef));
5196 if (ret == NULL) {
5197 xmlSchemaPErrMemory(pctxt,
5198 "allocating redefinition info", NULL);
5199 return (NULL);
5200 }
5201 memset(ret, 0, sizeof(xmlSchemaRedef));
5202 ret->item = item;
5203 ret->targetBucket = targetBucket;
5204 ret->refName = refName;
5205 ret->refTargetNs = refTargetNs;
5206 if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5207 WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5208 else
5209 WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5210 WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5211
5212 return (ret);
5213}
5214
5215/**
5216 * xmlSchemaAddAttributeGroupDefinition:
5217 * @ctxt: a schema parser context
5218 * @schema: the schema being built
5219 * @name: the item name
5220 * @nsName: the target namespace
5221 * @node: the corresponding node
5222 *
5223 * Add an XML schema Attrribute Group definition.
Daniel Veillard4255d502002-04-16 15:50:10 +00005224 *
5225 * Returns the new struture or NULL in case of error
5226 */
5227static xmlSchemaAttributeGroupPtr
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005228xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5229 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5230 const xmlChar *name,
5231 const xmlChar *nsName,
5232 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005233{
5234 xmlSchemaAttributeGroupPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005235
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005236 if ((pctxt == NULL) || (name == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005237 return (NULL);
5238
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005239 ret = (xmlSchemaAttributeGroupPtr)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005240 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00005241 if (ret == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005242 xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005243 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005244 }
5245 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005246 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005247 ret->name = name;
5248 ret->targetNamespace = nsName;
5249 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005250
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005251 /* TODO: Remove the flag. */
5252 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5253 if (pctxt->isRedefine) {
5254 pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5255 ret, name, nsName);
5256 if (pctxt->redef == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005257 xmlFree(ret);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005258 return(NULL);
5259 }
5260 pctxt->redefCounter = 0;
5261 }
5262 WXS_ADD_GLOBAL(pctxt, ret);
5263 WXS_ADD_PENDING(pctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005264 return (ret);
5265}
5266
5267/**
5268 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005269 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005270 * @schema: the schema being built
5271 * @name: the type name
5272 * @namespace: the type namespace
5273 *
5274 * Add an XML schema Element declaration
5275 * *WARNING* this interface is highly subject to change
5276 *
5277 * Returns the new struture or NULL in case of error
5278 */
5279static xmlSchemaElementPtr
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005280xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005281 const xmlChar * name, const xmlChar * nsName,
William M. Brack2f2a6632004-08-20 23:09:47 +00005282 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005283{
5284 xmlSchemaElementPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005285
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005286 if ((ctxt == NULL) || (name == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005287 return (NULL);
5288
Daniel Veillard4255d502002-04-16 15:50:10 +00005289 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5290 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005291 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005292 return (NULL);
5293 }
5294 memset(ret, 0, sizeof(xmlSchemaElement));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005295 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5296 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005297 ret->targetNamespace = nsName;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005298 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005299
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005300 if (topLevel)
5301 WXS_ADD_GLOBAL(ctxt, ret);
5302 else
5303 WXS_ADD_LOCAL(ctxt, ret);
5304 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005305 return (ret);
5306}
5307
5308/**
5309 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00005310 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005311 * @schema: the schema being built
5312 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005313 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005314 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005315 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00005316 * *WARNING* this interface is highly subject to change
5317 *
5318 * Returns the new struture or NULL in case of error
5319 */
5320static xmlSchemaTypePtr
5321xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005322 xmlSchemaTypeType type,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00005323 const xmlChar * name, const xmlChar * nsName,
5324 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005325{
5326 xmlSchemaTypePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005327
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005328 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005329 return (NULL);
5330
5331 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5332 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005333 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005334 return (NULL);
5335 }
5336 memset(ret, 0, sizeof(xmlSchemaType));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005337 ret->type = type;
5338 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005339 ret->targetNamespace = nsName;
5340 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005341 if (topLevel) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005342 if (ctxt->isRedefine) {
5343 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5344 ret, name, nsName);
5345 if (ctxt->redef == NULL) {
5346 xmlFree(ret);
5347 return(NULL);
5348 }
5349 ctxt->redefCounter = 0;
5350 }
5351 WXS_ADD_GLOBAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005352 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005353 WXS_ADD_LOCAL(ctxt, ret);
5354 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005355 return (ret);
5356}
5357
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005358static xmlSchemaQNameRefPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005359xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005360 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005361 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005362 const xmlChar *refNs)
5363{
5364 xmlSchemaQNameRefPtr ret;
5365
5366 ret = (xmlSchemaQNameRefPtr)
5367 xmlMalloc(sizeof(xmlSchemaQNameRef));
5368 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005369 xmlSchemaPErrMemory(pctxt,
5370 "allocating QName reference item", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005371 return (NULL);
5372 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005373 ret->node = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005374 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5375 ret->name = refName;
5376 ret->targetNamespace = refNs;
5377 ret->item = NULL;
5378 ret->itemType = refType;
5379 /*
5380 * Store the reference item in the schema.
5381 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005382 WXS_ADD_LOCAL(pctxt, ret);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005383 return (ret);
5384}
5385
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005386static xmlSchemaAttributeUseProhibPtr
5387xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5388{
5389 xmlSchemaAttributeUseProhibPtr ret;
5390
5391 ret = (xmlSchemaAttributeUseProhibPtr)
5392 xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5393 if (ret == NULL) {
5394 xmlSchemaPErrMemory(pctxt,
5395 "allocating attribute use prohibition", NULL);
5396 return (NULL);
5397 }
5398 memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5399 ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5400 WXS_ADD_LOCAL(pctxt, ret);
5401 return (ret);
5402}
5403
5404
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005405/**
5406 * xmlSchemaAddModelGroup:
5407 * @ctxt: a schema parser context
5408 * @schema: the schema being built
5409 * @type: the "compositor" type of the model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005410 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005411 *
5412 * Adds a schema model group
5413 * *WARNING* this interface is highly subject to change
5414 *
5415 * Returns the new struture or NULL in case of error
5416 */
5417static xmlSchemaModelGroupPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005418xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5419 xmlSchemaPtr schema,
5420 xmlSchemaTypeType type,
5421 xmlNodePtr node)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005422{
5423 xmlSchemaModelGroupPtr ret = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005424
5425 if ((ctxt == NULL) || (schema == NULL))
5426 return (NULL);
5427
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005428 ret = (xmlSchemaModelGroupPtr)
5429 xmlMalloc(sizeof(xmlSchemaModelGroup));
5430 if (ret == NULL) {
5431 xmlSchemaPErrMemory(ctxt, "allocating model group component",
5432 NULL);
5433 return (NULL);
5434 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005435 memset(ret, 0, sizeof(xmlSchemaModelGroup));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005436 ret->type = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005437 ret->node = node;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005438 WXS_ADD_LOCAL(ctxt, ret);
5439 if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5440 (type == XML_SCHEMA_TYPE_CHOICE))
5441 WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005442 return (ret);
5443}
5444
5445
5446/**
5447 * xmlSchemaAddParticle:
5448 * @ctxt: a schema parser context
5449 * @schema: the schema being built
5450 * @node: the corresponding node in the schema doc
5451 * @min: the minOccurs
5452 * @max: the maxOccurs
5453 *
5454 * Adds an XML schema particle component.
5455 * *WARNING* this interface is highly subject to change
5456 *
5457 * Returns the new struture or NULL in case of error
5458 */
5459static xmlSchemaParticlePtr
5460xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5461 xmlNodePtr node, int min, int max)
5462{
5463 xmlSchemaParticlePtr ret = NULL;
5464 if ((ctxt == NULL) || (schema == NULL))
5465 return (NULL);
5466
5467#ifdef DEBUG
5468 fprintf(stderr, "Adding particle component\n");
5469#endif
5470 ret = (xmlSchemaParticlePtr)
5471 xmlMalloc(sizeof(xmlSchemaParticle));
5472 if (ret == NULL) {
5473 xmlSchemaPErrMemory(ctxt, "allocating particle component",
5474 NULL);
5475 return (NULL);
5476 }
5477 ret->type = XML_SCHEMA_TYPE_PARTICLE;
5478 ret->annot = NULL;
5479 ret->node = node;
5480 ret->minOccurs = min;
5481 ret->maxOccurs = max;
5482 ret->next = NULL;
5483 ret->children = NULL;
5484
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005485 WXS_ADD_LOCAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005486 /*
5487 * Note that addition to pending components will be done locally
5488 * to the specific parsing function, since the most particles
5489 * need not to be fixed up (i.e. the reference to be resolved).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005490 * REMOVED: WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005491 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005492 return (ret);
5493}
5494
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005495/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005496 * xmlSchemaAddModelGroupDefinition:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005497 * @ctxt: a schema validation context
5498 * @schema: the schema being built
5499 * @name: the group name
5500 *
5501 * Add an XML schema Group definition
5502 *
5503 * Returns the new struture or NULL in case of error
5504 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005505static xmlSchemaModelGroupDefPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005506xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5507 xmlSchemaPtr schema,
5508 const xmlChar *name,
5509 const xmlChar *nsName,
5510 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005511{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005512 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005513
5514 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5515 return (NULL);
5516
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005517 ret = (xmlSchemaModelGroupDefPtr)
5518 xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005519 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005520 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005521 return (NULL);
5522 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005523 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005524 ret->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005525 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005526 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005527 ret->targetNamespace = nsName;
5528
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005529 if (ctxt->isRedefine) {
5530 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5531 ret, name, nsName);
5532 if (ctxt->redef == NULL) {
5533 xmlFree(ret);
5534 return(NULL);
5535 }
5536 ctxt->redefCounter = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005537 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005538 WXS_ADD_GLOBAL(ctxt, ret);
5539 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005540 return (ret);
5541}
5542
Daniel Veillard3646d642004-06-02 19:19:14 +00005543/**
5544 * xmlSchemaNewWildcardNs:
5545 * @ctxt: a schema validation context
5546 *
5547 * Creates a new wildcard namespace constraint.
5548 *
5549 * Returns the new struture or NULL in case of error
5550 */
5551static xmlSchemaWildcardNsPtr
5552xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5553{
5554 xmlSchemaWildcardNsPtr ret;
5555
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005556 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005557 xmlMalloc(sizeof(xmlSchemaWildcardNs));
5558 if (ret == NULL) {
5559 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005560 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00005561 }
5562 ret->value = NULL;
5563 ret->next = NULL;
5564 return (ret);
5565}
5566
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005567static xmlSchemaIDCPtr
5568xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5569 const xmlChar *name, const xmlChar *nsName,
5570 int category, xmlNodePtr node)
5571{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005572 xmlSchemaIDCPtr ret = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005573
5574 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5575 return (NULL);
5576
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005577 ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5578 if (ret == NULL) {
5579 xmlSchemaPErrMemory(ctxt,
5580 "allocating an identity-constraint definition", NULL);
5581 return (NULL);
5582 }
5583 memset(ret, 0, sizeof(xmlSchemaIDC));
5584 /* The target namespace of the parent element declaration. */
5585 ret->targetNamespace = nsName;
5586 ret->name = name;
5587 ret->type = category;
5588 ret->node = node;
5589
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005590 WXS_ADD_GLOBAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005591 /*
5592 * Only keyrefs need to be fixup up.
5593 */
5594 if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005595 WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005596 return (ret);
5597}
5598
Daniel Veillard3646d642004-06-02 19:19:14 +00005599/**
5600 * xmlSchemaAddWildcard:
5601 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005602 * @schema: a schema
5603 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005604 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005605 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00005606 *
5607 * Returns the new struture or NULL in case of error
5608 */
5609static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005610xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5611 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00005612{
5613 xmlSchemaWildcardPtr ret = NULL;
5614
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005615 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00005616 return (NULL);
5617
5618 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5619 if (ret == NULL) {
5620 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5621 return (NULL);
5622 }
5623 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005624 ret->type = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005625 ret->node = node;
5626 WXS_ADD_LOCAL(ctxt, ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00005627 return (ret);
5628}
5629
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005630static void
5631xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5632{
5633 if (group == NULL)
5634 return;
5635 if (group->members != NULL)
5636 xmlSchemaItemListFree(group->members);
5637 xmlFree(group);
5638}
5639
5640static xmlSchemaSubstGroupPtr
5641xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5642 xmlSchemaElementPtr head)
5643{
5644 xmlSchemaSubstGroupPtr ret;
5645
5646 /* Init subst group hash. */
5647 if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5648 WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5649 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5650 return(NULL);
5651 }
5652 /* Create a new substitution group. */
5653 ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5654 if (ret == NULL) {
5655 xmlSchemaPErrMemory(NULL,
5656 "allocating a substitution group container", NULL);
5657 return(NULL);
5658 }
5659 memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5660 ret->head = head;
5661 /* Create list of members. */
5662 ret->members = xmlSchemaItemListCreate();
5663 if (ret->members == NULL) {
5664 xmlSchemaSubstGroupFree(ret);
5665 return(NULL);
5666 }
5667 /* Add subst group to hash. */
5668 if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5669 head->name, head->targetNamespace, ret) != 0) {
5670 PERROR_INT("xmlSchemaSubstGroupAdd",
5671 "failed to add a new substitution container");
5672 xmlSchemaSubstGroupFree(ret);
5673 return(NULL);
5674 }
5675 return(ret);
5676}
5677
5678static xmlSchemaSubstGroupPtr
5679xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5680 xmlSchemaElementPtr head)
5681{
5682 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5683 return(NULL);
5684 return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5685 head->name, head->targetNamespace));
5686
5687}
5688
5689/**
5690 * xmlSchemaAddElementSubstitutionMember:
5691 * @pctxt: a schema parser context
5692 * @head: the head of the substitution group
5693 * @member: the new member of the substitution group
5694 *
5695 * Allocate a new annotation structure.
5696 *
5697 * Returns the newly allocated structure or NULL in case or error
5698 */
5699static int
5700xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5701 xmlSchemaElementPtr head,
5702 xmlSchemaElementPtr member)
5703{
5704 xmlSchemaSubstGroupPtr substGroup = NULL;
5705
5706 if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5707 return (-1);
5708
5709 substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5710 if (substGroup == NULL)
5711 substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5712 if (substGroup == NULL)
5713 return(-1);
5714 if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5715 return(-1);
5716 return(0);
5717}
5718
Daniel Veillard4255d502002-04-16 15:50:10 +00005719/************************************************************************
5720 * *
5721 * Utilities for parsing *
5722 * *
5723 ************************************************************************/
5724
Daniel Veillard4255d502002-04-16 15:50:10 +00005725/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005726 * xmlSchemaPValAttrNodeQNameValue:
5727 * @ctxt: a schema parser context
5728 * @schema: the schema context
5729 * @ownerDes: the designation of the parent element
5730 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005731 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00005732 * @local: the resulting local part if found, the attribute value otherwise
5733 * @uri: the resulting namespace URI if found
5734 *
5735 * Extracts the local name and the URI of a QName value and validates it.
5736 * This one is intended to be used on attribute values that
5737 * should resolve to schema components.
5738 *
5739 * Returns 0, in case the QName is valid, a positive error code
5740 * if not valid and -1 if an internal error occurs.
5741 */
5742static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005743xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005744 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005745 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005746 xmlAttrPtr attr,
5747 const xmlChar *value,
5748 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005749 const xmlChar **local)
5750{
5751 const xmlChar *pref;
5752 xmlNsPtr ns;
5753 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005754
Daniel Veillardc0826a72004-08-10 14:17:33 +00005755 *uri = NULL;
5756 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005757 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005758 if (ret > 0) {
5759 xmlSchemaPSimpleTypeErr(ctxt,
5760 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5761 ownerItem, (xmlNodePtr) attr,
5762 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5763 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005764 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005765 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005766 } else if (ret < 0)
5767 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005768
5769 if (!strchr((char *) value, ':')) {
Daniel Veillard24505b02005-07-28 23:49:35 +00005770 ns = xmlSearchNs(attr->doc, attr->parent, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005771 if (ns)
5772 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5773 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005774 /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5775 * parser context. */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005776 /*
5777 * This one takes care of included schemas with no
5778 * target namespace.
5779 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005780 *uri = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005781 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005782 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005783 return (0);
5784 }
5785 /*
5786 * At this point xmlSplitQName3 has to return a local name.
5787 */
5788 *local = xmlSplitQName3(value, &len);
5789 *local = xmlDictLookup(ctxt->dict, *local, -1);
5790 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005791 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5792 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005793 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005794 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005795 ownerItem, (xmlNodePtr) attr,
5796 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5797 "The value '%s' of simple type 'xs:QName' has no "
5798 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005799 return (ctxt->err);
5800 } else {
5801 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005802 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005803 return (0);
5804}
5805
5806/**
5807 * xmlSchemaPValAttrNodeQName:
5808 * @ctxt: a schema parser context
5809 * @schema: the schema context
5810 * @ownerDes: the designation of the owner element
5811 * @ownerItem: the owner as a schema object
5812 * @attr: the attribute node
5813 * @local: the resulting local part if found, the attribute value otherwise
5814 * @uri: the resulting namespace URI if found
5815 *
5816 * Extracts and validates the QName of an attribute value.
5817 * This one is intended to be used on attribute values that
5818 * should resolve to schema components.
5819 *
5820 * Returns 0, in case the QName is valid, a positive error code
5821 * if not valid and -1 if an internal error occurs.
5822 */
5823static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005824xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005825 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005826 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005827 xmlAttrPtr attr,
5828 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005829 const xmlChar **local)
5830{
5831 const xmlChar *value;
5832
5833 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005834 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005835 ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005836}
5837
5838/**
5839 * xmlSchemaPValAttrQName:
5840 * @ctxt: a schema parser context
5841 * @schema: the schema context
5842 * @ownerDes: the designation of the parent element
5843 * @ownerItem: the owner as a schema object
5844 * @ownerElem: the parent node of the attribute
5845 * @name: the name of the attribute
5846 * @local: the resulting local part if found, the attribute value otherwise
5847 * @uri: the resulting namespace URI if found
5848 *
5849 * Extracts and validates the QName of an attribute value.
5850 *
5851 * Returns 0, in case the QName is valid, a positive error code
5852 * if not valid and -1 if an internal error occurs.
5853 */
5854static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005855xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5856 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005857 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005858 xmlNodePtr ownerElem,
5859 const char *name,
5860 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005861 const xmlChar **local)
5862{
5863 xmlAttrPtr attr;
5864
5865 attr = xmlSchemaGetPropNode(ownerElem, name);
5866 if (attr == NULL) {
5867 *local = NULL;
5868 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005869 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005870 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005871 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005872 ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005873}
5874
5875/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005876 * xmlSchemaPValAttrID:
5877 * @ctxt: a schema parser context
5878 * @schema: the schema context
5879 * @ownerDes: the designation of the parent element
5880 * @ownerItem: the owner as a schema object
5881 * @ownerElem: the parent node of the attribute
5882 * @name: the name of the attribute
5883 *
5884 * Extracts and validates the ID of an attribute value.
5885 *
5886 * Returns 0, in case the ID is valid, a positive error code
5887 * if not valid and -1 if an internal error occurs.
5888 */
5889static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005890xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005891{
5892 int ret;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005893 const xmlChar *value;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005894
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005895 if (attr == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005896 return(0);
5897 value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5898 ret = xmlValidateNCName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005899 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005900 /*
5901 * NOTE: the IDness might have already be declared in the DTD
5902 */
5903 if (attr->atype != XML_ATTRIBUTE_ID) {
5904 xmlIDPtr res;
5905 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005906
5907 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005908 * TODO: Use xmlSchemaStrip here; it's not exported at this
5909 * moment.
5910 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005911 strip = xmlSchemaCollapseString(value);
5912 if (strip != NULL) {
5913 xmlFree((xmlChar *) value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005914 value = strip;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005915 }
5916 res = xmlAddID(NULL, attr->doc, value, attr);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005917 if (res == NULL) {
5918 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005919 xmlSchemaPSimpleTypeErr(ctxt,
5920 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005921 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005922 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5923 NULL, NULL, "Duplicate value '%s' of simple "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005924 "type 'xs:ID'", value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005925 } else
5926 attr->atype = XML_ATTRIBUTE_ID;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005927 }
5928 } else if (ret > 0) {
5929 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005930 xmlSchemaPSimpleTypeErr(ctxt,
5931 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005932 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005933 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5934 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5935 "not a valid 'xs:NCName'",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005936 value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005937 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005938 if (value != NULL)
5939 xmlFree((xmlChar *)value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005940
5941 return (ret);
5942}
5943
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005944static int
5945xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5946 xmlNodePtr ownerElem,
5947 const xmlChar *name)
5948{
5949 xmlAttrPtr attr;
5950
5951 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5952 if (attr == NULL)
5953 return(0);
5954 return(xmlSchemaPValAttrNodeID(ctxt, attr));
5955
5956}
5957
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005958/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005959 * xmlGetMaxOccurs:
5960 * @ctxt: a schema validation context
5961 * @node: a subtree containing XML Schema informations
5962 *
5963 * Get the maxOccurs property
5964 *
5965 * Returns the default if not found, or the value
5966 */
5967static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005968xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5969 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005970{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005971 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005972 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005973 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005974
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005975 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5976 if (attr == NULL)
5977 return (def);
5978 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005979
5980 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005981 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005982 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005983 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5984 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005985 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005986 val, NULL, NULL, NULL);
5987 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005988 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005989 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005990 }
5991
5992 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005993 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005994 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005995 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005996 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005997 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5998 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005999 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006000 val, NULL, NULL, NULL);
6001 return (def);
6002 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006003 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006004 ret = ret * 10 + (*cur - '0');
6005 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00006006 }
William M. Brack76e95df2003-10-18 16:20:14 +00006007 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006008 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006009 /*
6010 * TODO: Restrict the maximal value to Integer.
6011 */
6012 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006013 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006014 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6015 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006016 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006017 val, NULL, NULL, NULL);
6018 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006019 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006020 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006021}
6022
6023/**
6024 * xmlGetMinOccurs:
6025 * @ctxt: a schema validation context
6026 * @node: a subtree containing XML Schema informations
6027 *
6028 * Get the minOccurs property
6029 *
6030 * Returns the default if not found, or the value
6031 */
6032static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006033xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006034 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006035{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006036 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00006037 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006038 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006039
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006040 attr = xmlSchemaGetPropNode(node, "minOccurs");
6041 if (attr == NULL)
6042 return (def);
6043 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00006044 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00006045 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006046 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006047 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006048 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006049 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6050 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006051 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006052 val, NULL, NULL, NULL);
6053 return (def);
6054 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006055 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006056 ret = ret * 10 + (*cur - '0');
6057 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00006058 }
William M. Brack76e95df2003-10-18 16:20:14 +00006059 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006060 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006061 /*
6062 * TODO: Restrict the maximal value to Integer.
6063 */
6064 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006065 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006066 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6067 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006068 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006069 val, NULL, NULL, NULL);
6070 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006071 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006072 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006073}
6074
6075/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006076 * xmlSchemaPGetBoolNodeValue:
6077 * @ctxt: a schema validation context
6078 * @ownerDes: owner designation
6079 * @ownerItem: the owner as a schema item
6080 * @node: the node holding the value
6081 *
6082 * Converts a boolean string value into 1 or 0.
6083 *
6084 * Returns 0 or 1.
6085 */
6086static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006087xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006088 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006089 xmlNodePtr node)
6090{
6091 xmlChar *value = NULL;
6092 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006093
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006094 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006095 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006096 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006097 * An instance of a datatype that is defined as ·boolean·
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006098 * can have the following legal literals {true, false, 1, 0}.
6099 */
6100 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6101 res = 1;
6102 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6103 res = 0;
6104 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6105 res = 1;
6106 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006107 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006108 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006109 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006110 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006111 ownerItem, node,
6112 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6113 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006114 NULL, NULL, NULL);
6115 }
6116 if (value != NULL)
6117 xmlFree(value);
6118 return (res);
6119}
6120
6121/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006122 * xmlGetBooleanProp:
6123 * @ctxt: a schema validation context
6124 * @node: a subtree containing XML Schema informations
6125 * @name: the attribute name
6126 * @def: the default value
6127 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006128 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00006129 *
6130 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006131 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00006132 */
6133static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006134xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006135 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006136 const char *name, int def)
6137{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006138 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00006139
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006140 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006141 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006142 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006143 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006144 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006145 * An instance of a datatype that is defined as ·boolean·
Daniel Veillardc0826a72004-08-10 14:17:33 +00006146 * can have the following legal literals {true, false, 1, 0}.
6147 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006148 if (xmlStrEqual(val, BAD_CAST "true"))
6149 def = 1;
6150 else if (xmlStrEqual(val, BAD_CAST "false"))
6151 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006152 else if (xmlStrEqual(val, BAD_CAST "1"))
6153 def = 1;
6154 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006155 def = 0;
6156 else {
6157 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006158 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006159 NULL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006160 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006161 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6162 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006163 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006164 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006165}
6166
6167/************************************************************************
6168 * *
6169 * Shema extraction from an Infoset *
6170 * *
6171 ************************************************************************/
6172static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6173 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006174 xmlNodePtr node,
6175 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006176static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6177 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00006178 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006179 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00006180 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006181static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6182 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00006183 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006184 xmlNodePtr node,
6185 xmlSchemaTypeType parentType);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006186static xmlSchemaBasicItemPtr
6187xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6188 xmlSchemaPtr schema,
6189 xmlNodePtr node,
6190 xmlSchemaItemListPtr uses,
6191 int parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00006192static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6193 xmlSchemaPtr schema,
6194 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00006195static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006196xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6197 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006198
6199/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006200 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006201 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00006202 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00006203 * @ownerDes: the designation of the parent element
6204 * @ownerItem: the schema object owner if existent
6205 * @attr: the schema attribute node being validated
6206 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006207 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00006208 *
6209 * Validates a value against the given built-in type.
6210 * This one is intended to be used internally for validation
6211 * of schema attribute values during parsing of the schema.
6212 *
6213 * Returns 0 if the value is valid, a positive error code
6214 * number otherwise and -1 in case of an internal or API error.
6215 */
6216static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006217xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006218 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006219 xmlAttrPtr attr,
6220 const xmlChar *value,
6221 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00006222{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006223
6224 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006225
6226 /*
6227 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6228 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006229 */
6230 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00006231 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006232 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6233 PERROR_INT("xmlSchemaPValAttrNodeValue",
6234 "the given type is not a built-in type");
6235 return (-1);
6236 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006237 switch (type->builtInType) {
6238 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006239 case XML_SCHEMAS_QNAME:
6240 case XML_SCHEMAS_ANYURI:
6241 case XML_SCHEMAS_TOKEN:
6242 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006243 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6244 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006245 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006246 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006247 PERROR_INT("xmlSchemaPValAttrNodeValue",
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +00006248 "validation using the given type is not supported while "
6249 "parsing a schema");
Daniel Veillard01fa6152004-06-29 17:04:39 +00006250 return (-1);
6251 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006252 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006253 /*
6254 * TODO: Should we use the S4S error codes instead?
6255 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006256 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006257 PERROR_INT("xmlSchemaPValAttrNodeValue",
6258 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006259 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006260 } else if (ret > 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006261 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006262 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6263 else
6264 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6265 xmlSchemaPSimpleTypeErr(pctxt,
6266 ret, ownerItem, (xmlNodePtr) attr,
6267 type, NULL, value, NULL, NULL, NULL);
6268 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006269 return (ret);
6270}
6271
6272/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006273 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006274 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006275 * @ctxt: a schema parser context
6276 * @ownerDes: the designation of the parent element
6277 * @ownerItem: the schema object owner if existent
6278 * @attr: the schema attribute node being validated
6279 * @type: the built-in type to be validated against
6280 * @value: the resulting value if any
6281 *
6282 * Extracts and validates a value against the given built-in type.
6283 * This one is intended to be used internally for validation
6284 * of schema attribute values during parsing of the schema.
6285 *
6286 * Returns 0 if the value is valid, a positive error code
6287 * number otherwise and -1 in case of an internal or API error.
6288 */
6289static int
6290xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006291 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006292 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006293 xmlSchemaTypePtr type,
6294 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006295{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006296 const xmlChar *val;
6297
6298 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006299 return (-1);
6300
Daniel Veillardc0826a72004-08-10 14:17:33 +00006301 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6302 if (value != NULL)
6303 *value = val;
6304
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006305 return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006306 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00006307}
6308
6309/**
6310 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006311 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006312 * @ctxt: a schema parser context
6313 * @node: the element node of the attribute
6314 * @ownerDes: the designation of the parent element
6315 * @ownerItem: the schema object owner if existent
6316 * @ownerElem: the owner element node
6317 * @name: the name of the schema attribute node
6318 * @type: the built-in type to be validated against
6319 * @value: the resulting value if any
6320 *
6321 * Extracts and validates a value against the given built-in type.
6322 * This one is intended to be used internally for validation
6323 * of schema attribute values during parsing of the schema.
6324 *
6325 * Returns 0 if the value is valid, a positive error code
6326 * number otherwise and -1 in case of an internal or API error.
6327 */
6328static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006329xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6330 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006331 xmlNodePtr ownerElem,
6332 const char *name,
6333 xmlSchemaTypePtr type,
6334 const xmlChar **value)
6335{
6336 xmlAttrPtr attr;
6337
6338 if ((ctxt == NULL) || (type == NULL)) {
6339 if (value != NULL)
6340 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006341 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006342 }
6343 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6344 if (value != NULL)
6345 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006346 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006347 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006348 "Internal error: xmlSchemaPValAttr, the given "
6349 "type '%s' is not a built-in type.\n",
6350 type->name, NULL);
6351 return (-1);
6352 }
6353 attr = xmlSchemaGetPropNode(ownerElem, name);
6354 if (attr == NULL) {
6355 if (value != NULL)
6356 *value = NULL;
6357 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006358 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006359 return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006360 type, value));
6361}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006362
6363static int
6364xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006365 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006366 xmlNodePtr node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006367 xmlAttrPtr attr,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006368 const xmlChar *namespaceName)
6369{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006370 /* TODO: Pointer comparison instead? */
6371 if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006372 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006373 if (xmlStrEqual(xmlSchemaNs, namespaceName))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006374 return (0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006375 /*
6376 * Check if the referenced namespace was <import>ed.
6377 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006378 if (WXS_BUCKET(pctxt)->relations != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006379 xmlSchemaSchemaRelationPtr rel;
6380
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006381 rel = WXS_BUCKET(pctxt)->relations;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006382 do {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006383 if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006384 xmlStrEqual(namespaceName, rel->importNamespace))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006385 return (0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006386 rel = rel->next;
6387 } while (rel != NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006388 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006389 /*
6390 * No matching <import>ed namespace found.
6391 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006392 {
6393 xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6394
6395 if (namespaceName == NULL)
6396 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6397 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6398 "References from this schema to components in no "
6399 "namespace are not allowed, since not indicated by an "
6400 "import statement", NULL, NULL);
6401 else
6402 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6403 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6404 "References from this schema to components in the "
6405 "namespace '%s' are not allowed, since not indicated by an "
6406 "import statement", namespaceName, NULL);
6407 }
6408 return (XML_SCHEMAP_SRC_RESOLVE);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006409}
6410
Daniel Veillardc0826a72004-08-10 14:17:33 +00006411/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006412 * xmlSchemaParseLocalAttributes:
Daniel Veillard4255d502002-04-16 15:50:10 +00006413 * @ctxt: a schema validation context
6414 * @schema: the schema being built
6415 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006416 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00006417 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006418 * Parses attribute uses and attribute declarations and
6419 * attribute group references.
Daniel Veillard4255d502002-04-16 15:50:10 +00006420 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006421static int
6422xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6423 xmlNodePtr *child, xmlSchemaItemListPtr *list,
6424 int parentType, int *hasRefs)
Daniel Veillard4255d502002-04-16 15:50:10 +00006425{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006426 void *item;
Daniel Veillard4255d502002-04-16 15:50:10 +00006427
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006428 while ((IS_SCHEMA((*child), "attribute")) ||
6429 (IS_SCHEMA((*child), "attributeGroup"))) {
6430 if (IS_SCHEMA((*child), "attribute")) {
6431 item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6432 *list, parentType);
6433 } else {
6434 item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6435 if ((item != NULL) && (hasRefs != NULL))
6436 *hasRefs = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006437 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006438 if (item != NULL) {
6439 if (*list == NULL) {
6440 /* TODO: Customize grow factor. */
6441 *list = xmlSchemaItemListCreate();
6442 if (*list == NULL)
6443 return(-1);
6444 }
6445 if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6446 return(-1);
6447 }
6448 *child = (*child)->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006449 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006450 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006451}
6452
6453/**
6454 * xmlSchemaParseAnnotation:
6455 * @ctxt: a schema validation context
6456 * @schema: the schema being built
6457 * @node: a subtree containing XML Schema informations
6458 *
6459 * parse a XML schema Attrribute declaration
6460 * *WARNING* this interface is highly subject to change
6461 *
William M. Bracke7091952004-05-11 15:09:58 +00006462 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006463 * 1 in case of success.
6464 */
6465static xmlSchemaAnnotPtr
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00006466xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
Daniel Veillard4255d502002-04-16 15:50:10 +00006467{
6468 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006469 xmlNodePtr child = NULL;
6470 xmlAttrPtr attr;
6471 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00006472
Daniel Veillardc0826a72004-08-10 14:17:33 +00006473 /*
6474 * INFO: S4S completed.
6475 */
6476 /*
6477 * id = ID
6478 * {any attributes with non-schema namespace . . .}>
6479 * Content: (appinfo | documentation)*
6480 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00006481 if ((ctxt == NULL) || (node == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00006482 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006483 if (needed)
6484 ret = xmlSchemaNewAnnot(ctxt, node);
6485 else
6486 ret = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006487 attr = node->properties;
6488 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006489 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006490 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006491 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006492 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006493
6494 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006495 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006496 }
6497 attr = attr->next;
6498 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006499 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006500 /*
6501 * And now for the children...
6502 */
6503 child = node->children;
6504 while (child != NULL) {
6505 if (IS_SCHEMA(child, "appinfo")) {
6506 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006507 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006508 * source = anyURI
6509 * {any attributes with non-schema namespace . . .}>
6510 * Content: ({any})*
6511 */
6512 attr = child->properties;
6513 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006514 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006515 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006516 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006517 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006518
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006519 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006520 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006521 }
6522 attr = attr->next;
6523 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006524 xmlSchemaPValAttr(ctxt, NULL, child, "source",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006525 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006526 child = child->next;
6527 } else if (IS_SCHEMA(child, "documentation")) {
6528 /* TODO: make available the content of "documentation". */
6529 /*
6530 * source = anyURI
6531 * {any attributes with non-schema namespace . . .}>
6532 * Content: ({any})*
6533 */
6534 attr = child->properties;
6535 while (attr != NULL) {
6536 if (attr->ns == NULL) {
6537 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006538 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006539 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006540 }
6541 } else {
6542 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6543 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
6544 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006545
6546 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006547 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006548 }
6549 }
6550 attr = attr->next;
6551 }
6552 /*
6553 * Attribute "xml:lang".
6554 */
6555 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6556 if (attr != NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006557 xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006558 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006559 child = child->next;
6560 } else {
6561 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006562 xmlSchemaPContentErr(ctxt,
6563 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006564 NULL, node, child, NULL, "(appinfo | documentation)*");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006565 barked = 1;
6566 child = child->next;
6567 }
6568 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006569
Daniel Veillard4255d502002-04-16 15:50:10 +00006570 return (ret);
6571}
6572
6573/**
6574 * xmlSchemaParseFacet:
6575 * @ctxt: a schema validation context
6576 * @schema: the schema being built
6577 * @node: a subtree containing XML Schema informations
6578 *
6579 * parse a XML schema Facet declaration
6580 * *WARNING* this interface is highly subject to change
6581 *
6582 * Returns the new type structure or NULL in case of error
6583 */
6584static xmlSchemaFacetPtr
6585xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006586 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006587{
6588 xmlSchemaFacetPtr facet;
6589 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006590 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00006591
6592 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6593 return (NULL);
6594
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006595 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006596 if (facet == NULL) {
6597 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6598 return (NULL);
6599 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006600 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006601 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00006602 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006603 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6604 "Facet %s has no value\n", node->name, NULL);
6605 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00006606 return (NULL);
6607 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006608 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006609 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006610 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006611 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006612 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006613 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006614 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006615 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006616 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006617 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006618 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006619 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006620 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006621 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006622 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006623 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006624 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006625 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006626 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006627 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006628 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006629 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6630 } else if (IS_SCHEMA(node, "minLength")) {
6631 facet->type = XML_SCHEMA_FACET_MINLENGTH;
6632 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006633 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6634 "Unknown facet type %s\n", node->name, NULL);
6635 xmlSchemaFreeFacet(facet);
6636 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006637 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006638 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006639 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006640 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6641 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6642 const xmlChar *fixed;
6643
6644 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6645 if (fixed != NULL) {
6646 if (xmlStrEqual(fixed, BAD_CAST "true"))
6647 facet->fixed = 1;
6648 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006649 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006650 child = node->children;
6651
6652 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00006653 facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006654 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006655 }
6656 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006657 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6658 "Facet %s has unexpected child content\n",
6659 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006660 }
6661 return (facet);
6662}
6663
6664/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006665 * xmlSchemaParseWildcardNs:
6666 * @ctxt: a schema parser context
6667 * @wildc: the wildcard, already created
6668 * @node: a subtree containing XML Schema informations
6669 *
6670 * Parses the attribute "processContents" and "namespace"
6671 * of a xsd:anyAttribute and xsd:any.
6672 * *WARNING* this interface is highly subject to change
6673 *
6674 * Returns 0 if everything goes fine, a positive error code
6675 * if something is not valid and -1 if an internal error occurs.
6676 */
6677static int
6678xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006679 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006680 xmlSchemaWildcardPtr wildc,
6681 xmlNodePtr node)
6682{
6683 const xmlChar *pc, *ns, *dictnsItem;
6684 int ret = 0;
6685 xmlChar *nsItem;
6686 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6687 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006688
Daniel Veillardc0826a72004-08-10 14:17:33 +00006689 pc = xmlSchemaGetProp(ctxt, node, "processContents");
6690 if ((pc == NULL)
6691 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6692 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6693 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6694 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6695 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6696 wildc->processContents = XML_SCHEMAS_ANY_LAX;
6697 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006698 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006699 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006700 NULL, node,
6701 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006702 NULL, NULL, NULL);
6703 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006704 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006705 }
6706 /*
6707 * Build the namespace constraints.
6708 */
6709 attr = xmlSchemaGetPropNode(node, "namespace");
6710 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006711 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00006712 wildc->any = 1;
6713 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6714 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006715 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006716 return (-1);
6717 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006718 wildc->negNsSet->value = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006719 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006720 const xmlChar *end, *cur;
6721
6722 cur = ns;
6723 do {
6724 while (IS_BLANK_CH(*cur))
6725 cur++;
6726 end = cur;
6727 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6728 end++;
6729 if (end == cur)
6730 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006731 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006732 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6733 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006734 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006735 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006736 NULL, (xmlNodePtr) attr,
6737 NULL,
6738 "((##any | ##other) | List of (xs:anyURI | "
6739 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006740 nsItem, NULL, NULL, NULL);
6741 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6742 } else {
6743 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006744 dictnsItem = ctxt->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006745 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6746 dictnsItem = NULL;
6747 } else {
6748 /*
6749 * Validate the item (anyURI).
6750 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006751 xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006752 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6753 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6754 }
6755 /*
6756 * Avoid dublicate namespaces.
6757 */
6758 tmp = wildc->nsSet;
6759 while (tmp != NULL) {
6760 if (dictnsItem == tmp->value)
6761 break;
6762 tmp = tmp->next;
6763 }
6764 if (tmp == NULL) {
6765 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6766 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006767 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006768 return (-1);
6769 }
6770 tmp->value = dictnsItem;
6771 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006772 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006773 wildc->nsSet = tmp;
6774 else
6775 lastNs->next = tmp;
6776 lastNs = tmp;
6777 }
6778
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006779 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006780 xmlFree(nsItem);
6781 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006782 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006783 }
6784 return (ret);
6785}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006786
6787static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006788xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6789 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006790 xmlNodePtr node,
6791 int minOccurs,
6792 int maxOccurs) {
6793
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006794 if ((maxOccurs == 0) && ( minOccurs == 0))
6795 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006796 if (maxOccurs != UNBOUNDED) {
6797 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006798 * TODO: Maybe we should better not create the particle,
6799 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006800 * content model.
6801 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006802 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006803 * 3.9.6 Schema Component Constraint: Particle Correct
6804 *
6805 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006806 if (maxOccurs < 1) {
6807 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006808 * 2.2 {max occurs} must be greater than or equal to 1.
6809 */
6810 xmlSchemaPCustomAttrErr(ctxt,
6811 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006812 NULL, NULL,
6813 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006814 "The value must be greater than or equal to 1");
6815 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6816 } else if (minOccurs > maxOccurs) {
6817 /*
6818 * 2.1 {min occurs} must not be greater than {max occurs}.
6819 */
6820 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006821 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006822 NULL, NULL,
6823 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006824 "The value must not be greater than the value of 'maxOccurs'");
6825 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6826 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006827 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006828 return (0);
6829}
6830
Daniel Veillardc0826a72004-08-10 14:17:33 +00006831/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006832 * xmlSchemaParseAny:
6833 * @ctxt: a schema validation context
6834 * @schema: the schema being built
6835 * @node: a subtree containing XML Schema informations
6836 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006837 * Parsea a XML schema <any> element. A particle and wildcard
6838 * will be created (except if minOccurs==maxOccurs==0, in this case
6839 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006840 * *WARNING* this interface is highly subject to change
6841 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006842 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006843 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006844static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006845xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6846 xmlNodePtr node)
6847{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006848 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006849 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006850 xmlSchemaWildcardPtr wild;
6851 int min, max;
6852 xmlAttrPtr attr;
6853 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006854
6855 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6856 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006857 /*
6858 * Check for illegal attributes.
6859 */
6860 attr = node->properties;
6861 while (attr != NULL) {
6862 if (attr->ns == NULL) {
6863 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6864 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6865 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6866 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6867 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006868 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006869 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006870 }
6871 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006872 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006873 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006874 }
6875 attr = attr->next;
6876 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006877 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006878 /*
6879 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006880 */
6881 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6882 "(xs:nonNegativeInteger | unbounded)");
6883 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6884 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006885 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6886 /*
6887 * Create & parse the wildcard.
6888 */
6889 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6890 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006891 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006892 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006893 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006894 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006895 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006896 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006897 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00006898 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006899 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006900 }
6901 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006902 xmlSchemaPContentErr(ctxt,
6903 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006904 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006905 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006906 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006907 /*
6908 * No component if minOccurs==maxOccurs==0.
6909 */
6910 if ((min == 0) && (max == 0)) {
6911 /* Don't free the wildcard, since it's already on the list. */
6912 return (NULL);
6913 }
6914 /*
6915 * Create the particle.
6916 */
6917 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6918 if (particle == NULL)
6919 return (NULL);
6920 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006921 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006922
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006923 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006924}
6925
6926/**
6927 * xmlSchemaParseNotation:
6928 * @ctxt: a schema validation context
6929 * @schema: the schema being built
6930 * @node: a subtree containing XML Schema informations
6931 *
6932 * parse a XML schema Notation declaration
6933 *
6934 * Returns the new structure or NULL in case of error
6935 */
6936static xmlSchemaNotationPtr
6937xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006938 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006939{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006940 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006941 xmlSchemaNotationPtr ret;
6942 xmlNodePtr child = NULL;
6943
6944 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6945 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006946 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006947 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006948 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6949 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006950 return (NULL);
6951 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006952 ret = xmlSchemaAddNotation(ctxt, schema, name,
6953 ctxt->targetNamespace, node);
6954 if (ret == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00006955 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006956 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006957
6958 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00006959 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006960 child = child->next;
6961 }
6962
Daniel Veillard4255d502002-04-16 15:50:10 +00006963 child = node->children;
6964 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00006965 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006966 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006967 }
6968 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006969 xmlSchemaPContentErr(ctxt,
6970 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006971 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006972 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006973 }
6974
6975 return (ret);
6976}
6977
6978/**
6979 * xmlSchemaParseAnyAttribute:
6980 * @ctxt: a schema validation context
6981 * @schema: the schema being built
6982 * @node: a subtree containing XML Schema informations
6983 *
6984 * parse a XML schema AnyAttrribute declaration
6985 * *WARNING* this interface is highly subject to change
6986 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006987 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006988 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006989static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006990xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6991 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006992{
Daniel Veillard3646d642004-06-02 19:19:14 +00006993 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006994 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006995 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006996
6997 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6998 return (NULL);
6999
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007000 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7001 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007002 if (ret == NULL) {
7003 return (NULL);
7004 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007005 /*
7006 * Check for illegal attributes.
7007 */
7008 attr = node->properties;
7009 while (attr != NULL) {
7010 if (attr->ns == NULL) {
7011 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7012 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7013 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007014 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007015 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007016 }
7017 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007018 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007019 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007020 }
7021 attr = attr->next;
7022 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007023 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007024 /*
7025 * Parse the namespace list.
7026 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007027 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007028 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007029 /*
7030 * And now for the children...
7031 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007032 child = node->children;
7033 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007034 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007035 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007036 }
7037 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007038 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007039 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007040 NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007041 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007042 }
7043
7044 return (ret);
7045}
7046
7047
7048/**
7049 * xmlSchemaParseAttribute:
7050 * @ctxt: a schema validation context
7051 * @schema: the schema being built
7052 * @node: a subtree containing XML Schema informations
7053 *
7054 * parse a XML schema Attrribute declaration
7055 * *WARNING* this interface is highly subject to change
7056 *
William M. Bracke7091952004-05-11 15:09:58 +00007057 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007058 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007059static xmlSchemaBasicItemPtr
7060xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7061 xmlSchemaPtr schema,
7062 xmlNodePtr node,
7063 xmlSchemaItemListPtr uses,
7064 int parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00007065{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007066 const xmlChar *attrValue, *name = NULL, *ns = NULL;
7067 xmlSchemaAttributeUsePtr use = NULL;
7068 xmlNodePtr child = NULL;
7069 xmlAttrPtr attr;
7070 const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7071 int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7072 int nberrors, hasForm = 0, defValueType = 0;
7073
7074#define WXS_ATTR_DEF_VAL_DEFAULT 1
7075#define WXS_ATTR_DEF_VAL_FIXED 2
7076
7077 /*
7078 * 3.2.3 Constraints on XML Representations of Attribute Declarations
7079 */
7080
7081 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7082 return (NULL);
7083 attr = xmlSchemaGetPropNode(node, "ref");
7084 if (attr != NULL) {
7085 if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7086 NULL, attr, &tmpNs, &tmpName) != 0) {
7087 return (NULL);
7088 }
7089 if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7090 return(NULL);
7091 isRef = 1;
7092 }
7093 nberrors = pctxt->nberrors;
7094 /*
7095 * Check for illegal attributes.
7096 */
7097 attr = node->properties;
7098 while (attr != NULL) {
7099 if (attr->ns == NULL) {
7100 if (isRef) {
7101 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7102 xmlSchemaPValAttrNodeID(pctxt, attr);
7103 goto attr_next;
7104 } else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7105 goto attr_next;
7106 }
7107 } else {
7108 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7109 goto attr_next;
7110 } else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7111 xmlSchemaPValAttrNodeID(pctxt, attr);
7112 goto attr_next;
7113 } else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7114 xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7115 attr, &tmpNs, &tmpName);
7116 goto attr_next;
7117 } else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7118 /*
7119 * Evaluate the target namespace
7120 */
7121 hasForm = 1;
7122 attrValue = xmlSchemaGetNodeContent(pctxt,
7123 (xmlNodePtr) attr);
7124 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7125 ns = pctxt->targetNamespace;
7126 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7127 {
7128 xmlSchemaPSimpleTypeErr(pctxt,
7129 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7130 NULL, (xmlNodePtr) attr,
7131 NULL, "(qualified | unqualified)",
7132 attrValue, NULL, NULL, NULL);
7133 }
7134 goto attr_next;
7135 }
7136 }
7137 if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7138
7139 attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7140 /* TODO: Maybe we need to normalize the value beforehand. */
7141 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7142 occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7143 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7144 occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7145 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7146 occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7147 else {
7148 xmlSchemaPSimpleTypeErr(pctxt,
7149 XML_SCHEMAP_INVALID_ATTR_USE,
7150 NULL, (xmlNodePtr) attr,
7151 NULL, "(optional | prohibited | required)",
7152 attrValue, NULL, NULL, NULL);
7153 }
7154 goto attr_next;
7155 } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7156 /*
7157 * 3.2.3 : 1
7158 * default and fixed must not both be present.
7159 */
7160 if (defValue) {
7161 xmlSchemaPMutualExclAttrErr(pctxt,
7162 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7163 NULL, attr, "default", "fixed");
7164 } else {
7165 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7166 defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7167 }
7168 goto attr_next;
7169 } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7170 /*
7171 * 3.2.3 : 1
7172 * default and fixed must not both be present.
7173 */
7174 if (defValue) {
7175 xmlSchemaPMutualExclAttrErr(pctxt,
7176 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7177 NULL, attr, "default", "fixed");
7178 } else {
7179 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7180 defValueType = WXS_ATTR_DEF_VAL_FIXED;
7181 }
7182 goto attr_next;
7183 }
7184 } else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7185 goto attr_next;
7186
7187 xmlSchemaPIllegalAttrErr(pctxt,
7188 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7189
7190attr_next:
7191 attr = attr->next;
7192 }
7193 /*
7194 * 3.2.3 : 2
7195 * If default and use are both present, use must have
7196 * the actual value optional.
7197 */
7198 if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7199 (occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7200 xmlSchemaPSimpleTypeErr(pctxt,
7201 XML_SCHEMAP_SRC_ATTRIBUTE_2,
7202 NULL, node, NULL,
7203 "(optional | prohibited | required)", NULL,
7204 "The value of the attribute 'use' must be 'optional' "
7205 "if the attribute 'default' is present",
7206 NULL, NULL);
7207 }
7208 /*
7209 * We want correct attributes.
7210 */
7211 if (nberrors != pctxt->nberrors)
7212 return(NULL);
7213 if (! isRef) {
7214 xmlSchemaAttributePtr attrDecl;
7215
7216 /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7217 if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7218 ns = pctxt->targetNamespace;
7219 /*
7220 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7221 * TODO: Move this to the component layer.
7222 */
7223 if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7224 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7225 XML_SCHEMAP_NO_XSI,
7226 node, NULL,
7227 "The target namespace must not match '%s'",
7228 xmlSchemaInstanceNs, NULL);
7229 }
7230 attr = xmlSchemaGetPropNode(node, "name");
7231 if (attr == NULL) {
7232 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7233 NULL, node, "name", NULL);
7234 return (NULL);
7235 }
7236 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7237 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7238 return (NULL);
7239 }
7240 /*
7241 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7242 * TODO: Move this to the component layer.
7243 */
7244 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7245 xmlSchemaPSimpleTypeErr(pctxt,
7246 XML_SCHEMAP_NO_XMLNS,
7247 NULL, (xmlNodePtr) attr,
7248 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7249 "The value of the attribute must not match 'xmlns'",
7250 NULL, NULL);
7251 return (NULL);
7252 }
7253 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7254 goto check_children;
7255 /*
7256 * Create the attribute use component.
7257 */
7258 use = xmlSchemaAddAttributeUse(pctxt, node);
7259 if (use == NULL)
7260 return(NULL);
7261 use->occurs = occurs;
7262 /*
7263 * Create the attribute declaration.
7264 */
7265 attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7266 if (attrDecl == NULL)
7267 return (NULL);
7268 if (tmpName != NULL) {
7269 attrDecl->typeName = tmpName;
7270 attrDecl->typeNs = tmpNs;
7271 }
7272 use->attrDecl = attrDecl;
7273 /*
7274 * Value constraint.
7275 */
7276 if (defValue != NULL) {
7277 attrDecl->defValue = defValue;
7278 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7279 attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7280 }
7281 } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7282 xmlSchemaQNameRefPtr ref;
7283
7284 /*
7285 * Create the attribute use component.
7286 */
7287 use = xmlSchemaAddAttributeUse(pctxt, node);
7288 if (use == NULL)
7289 return(NULL);
7290 /*
7291 * We need to resolve the reference at later stage.
7292 */
7293 WXS_ADD_PENDING(pctxt, use);
7294 use->occurs = occurs;
7295 /*
7296 * Create a QName reference to the attribute declaration.
7297 */
7298 ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7299 tmpName, tmpNs);
7300 if (ref == NULL)
7301 return(NULL);
7302 /*
7303 * Assign the reference. This will be substituted for the
7304 * referenced attribute declaration when the QName is resolved.
7305 */
7306 use->attrDecl = WXS_ATTR_CAST ref;
7307 /*
7308 * Value constraint.
7309 */
7310 if (defValue != NULL)
7311 use->defValue = defValue;
7312 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7313 use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7314 }
7315
7316check_children:
7317 /*
7318 * And now for the children...
7319 */
7320 child = node->children;
7321 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7322 xmlSchemaAttributeUseProhibPtr prohib;
7323
7324 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007325 xmlSchemaParseAnnotation(pctxt, child, 0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007326 child = child->next;
7327 }
7328 if (child != NULL) {
7329 xmlSchemaPContentErr(pctxt,
7330 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7331 NULL, node, child, NULL,
7332 "(annotation?)");
7333 }
7334 /*
7335 * Check for pointlessness of attribute prohibitions.
7336 */
7337 if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7338 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7339 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7340 node, NULL,
7341 "Skipping attribute use prohibition, since it is "
7342 "pointless inside an <attributeGroup>",
7343 NULL, NULL, NULL);
7344 return(NULL);
7345 } else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7346 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7347 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7348 node, NULL,
7349 "Skipping attribute use prohibition, since it is "
7350 "pointless when extending a type",
7351 NULL, NULL, NULL);
7352 return(NULL);
7353 }
7354 if (! isRef) {
7355 tmpName = name;
7356 tmpNs = ns;
7357 }
7358 /*
7359 * Check for duplicate attribute prohibitions.
7360 */
7361 if (uses) {
7362 int i;
7363
7364 for (i = 0; i < uses->nbItems; i++) {
7365 use = uses->items[i];
7366 if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7367 (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7368 (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7369 {
7370 xmlChar *str = NULL;
7371
7372 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7373 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7374 node, NULL,
7375 "Skipping duplicate attribute use prohibition '%s'",
7376 xmlSchemaFormatQName(&str, tmpNs, tmpName),
7377 NULL, NULL);
7378 FREE_AND_NULL(str)
7379 return(NULL);
7380 }
7381 }
7382 }
7383 /*
7384 * Create the attribute prohibition helper component.
7385 */
7386 prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7387 if (prohib == NULL)
7388 return(NULL);
7389 prohib->node = node;
7390 prohib->name = tmpName;
7391 prohib->targetNamespace = tmpNs;
7392 if (isRef) {
7393 /*
7394 * We need at least to resolve to the attribute declaration.
7395 */
7396 WXS_ADD_PENDING(pctxt, prohib);
7397 }
7398 return(WXS_BASIC_CAST prohib);
7399 } else {
7400 if (IS_SCHEMA(child, "annotation")) {
7401 /*
7402 * TODO: Should this go into the attr decl?
7403 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007404 use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007405 child = child->next;
7406 }
7407 if (isRef) {
7408 if (child != NULL) {
7409 if (IS_SCHEMA(child, "simpleType"))
7410 /*
7411 * 3.2.3 : 3.2
7412 * If ref is present, then all of <simpleType>,
7413 * form and type must be absent.
7414 */
7415 xmlSchemaPContentErr(pctxt,
7416 XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7417 NULL, node, child, NULL,
7418 "(annotation?)");
7419 else
7420 xmlSchemaPContentErr(pctxt,
7421 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7422 NULL, node, child, NULL,
7423 "(annotation?)");
7424 }
7425 } else {
7426 if (IS_SCHEMA(child, "simpleType")) {
7427 if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7428 /*
7429 * 3.2.3 : 4
7430 * type and <simpleType> must not both be present.
7431 */
7432 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7433 NULL, node, child,
7434 "The attribute 'type' and the <simpleType> child "
7435 "are mutually exclusive", NULL);
7436 } else
7437 WXS_ATTRUSE_TYPEDEF(use) =
7438 xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7439 child = child->next;
7440 }
7441 if (child != NULL)
7442 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7443 NULL, node, child, NULL,
7444 "(annotation?, simpleType?)");
7445 }
7446 }
7447 return (WXS_BASIC_CAST use);
7448}
7449
7450
7451static xmlSchemaAttributePtr
7452xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7453 xmlSchemaPtr schema,
7454 xmlNodePtr node)
7455{
7456 const xmlChar *attrValue;
Daniel Veillard4255d502002-04-16 15:50:10 +00007457 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007458 xmlNodePtr child = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007459 xmlAttrPtr attr;
William M. Bracke7091952004-05-11 15:09:58 +00007460
7461 /*
7462 * Note that the w3c spec assumes the schema to be validated with schema
7463 * for schemas beforehand.
7464 *
7465 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00007466 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007467 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7468 return (NULL);
7469 /*
7470 * 3.2.3 : 3.1
7471 * One of ref or name must be present, but not both
7472 */
7473 attr = xmlSchemaGetPropNode(node, "name");
7474 if (attr == NULL) {
7475 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7476 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007477 return (NULL);
7478 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007479 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7480 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7481 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007482 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007483 /*
7484 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7485 * TODO: Move this to the component layer.
7486 */
7487 if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7488 xmlSchemaPSimpleTypeErr(pctxt,
7489 XML_SCHEMAP_NO_XMLNS,
7490 NULL, (xmlNodePtr) attr,
7491 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7492 "The value of the attribute must not match 'xmlns'",
7493 NULL, NULL);
7494 return (NULL);
7495 }
7496 /*
7497 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7498 * TODO: Move this to the component layer.
7499 * Or better leave it here and add it to the component layer
7500 * if we have a schema construction API.
7501 */
7502 if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7503 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7504 XML_SCHEMAP_NO_XSI, node, NULL,
7505 "The target namespace must not match '%s'",
7506 xmlSchemaInstanceNs, NULL);
7507 }
7508
7509 ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7510 pctxt->targetNamespace, node, 1);
7511 if (ret == NULL)
7512 return (NULL);
7513 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7514
7515 /*
7516 * Check for illegal attributes.
7517 */
7518 attr = node->properties;
7519 while (attr != NULL) {
7520 if (attr->ns == NULL) {
7521 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7522 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7523 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7524 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7525 (!xmlStrEqual(attr->name, BAD_CAST "type")))
7526 {
7527 xmlSchemaPIllegalAttrErr(pctxt,
7528 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7529 }
7530 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7531 xmlSchemaPIllegalAttrErr(pctxt,
7532 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7533 }
7534 attr = attr->next;
7535 }
7536 xmlSchemaPValAttrQName(pctxt, schema, NULL,
7537 node, "type", &ret->typeNs, &ret->typeName);
7538
7539 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00007540 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007541 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00007542 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007543 ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007544 if (ret->defValue != NULL)
7545 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007546 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007547 * Attribute "default".
7548 */
7549 attr = xmlSchemaGetPropNode(node, "default");
7550 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007551 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007552 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007553 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007554 */
7555 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007556 xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7557 WXS_BASIC_CAST ret, attr, "default", "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007558 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007559 ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007560 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007561 /*
7562 * And now for the children...
7563 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007564 child = node->children;
7565 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007566 ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007567 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007568 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007569 if (IS_SCHEMA(child, "simpleType")) {
7570 if (ret->typeName != NULL) {
7571 /*
7572 * 3.2.3 : 4
7573 * type and <simpleType> must not both be present.
7574 */
7575 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7576 NULL, node, child,
7577 "The attribute 'type' and the <simpleType> child "
7578 "are mutually exclusive", NULL);
7579 } else
7580 ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7581 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007582 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007583 if (child != NULL)
7584 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7585 NULL, node, child, NULL,
7586 "(annotation?, simpleType?)");
7587
Daniel Veillard4255d502002-04-16 15:50:10 +00007588 return (ret);
7589}
7590
7591/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007592 * xmlSchemaParseAttributeGroupRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00007593 * @ctxt: a schema validation context
7594 * @schema: the schema being built
7595 * @node: a subtree containing XML Schema informations
7596 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007597 * Parse an attribute group definition reference.
7598 * Note that a reference to an attribute group does not
7599 * correspond to any component at all.
Daniel Veillard4255d502002-04-16 15:50:10 +00007600 * *WARNING* this interface is highly subject to change
7601 *
7602 * Returns the attribute group or NULL in case of error.
7603 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007604static xmlSchemaQNameRefPtr
7605xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7606 xmlSchemaPtr schema,
7607 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007608{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007609 xmlSchemaQNameRefPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00007610 xmlNodePtr child = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007611 xmlAttrPtr attr;
7612 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007613
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007614 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00007615 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007616
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007617 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007618 if (attr == NULL) {
7619 xmlSchemaPMissingAttrErr(pctxt,
7620 XML_SCHEMAP_S4S_ATTR_MISSING,
7621 NULL, node, "ref", NULL);
7622 return (NULL);
7623 }
7624 xmlSchemaPValAttrNodeQName(pctxt, schema,
7625 NULL, attr, &refNs, &ref);
7626 if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7627 return(NULL);
7628
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007629 /*
7630 * Check for illegal attributes.
7631 */
7632 attr = node->properties;
7633 while (attr != NULL) {
7634 if (attr->ns == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007635 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007636 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007637 {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007638 xmlSchemaPIllegalAttrErr(pctxt,
7639 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007640 }
7641 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007642 xmlSchemaPIllegalAttrErr(pctxt,
7643 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007644 }
7645 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007646 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00007647 /* Attribute ID */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007648 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7649
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007650 /*
7651 * And now for the children...
7652 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007653 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00007654 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007655 /*
7656 * TODO: We do not have a place to store the annotation, do we?
7657 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007658 xmlSchemaParseAnnotation(pctxt, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007659 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007660 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007661 if (child != NULL) {
7662 xmlSchemaPContentErr(pctxt,
7663 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7664 NULL, node, child, NULL,
7665 "(annotation?)");
7666 }
7667
7668 /*
7669 * Handle attribute group redefinitions.
7670 */
7671 if (pctxt->isRedefine && pctxt->redef &&
7672 (pctxt->redef->item->type ==
7673 XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7674 (ref == pctxt->redef->refName) &&
7675 (refNs == pctxt->redef->refTargetNs))
7676 {
7677 /*
7678 * SPEC src-redefine:
7679 * (7.1) "If it has an <attributeGroup> among its contents
7680 * the ·actual value· of whose ref [attribute] is the same
7681 * as the ·actual value· of its own name attribute plus
7682 * target namespace, then it must have exactly one such group."
7683 */
7684 if (pctxt->redefCounter != 0) {
7685 xmlChar *str = NULL;
7686
7687 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7688 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7689 "The redefining attribute group definition "
7690 "'%s' must not contain more than one "
7691 "reference to the redefined definition",
7692 xmlSchemaFormatQName(&str, refNs, ref), NULL);
7693 FREE_AND_NULL(str);
7694 return(NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007695 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007696 pctxt->redefCounter++;
7697 /*
7698 * URGENT TODO: How to ensure that the reference will not be
7699 * handled by the normal component resolution mechanism?
7700 */
7701 ret = xmlSchemaNewQNameRef(pctxt,
7702 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7703 if (ret == NULL)
7704 return(NULL);
7705 ret->node = node;
7706 pctxt->redef->reference = WXS_BASIC_CAST ret;
7707 } else {
7708 /*
7709 * Create a QName-reference helper component. We will substitute this
7710 * component for the attribute uses of the referenced attribute group
7711 * definition.
7712 */
7713 ret = xmlSchemaNewQNameRef(pctxt,
7714 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7715 if (ret == NULL)
7716 return(NULL);
7717 ret->node = node;
7718 /* Add to pending items, to be able to resolve the reference. */
7719 WXS_ADD_PENDING(pctxt, ret);
7720 }
7721 return (ret);
7722}
7723
7724/**
7725 * xmlSchemaParseAttributeGroupDefinition:
7726 * @pctxt: a schema validation context
7727 * @schema: the schema being built
7728 * @node: a subtree containing XML Schema informations
7729 *
7730 * parse a XML schema Attribute Group declaration
7731 * *WARNING* this interface is highly subject to change
7732 *
7733 * Returns the attribute group definition or NULL in case of error.
7734 */
7735static xmlSchemaAttributeGroupPtr
7736xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7737 xmlSchemaPtr schema,
7738 xmlNodePtr node)
7739{
7740 const xmlChar *name;
7741 xmlSchemaAttributeGroupPtr ret;
7742 xmlNodePtr child = NULL;
7743 xmlAttrPtr attr;
7744 int hasRefs = 0;
7745
7746 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7747 return (NULL);
7748
7749 attr = xmlSchemaGetPropNode(node, "name");
7750 if (attr == NULL) {
7751 xmlSchemaPMissingAttrErr(pctxt,
7752 XML_SCHEMAP_S4S_ATTR_MISSING,
7753 NULL, node, "name", NULL);
7754 return (NULL);
7755 }
7756 /*
7757 * The name is crucial, exit if invalid.
7758 */
7759 if (xmlSchemaPValAttrNode(pctxt,
7760 NULL, attr,
7761 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7762 return (NULL);
7763 }
7764 ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7765 name, pctxt->targetNamespace, node);
7766 if (ret == NULL)
7767 return (NULL);
7768 /*
7769 * Check for illegal attributes.
7770 */
7771 attr = node->properties;
7772 while (attr != NULL) {
7773 if (attr->ns == NULL) {
7774 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7775 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7776 {
7777 xmlSchemaPIllegalAttrErr(pctxt,
7778 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7779 }
7780 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7781 xmlSchemaPIllegalAttrErr(pctxt,
7782 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7783 }
7784 attr = attr->next;
7785 }
7786 /* Attribute ID */
7787 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7788 /*
7789 * And now for the children...
7790 */
7791 child = node->children;
7792 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007793 ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007794 child = child->next;
7795 }
7796 /*
7797 * Parse contained attribute decls/refs.
7798 */
7799 if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7800 (xmlSchemaItemListPtr *) &(ret->attrUses),
7801 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7802 return(NULL);
7803 if (hasRefs)
7804 ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7805 /*
7806 * Parse the attribute wildcard.
7807 */
7808 if (IS_SCHEMA(child, "anyAttribute")) {
7809 ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7810 schema, child);
7811 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007812 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007813 if (child != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007814 xmlSchemaPContentErr(pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007815 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007816 NULL, node, child, NULL,
7817 "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007818 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007819 return (ret);
7820}
7821
7822/**
William M. Brack2f2a6632004-08-20 23:09:47 +00007823 * xmlSchemaPValAttrFormDefault:
7824 * @value: the value
7825 * @flags: the flags to be modified
7826 * @flagQualified: the specific flag for "qualified"
7827 *
7828 * Returns 0 if the value is valid, 1 otherwise.
7829 */
7830static int
7831xmlSchemaPValAttrFormDefault(const xmlChar *value,
7832 int *flags,
7833 int flagQualified)
7834{
7835 if (xmlStrEqual(value, BAD_CAST "qualified")) {
7836 if ((*flags & flagQualified) == 0)
7837 *flags |= flagQualified;
7838 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007839 return (1);
7840
William M. Brack2f2a6632004-08-20 23:09:47 +00007841 return (0);
7842}
7843
7844/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00007845 * xmlSchemaPValAttrBlockFinal:
7846 * @value: the value
7847 * @flags: the flags to be modified
7848 * @flagAll: the specific flag for "#all"
7849 * @flagExtension: the specific flag for "extension"
7850 * @flagRestriction: the specific flag for "restriction"
7851 * @flagSubstitution: the specific flag for "substitution"
7852 * @flagList: the specific flag for "list"
7853 * @flagUnion: the specific flag for "union"
7854 *
7855 * Validates the value of the attribute "final" and "block". The value
7856 * is converted into the specified flag values and returned in @flags.
7857 *
7858 * Returns 0 if the value is valid, 1 otherwise.
7859 */
7860
7861static int
7862xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007863 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007864 int flagAll,
7865 int flagExtension,
7866 int flagRestriction,
7867 int flagSubstitution,
7868 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007869 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007870{
7871 int ret = 0;
7872
7873 /*
7874 * TODO: This does not check for dublicate entries.
7875 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007876 if ((flags == NULL) || (value == NULL))
7877 return (-1);
7878 if (value[0] == 0)
7879 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007880 if (xmlStrEqual(value, BAD_CAST "#all")) {
7881 if (flagAll != -1)
7882 *flags |= flagAll;
7883 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007884 if (flagExtension != -1)
7885 *flags |= flagExtension;
7886 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007887 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007888 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007889 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007890 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007891 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007892 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007893 *flags |= flagUnion;
7894 }
7895 } else {
7896 const xmlChar *end, *cur = value;
7897 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007898
Daniel Veillardc0826a72004-08-10 14:17:33 +00007899 do {
7900 while (IS_BLANK_CH(*cur))
7901 cur++;
7902 end = cur;
7903 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7904 end++;
7905 if (end == cur)
7906 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007907 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007908 if (xmlStrEqual(item, BAD_CAST "extension")) {
7909 if (flagExtension != -1) {
7910 if ((*flags & flagExtension) == 0)
7911 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007912 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007913 ret = 1;
7914 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7915 if (flagRestriction != -1) {
7916 if ((*flags & flagRestriction) == 0)
7917 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007918 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007919 ret = 1;
7920 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7921 if (flagSubstitution != -1) {
7922 if ((*flags & flagSubstitution) == 0)
7923 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007924 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007925 ret = 1;
7926 } else if (xmlStrEqual(item, BAD_CAST "list")) {
7927 if (flagList != -1) {
7928 if ((*flags & flagList) == 0)
7929 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007930 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007931 ret = 1;
7932 } else if (xmlStrEqual(item, BAD_CAST "union")) {
7933 if (flagUnion != -1) {
7934 if ((*flags & flagUnion) == 0)
7935 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007936 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007937 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007938 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007939 ret = 1;
7940 if (item != NULL)
7941 xmlFree(item);
7942 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007943 } while ((ret == 0) && (*cur != 0));
7944 }
7945
Daniel Veillardc0826a72004-08-10 14:17:33 +00007946 return (ret);
7947}
7948
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007949static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007950xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007951 xmlSchemaIDCPtr idc,
7952 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007953 xmlAttrPtr attr,
7954 int isField)
7955{
7956 xmlNodePtr node;
7957
7958 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007959 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007960 * Schema Component Constraint: Selector Value OK
7961 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007962 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007963 * in [XPath].
7964 */
7965 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007966 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007967 XML_SCHEMAP_INTERNAL,
7968 "Internal error: xmlSchemaCheckCSelectorXPath, "
7969 "the selector is not specified.\n", NULL, NULL);
7970 return (-1);
7971 }
7972 if (attr == NULL)
7973 node = idc->node;
7974 else
7975 node = (xmlNodePtr) attr;
7976 if (selector->xpath == NULL) {
7977 xmlSchemaPCustomErr(ctxt,
7978 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007979 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007980 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007981 "The XPath expression of the selector is not valid", NULL);
7982 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
7983 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007984 const xmlChar **nsArray = NULL;
7985 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007986 /*
7987 * Compile the XPath expression.
7988 */
7989 /*
7990 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007991 * TODO: Call xmlPatterncompile with different options for selector/
7992 * field.
7993 */
7994 nsList = xmlGetNsList(attr->doc, attr->parent);
7995 /*
7996 * Build an array of prefixes and namespaces.
7997 */
7998 if (nsList != NULL) {
7999 int i, count = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008000
8001 for (i = 0; nsList[i] != NULL; i++)
8002 count++;
8003
8004 nsArray = (const xmlChar **) xmlMalloc(
8005 (count * 2 + 1) * sizeof(const xmlChar *));
8006 if (nsArray == NULL) {
8007 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8008 NULL);
Kasimier T. Buchcik940ab0c2005-10-19 17:00:53 +00008009 xmlFree(nsList);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008010 return (-1);
8011 }
8012 for (i = 0; i < count; i++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008013 nsArray[2 * i] = nsList[i]->href;
8014 nsArray[2 * i + 1] = nsList[i]->prefix;
8015 }
8016 nsArray[count * 2] = NULL;
8017 xmlFree(nsList);
8018 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008019 /*
8020 * TODO: Differentiate between "selector" and "field".
8021 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008022 if (isField)
8023 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008024 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008025 else
8026 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008027 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008028 if (nsArray != NULL)
8029 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008030
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00008031 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008032 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00008033 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008034 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008035 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008036 "The XPath expression '%s' could not be "
8037 "compiled", selector->xpath);
8038 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008039 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008040 }
8041 return (0);
8042}
8043
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008044#define ADD_ANNOTATION(annot) \
8045 xmlSchemaAnnotPtr cur = item->annot; \
8046 if (item->annot == NULL) { \
8047 item->annot = annot; \
8048 return (annot); \
8049 } \
8050 cur = item->annot; \
8051 if (cur->next != NULL) { \
8052 cur = cur->next; \
8053 } \
8054 cur->next = annot;
8055
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008056/**
8057 * xmlSchemaAssignAnnotation:
8058 * @item: the schema component
8059 * @annot: the annotation
8060 *
8061 * Adds the annotation to the given schema component.
8062 *
8063 * Returns the given annotaion.
8064 */
8065static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008066xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8067 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008068{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008069 if ((annItem == NULL) || (annot == NULL))
8070 return (NULL);
8071 switch (annItem->type) {
8072 case XML_SCHEMA_TYPE_ELEMENT: {
8073 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8074 ADD_ANNOTATION(annot)
8075 }
8076 break;
8077 case XML_SCHEMA_TYPE_ATTRIBUTE: {
8078 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8079 ADD_ANNOTATION(annot)
8080 }
8081 break;
8082 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8083 case XML_SCHEMA_TYPE_ANY: {
8084 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8085 ADD_ANNOTATION(annot)
8086 }
8087 break;
8088 case XML_SCHEMA_TYPE_PARTICLE:
8089 case XML_SCHEMA_TYPE_IDC_KEY:
8090 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008091 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008092 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8093 ADD_ANNOTATION(annot)
8094 }
8095 break;
8096 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8097 xmlSchemaAttributeGroupPtr item =
8098 (xmlSchemaAttributeGroupPtr) annItem;
8099 ADD_ANNOTATION(annot)
8100 }
8101 break;
8102 case XML_SCHEMA_TYPE_NOTATION: {
8103 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8104 ADD_ANNOTATION(annot)
8105 }
8106 break;
8107 case XML_SCHEMA_FACET_MININCLUSIVE:
8108 case XML_SCHEMA_FACET_MINEXCLUSIVE:
8109 case XML_SCHEMA_FACET_MAXINCLUSIVE:
8110 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8111 case XML_SCHEMA_FACET_TOTALDIGITS:
8112 case XML_SCHEMA_FACET_FRACTIONDIGITS:
8113 case XML_SCHEMA_FACET_PATTERN:
8114 case XML_SCHEMA_FACET_ENUMERATION:
8115 case XML_SCHEMA_FACET_WHITESPACE:
8116 case XML_SCHEMA_FACET_LENGTH:
8117 case XML_SCHEMA_FACET_MAXLENGTH:
8118 case XML_SCHEMA_FACET_MINLENGTH: {
8119 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8120 ADD_ANNOTATION(annot)
8121 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008122 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008123 case XML_SCHEMA_TYPE_SIMPLE:
8124 case XML_SCHEMA_TYPE_COMPLEX: {
8125 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8126 ADD_ANNOTATION(annot)
8127 }
8128 break;
8129 case XML_SCHEMA_TYPE_GROUP: {
8130 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8131 ADD_ANNOTATION(annot)
8132 }
8133 break;
8134 case XML_SCHEMA_TYPE_SEQUENCE:
8135 case XML_SCHEMA_TYPE_CHOICE:
8136 case XML_SCHEMA_TYPE_ALL: {
8137 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8138 ADD_ANNOTATION(annot)
8139 }
8140 break;
8141 default:
8142 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008143 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008144 NULL, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008145 "Internal error: xmlSchemaAddAnnotation, "
8146 "The item is not a annotated schema component", NULL);
8147 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008148 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008149 return (annot);
8150}
8151
8152/**
8153 * xmlSchemaParseIDCSelectorAndField:
8154 * @ctxt: a schema validation context
8155 * @schema: the schema being built
8156 * @node: a subtree containing XML Schema informations
8157 *
8158 * Parses a XML Schema identity-contraint definition's
8159 * <selector> and <field> elements.
8160 *
8161 * Returns the parsed identity-constraint definition.
8162 */
8163static xmlSchemaIDCSelectPtr
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008164xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008165 xmlSchemaIDCPtr idc,
8166 xmlNodePtr node,
8167 int isField)
8168{
8169 xmlSchemaIDCSelectPtr item;
8170 xmlNodePtr child = NULL;
8171 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008172
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008173 /*
8174 * Check for illegal attributes.
8175 */
8176 attr = node->properties;
8177 while (attr != NULL) {
8178 if (attr->ns == NULL) {
8179 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8180 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008181 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008182 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008183 }
8184 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008185 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008186 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008187 }
8188 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008189 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008190 /*
8191 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008192 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008193 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8194 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008195 xmlSchemaPErrMemory(ctxt,
8196 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008197 NULL);
8198 return (NULL);
8199 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008200 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008201 /*
8202 * Attribute "xpath" (mandatory).
8203 */
8204 attr = xmlSchemaGetPropNode(node, "xpath");
8205 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008206 xmlSchemaPMissingAttrErr(ctxt,
8207 XML_SCHEMAP_S4S_ATTR_MISSING,
8208 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008209 "name", NULL);
8210 } else {
8211 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8212 /*
8213 * URGENT TODO: "field"s have an other syntax than "selector"s.
8214 */
8215
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008216 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8217 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008218 xmlSchemaPErr(ctxt,
8219 (xmlNodePtr) attr,
8220 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008221 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008222 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008223 NULL, NULL);
8224 }
8225
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008226 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008227 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008228 /*
8229 * And now for the children...
8230 */
8231 child = node->children;
8232 if (IS_SCHEMA(child, "annotation")) {
8233 /*
8234 * Add the annotation to the parent IDC.
8235 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008236 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008237 xmlSchemaParseAnnotation(ctxt, child, 1));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008238 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008239 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008240 if (child != NULL) {
8241 xmlSchemaPContentErr(ctxt,
8242 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008243 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008244 NULL, "(annotation?)");
8245 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008246
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008247 return (item);
8248}
8249
8250/**
8251 * xmlSchemaParseIDC:
8252 * @ctxt: a schema validation context
8253 * @schema: the schema being built
8254 * @node: a subtree containing XML Schema informations
8255 *
8256 * Parses a XML Schema identity-contraint definition.
8257 *
8258 * Returns the parsed identity-constraint definition.
8259 */
8260static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008261xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008262 xmlSchemaPtr schema,
8263 xmlNodePtr node,
8264 xmlSchemaTypeType idcCategory,
8265 const xmlChar *targetNamespace)
8266{
8267 xmlSchemaIDCPtr item = NULL;
8268 xmlNodePtr child = NULL;
8269 xmlAttrPtr attr;
8270 const xmlChar *name = NULL;
8271 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008272
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008273 /*
8274 * Check for illegal attributes.
8275 */
8276 attr = node->properties;
8277 while (attr != NULL) {
8278 if (attr->ns == NULL) {
8279 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8280 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8281 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8282 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008283 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008284 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008285 }
8286 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008287 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008288 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008289 }
8290 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008291 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008292 /*
8293 * Attribute "name" (mandatory).
8294 */
8295 attr = xmlSchemaGetPropNode(node, "name");
8296 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008297 xmlSchemaPMissingAttrErr(ctxt,
8298 XML_SCHEMAP_S4S_ATTR_MISSING,
8299 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008300 "name", NULL);
8301 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008302 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008303 NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008304 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8305 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008306 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008307 /* Create the component. */
8308 item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8309 idcCategory, node);
8310 if (item == NULL)
8311 return(NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008312
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008313 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008314 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8315 /*
8316 * Attribute "refer" (mandatory).
8317 */
8318 attr = xmlSchemaGetPropNode(node, "refer");
8319 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008320 xmlSchemaPMissingAttrErr(ctxt,
8321 XML_SCHEMAP_S4S_ATTR_MISSING,
8322 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008323 "refer", NULL);
8324 } else {
8325 /*
8326 * Create a reference item.
8327 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008328 item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008329 NULL, NULL);
8330 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008331 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008332 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008333 NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008334 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008335 &(item->ref->name));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008336 xmlSchemaCheckReference(ctxt, schema, node, attr,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008337 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008338 }
8339 }
8340 /*
8341 * And now for the children...
8342 */
8343 child = node->children;
8344 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008345 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008346 child = child->next;
8347 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00008348 if (child == NULL) {
8349 xmlSchemaPContentErr(ctxt,
8350 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008351 NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00008352 "A child element is missing",
8353 "(annotation?, (selector, field+))");
8354 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008355 /*
8356 * Child element <selector>.
8357 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008358 if (IS_SCHEMA(child, "selector")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008359 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008360 item, child, 0);
8361 child = child->next;
8362 /*
8363 * Child elements <field>.
8364 */
8365 if (IS_SCHEMA(child, "field")) {
8366 do {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008367 field = xmlSchemaParseIDCSelectorAndField(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008368 item, child, 1);
8369 if (field != NULL) {
8370 field->index = item->nbFields;
8371 item->nbFields++;
8372 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008373 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008374 else
8375 item->fields = field;
8376 lastField = field;
8377 }
8378 child = child->next;
8379 } while (IS_SCHEMA(child, "field"));
8380 } else {
8381 xmlSchemaPContentErr(ctxt,
8382 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008383 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008384 NULL, "(annotation?, (selector, field+))");
8385 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008386 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008387 if (child != NULL) {
8388 xmlSchemaPContentErr(ctxt,
8389 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008390 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008391 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008392 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008393
8394 return (item);
8395}
8396
Daniel Veillardc0826a72004-08-10 14:17:33 +00008397/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008398 * xmlSchemaParseElement:
8399 * @ctxt: a schema validation context
8400 * @schema: the schema being built
8401 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008402 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00008403 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008404 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00008405 * *WARNING* this interface is highly subject to change
8406 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008407 * Returns the element declaration or a particle; NULL in case
8408 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00008409 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008410static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00008411xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008412 xmlNodePtr node, int *isElemRef, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008413{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008414 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008415 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008416 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008417 xmlNodePtr child = NULL;
8418 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008419 int min, max, isRef = 0;
8420 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00008421
8422 /* 3.3.3 Constraints on XML Representations of Element Declarations */
8423 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008424
Daniel Veillard4255d502002-04-16 15:50:10 +00008425 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008426 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008427
8428 if (isElemRef != NULL)
8429 *isElemRef = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008430 /*
8431 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008432 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008433 * robust.
8434 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008435 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008436 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008437 if ((topLevel) || (attr == NULL)) {
8438 if (nameAttr == NULL) {
8439 xmlSchemaPMissingAttrErr(ctxt,
8440 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008441 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008442 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008443 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008444 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00008445 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008446
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008447 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008448 child = node->children;
8449 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008450 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008451 child = child->next;
8452 }
8453 /*
8454 * Skip particle part if a global declaration.
8455 */
8456 if (topLevel)
8457 goto declaration_part;
8458 /*
8459 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008460 */
8461 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8462 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8463 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008464 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8465 if (particle == NULL)
8466 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008467
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008468 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8469
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008470 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008471 const xmlChar *refNs = NULL, *ref = NULL;
8472 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008473 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008474 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00008475 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008476 if (isElemRef != NULL)
8477 *isElemRef = 1;
8478
Daniel Veillardc0826a72004-08-10 14:17:33 +00008479 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008480 NULL, attr, &refNs, &ref);
8481 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008482 /*
8483 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00008484 */
8485 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008486 xmlSchemaPMutualExclAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008487 XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008488 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008489 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008490 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008491 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008492 attr = node->properties;
8493 while (attr != NULL) {
8494 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008495 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8496 xmlStrEqual(attr->name, BAD_CAST "name") ||
8497 xmlStrEqual(attr->name, BAD_CAST "id") ||
8498 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8499 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8500 {
8501 attr = attr->next;
8502 continue;
8503 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008504 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008505 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008506 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008507 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008508 "Only the attributes 'minOccurs', 'maxOccurs' and "
8509 "'id' are allowed in addition to 'ref'");
8510 break;
8511 }
8512 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8513 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008514 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008515 }
8516 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008517 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008518 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008519 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008520 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008521 if (child != NULL) {
8522 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008523 NULL, node, child, NULL, "(annotation?)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008524 }
8525 if ((min == 0) && (max == 0))
8526 goto return_null;
8527 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008528 * Create the reference item and attach it to the particle.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008529 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008530 refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008531 ref, refNs);
8532 if (refer == NULL)
8533 goto return_null;
8534 particle->children = (xmlSchemaTreeItemPtr) refer;
8535 particle->annot = annot;
8536 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008537 * Add the particle to pending components, since the reference
8538 * need to be resolved.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008539 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008540 WXS_ADD_PENDING(ctxt, particle);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008541 return ((xmlSchemaBasicItemPtr) particle);
8542 }
8543 /*
8544 * The declaration part ===============================================
8545 */
8546declaration_part:
8547 {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008548 const xmlChar *ns = NULL, *fixed, *name, *attrValue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008549 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8550
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008551 if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008552 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008553 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008554 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008555 * Evaluate the target namespace.
8556 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008557 if (topLevel) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008558 ns = ctxt->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008559 } else {
8560 attr = xmlSchemaGetPropNode(node, "form");
8561 if (attr != NULL) {
8562 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8563 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008564 ns = ctxt->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008565 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008566 xmlSchemaPSimpleTypeErr(ctxt,
8567 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8568 NULL, (xmlNodePtr) attr,
8569 NULL, "(qualified | unqualified)",
8570 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008571 }
8572 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008573 ns = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008574 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008575 decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008576 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008577 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00008578 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008579 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008580 * Check for illegal attributes.
8581 */
William M. Bracke7091952004-05-11 15:09:58 +00008582 attr = node->properties;
8583 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008584 if (attr->ns == NULL) {
8585 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8586 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008587 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008588 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008589 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008590 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008591 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8592 {
8593 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008594 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008595 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008596 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008597 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008598 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008599 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008600 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008601 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8602 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008603 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8604
8605 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008606 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008607 }
8608 }
8609 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008610
Daniel Veillardc0826a72004-08-10 14:17:33 +00008611 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008612 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Bracke7091952004-05-11 15:09:58 +00008613 }
8614 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008615 }
William M. Bracke7091952004-05-11 15:09:58 +00008616 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008617 * Extract/validate attributes.
8618 */
8619 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008620 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008621 * Process top attributes of global element declarations here.
8622 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008623 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8624 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008625 xmlSchemaPValAttrQName(ctxt, schema,
8626 NULL, node, "substitutionGroup",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008627 &(decl->substGroupNs), &(decl->substGroup));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008628 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008629 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008630 /*
8631 * Attribute "final".
8632 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008633 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008634 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008635 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8636 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8637 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8638 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008639 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008640 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8641 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00008642 -1,
8643 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8644 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008645 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008646 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008647 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008648 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008649 attrValue, NULL, NULL, NULL);
8650 }
8651 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008652 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008653 /*
8654 * Attribute "block".
8655 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008656 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008657 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00008658 /*
8659 * Apply default "block" values.
8660 */
8661 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8662 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8663 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8664 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8665 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8666 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008667 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008668 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8669 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00008670 -1,
8671 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008672 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008673 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8674 xmlSchemaPSimpleTypeErr(ctxt,
8675 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008676 NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00008677 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008678 "restriction | substitution))", attrValue,
8679 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008680 }
8681 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008682 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008683 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008684
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008685 attr = xmlSchemaGetPropNode(node, "type");
8686 if (attr != NULL) {
8687 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008688 NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008689 &(decl->namedTypeNs), &(decl->namedType));
8690 xmlSchemaCheckReference(ctxt, schema, node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008691 attr, decl->namedTypeNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008692 }
8693 decl->value = xmlSchemaGetProp(ctxt, node, "default");
8694 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008695 if (attr != NULL) {
8696 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008697 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008698 /*
8699 * 3.3.3 : 1
8700 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008701 */
8702 xmlSchemaPMutualExclAttrErr(ctxt,
8703 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008704 NULL, attr, "default", "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008705 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008706 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8707 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008708 }
William M. Bracke7091952004-05-11 15:09:58 +00008709 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008710 /*
8711 * And now for the children...
8712 */
William M. Bracke7091952004-05-11 15:09:58 +00008713 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008714 /*
8715 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00008716 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008717 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00008718 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008719 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008720 xmlSchemaPContentErr(ctxt,
8721 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008722 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008723 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008724 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008725 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008726 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00008727 child = child->next;
8728 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008729 /*
8730 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00008731 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008732 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00008733 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008734 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008735 xmlSchemaPContentErr(ctxt,
8736 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008737 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008738 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008739 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008740 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008741 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00008742 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008743 }
William M. Bracke7091952004-05-11 15:09:58 +00008744 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00008745 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008746 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008747 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008748 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008749 } else if (IS_SCHEMA(child, "key")) {
8750 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008751 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008752 } else if (IS_SCHEMA(child, "keyref")) {
8753 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008754 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008755 }
8756 if (lastIDC != NULL)
8757 lastIDC->next = curIDC;
8758 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008759 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008760 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008761 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00008762 }
8763 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008764 xmlSchemaPContentErr(ctxt,
8765 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008766 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008767 NULL, "(annotation?, ((simpleType | complexType)?, "
8768 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008769 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008770 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008771 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008772 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008773 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00008774 * different layer.
8775 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008776 FREE_AND_NULL(des)
8777 if (topLevel)
8778 return ((xmlSchemaBasicItemPtr) decl);
8779 else {
8780 particle->children = (xmlSchemaTreeItemPtr) decl;
8781 return ((xmlSchemaBasicItemPtr) particle);
8782 }
8783
8784return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008785 FREE_AND_NULL(des);
8786 if (annot != NULL) {
8787 if (particle != NULL)
8788 particle->annot = NULL;
8789 if (decl != NULL)
8790 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008791 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008792 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008793 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008794}
8795
8796/**
8797 * xmlSchemaParseUnion:
8798 * @ctxt: a schema validation context
8799 * @schema: the schema being built
8800 * @node: a subtree containing XML Schema informations
8801 *
8802 * parse a XML schema Union definition
8803 * *WARNING* this interface is highly subject to change
8804 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008805 * Returns -1 in case of internal error, 0 in case of success and a positive
8806 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00008807 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008808static int
Daniel Veillard4255d502002-04-16 15:50:10 +00008809xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008810 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008811{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008812 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008813 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008814 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008815 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008816
8817 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008818 return (-1);
8819 /* Not a component, don't create it. */
8820 type = ctxt->ctxtType;
8821 /*
8822 * Mark the simple type as being of variety "union".
8823 */
8824 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008825 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008826 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8827 * then the ·simple ur-type definition·."
8828 */
8829 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008830 /*
8831 * Check for illegal attributes.
8832 */
8833 attr = node->properties;
8834 while (attr != NULL) {
8835 if (attr->ns == NULL) {
8836 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8837 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008838 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008839 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008840 }
8841 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008842 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008843 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008844 }
8845 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008846 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008847 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008848 /*
8849 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008850 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00008851 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008852 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008853 if (attr != NULL) {
8854 const xmlChar *end;
8855 xmlChar *tmp;
8856 const xmlChar *localName, *nsName;
8857 xmlSchemaTypeLinkPtr link, lastLink = NULL;
8858 xmlSchemaQNameRefPtr ref;
8859
8860 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008861 type->base = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008862 do {
8863 while (IS_BLANK_CH(*cur))
8864 cur++;
8865 end = cur;
8866 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8867 end++;
8868 if (end == cur)
8869 break;
8870 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008871 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008872 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008873 /*
8874 * Create the member type link.
8875 */
8876 link = (xmlSchemaTypeLinkPtr)
8877 xmlMalloc(sizeof(xmlSchemaTypeLink));
8878 if (link == NULL) {
8879 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8880 "allocating a type link", NULL);
8881 return (-1);
8882 }
8883 link->type = NULL;
8884 link->next = NULL;
8885 if (lastLink == NULL)
8886 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008887 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008888 lastLink->next = link;
8889 lastLink = link;
8890 /*
8891 * Create a reference item.
8892 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008893 ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008894 localName, nsName);
8895 if (ref == NULL) {
8896 FREE_AND_NULL(tmp)
8897 return (-1);
8898 }
8899 /*
8900 * Assign the reference to the link, it will be resolved
8901 * later during fixup of the union simple type.
8902 */
8903 link->type = (xmlSchemaTypePtr) ref;
8904 }
8905 FREE_AND_NULL(tmp)
8906 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008907 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008908
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008909 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008910 /*
8911 * And now for the children...
8912 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008913 child = node->children;
8914 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008915 /*
8916 * Add the annotation to the simple type ancestor.
8917 */
8918 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008919 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008920 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008921 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008922 if (IS_SCHEMA(child, "simpleType")) {
8923 xmlSchemaTypePtr subtype, last = NULL;
8924
8925 /*
8926 * Anchor the member types in the "subtypes" field of the
8927 * simple type.
8928 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008929 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008930 subtype = (xmlSchemaTypePtr)
8931 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8932 if (subtype != NULL) {
8933 if (last == NULL) {
8934 type->subtypes = subtype;
8935 last = subtype;
8936 } else {
8937 last->next = subtype;
8938 last = subtype;
8939 }
8940 last->next = NULL;
8941 }
8942 child = child->next;
8943 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008944 }
8945 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008946 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008947 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008948 NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008949 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008950 if ((attr == NULL) && (type->subtypes == NULL)) {
8951 /*
8952 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008953 * Either the memberTypes [attribute] of the <union> element must
8954 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008955 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008956 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008957 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008958 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008959 "Either the attribute 'memberTypes' or "
8960 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008961 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008962 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00008963}
8964
8965/**
8966 * xmlSchemaParseList:
8967 * @ctxt: a schema validation context
8968 * @schema: the schema being built
8969 * @node: a subtree containing XML Schema informations
8970 *
8971 * parse a XML schema List definition
8972 * *WARNING* this interface is highly subject to change
8973 *
William M. Bracke7091952004-05-11 15:09:58 +00008974 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008975 * 1 in case of success.
8976 */
8977static xmlSchemaTypePtr
8978xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008979 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008980{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008981 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008982 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008983 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008984
8985 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8986 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008987 /* Not a component, don't create it. */
8988 type = ctxt->ctxtType;
8989 /*
8990 * Mark the type as being of variety "list".
8991 */
8992 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008993 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008994 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8995 * then the ·simple ur-type definition·."
8996 */
8997 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008998 /*
8999 * Check for illegal attributes.
9000 */
9001 attr = node->properties;
9002 while (attr != NULL) {
9003 if (attr->ns == NULL) {
9004 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9005 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009006 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009007 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009008 }
9009 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009010 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009011 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009012 }
9013 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009014 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009015
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009016 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009017
William M. Brack2f2a6632004-08-20 23:09:47 +00009018 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009019 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9020 * fields for holding the reference to the itemType.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009021 *
9022 * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9023 * the "ref" fields.
William M. Brack2f2a6632004-08-20 23:09:47 +00009024 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009025 xmlSchemaPValAttrQName(ctxt, schema, NULL,
9026 node, "itemType", &(type->baseNs), &(type->base));
William M. Brack2f2a6632004-08-20 23:09:47 +00009027 /*
9028 * And now for the children...
9029 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009030 child = node->children;
9031 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009032 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009033 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009034 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009035 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009036 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009037 /*
9038 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009039 * Either the itemType [attribute] or the <simpleType> [child] of
9040 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009041 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009042 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009043 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009044 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009045 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00009046 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009047 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009048 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009049 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009050 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009051 child = child->next;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009052 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009053 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009054 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009055 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009056 "Either the attribute 'itemType' or the <simpleType> child "
9057 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009058 }
9059 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009060 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009061 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009062 NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00009063 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009064 if ((type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009065 (type->subtypes == NULL) &&
9066 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009067 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009068 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009069 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009070 "Either the attribute 'itemType' or the <simpleType> child "
9071 "must be present", NULL);
9072 }
9073 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009074}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009075
Daniel Veillard4255d502002-04-16 15:50:10 +00009076/**
9077 * xmlSchemaParseSimpleType:
9078 * @ctxt: a schema validation context
9079 * @schema: the schema being built
9080 * @node: a subtree containing XML Schema informations
9081 *
9082 * parse a XML schema Simple Type definition
9083 * *WARNING* this interface is highly subject to change
9084 *
William M. Bracke7091952004-05-11 15:09:58 +00009085 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00009086 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00009087 */
9088static xmlSchemaTypePtr
9089xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00009090 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00009091{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009092 xmlSchemaTypePtr type, oldCtxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009093 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009094 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009095 xmlAttrPtr attr;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009096 int hasRestriction = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009097
9098 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9099 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009100
Daniel Veillardc0826a72004-08-10 14:17:33 +00009101 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009102 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009103 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009104 xmlSchemaPMissingAttrErr(ctxt,
9105 XML_SCHEMAP_S4S_ATTR_MISSING,
9106 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009107 "name", NULL);
9108 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009109 } else {
9110 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009111 NULL, attr,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009112 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9113 return (NULL);
9114 /*
9115 * Skip built-in types.
9116 */
9117 if (ctxt->isS4S) {
9118 xmlSchemaTypePtr biType;
9119
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009120 if (ctxt->isRedefine) {
9121 /*
9122 * REDEFINE: Disallow redefinition of built-in-types.
9123 * TODO: It seems that the spec does not say anything
9124 * about this case.
9125 */
9126 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009127 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009128 "Redefinition of built-in simple types is not "
9129 "supported", NULL);
9130 return(NULL);
9131 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009132 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9133 if (biType != NULL)
9134 return (biType);
9135 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009136 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009137 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009138 /*
9139 * TargetNamespace:
9140 * SPEC "The ·actual value· of the targetNamespace [attribute]
9141 * of the <schema> ancestor element information item if present,
9142 * otherwise ·absent·.
9143 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009144 if (topLevel == 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009145#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009146 char buf[40];
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009147#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +00009148 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00009149 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009150 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009151#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009152 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009153 type = xmlSchemaAddType(ctxt, schema,
9154 XML_SCHEMA_TYPE_SIMPLE,
9155 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009156 ctxt->targetNamespace, node, 0);
9157#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009158 type = xmlSchemaAddType(ctxt, schema,
9159 XML_SCHEMA_TYPE_SIMPLE,
9160 NULL, ctxt->targetNamespace, node, 0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009161#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +00009162 if (type == NULL)
9163 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009164 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009165 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009166 /*
9167 * Check for illegal attributes.
9168 */
9169 attr = node->properties;
9170 while (attr != NULL) {
9171 if (attr->ns == NULL) {
9172 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009173 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009174 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009175 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009176 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009177 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009178 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009179 }
9180 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009181 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009182 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009183 /*
9184 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009185 *
9186 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009187 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009188 type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9189 attrValue, ctxt->targetNamespace, node, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009190 if (type == NULL)
9191 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009192 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009193 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009194 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9195 /*
9196 * Check for illegal attributes.
9197 */
9198 attr = node->properties;
9199 while (attr != NULL) {
9200 if (attr->ns == NULL) {
9201 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9202 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009203 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009204 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009205 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009206 }
9207 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009208 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009209 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009210 }
9211 attr = attr->next;
9212 }
9213 /*
9214 * Attribute "final".
9215 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009216 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009217 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009218 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9219 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9220 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9221 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9222 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9223 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009224 } else {
9225 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009226 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9227 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009228 XML_SCHEMAS_TYPE_FINAL_LIST,
9229 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9230
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009231 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009232 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009233 WXS_BASIC_CAST type, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009234 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00009235 attrValue, NULL, NULL, NULL);
9236 }
9237 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009238 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009239 type->targetNamespace = ctxt->targetNamespace;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009240 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009241 /*
9242 * And now for the children...
9243 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009244 oldCtxtType = ctxt->ctxtType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009245
Daniel Veillardc0826a72004-08-10 14:17:33 +00009246 ctxt->ctxtType = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009247
Daniel Veillard4255d502002-04-16 15:50:10 +00009248 child = node->children;
9249 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009250 type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009251 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009252 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009253 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009254 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009255 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009256 "(annotation?, (restriction | list | union))");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009257 } else if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009258 xmlSchemaParseRestriction(ctxt, schema, child,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009259 XML_SCHEMA_TYPE_SIMPLE);
9260 hasRestriction = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009261 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009262 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009263 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009264 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009265 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009266 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009267 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009268 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009269 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009270 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009271 NULL, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009272 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00009273 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009274 /*
9275 * REDEFINE: SPEC src-redefine (5)
9276 * "Within the [children], each <simpleType> must have a
9277 * <restriction> among its [children] ... the ·actual value· of whose
9278 * base [attribute] must be the same as the ·actual value· of its own
9279 * name attribute plus target namespace;"
9280 */
9281 if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9282 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009283 NULL, node, "This is a redefinition, thus the "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009284 "<simpleType> must have a <restriction> child", NULL);
9285 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009286
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009287 ctxt->ctxtType = oldCtxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009288 return (type);
9289}
9290
Daniel Veillard4255d502002-04-16 15:50:10 +00009291/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009292 * xmlSchemaParseModelGroupDefRef:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009293 * @ctxt: the parser context
9294 * @schema: the schema being built
9295 * @node: the node
Daniel Veillard4255d502002-04-16 15:50:10 +00009296 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009297 * Parses a reference to a model group definition.
Daniel Veillard4255d502002-04-16 15:50:10 +00009298 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009299 * We will return a particle component with a qname-component or
9300 * NULL in case of an error.
Daniel Veillard4255d502002-04-16 15:50:10 +00009301 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009302static xmlSchemaTreeItemPtr
9303xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9304 xmlSchemaPtr schema,
9305 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00009306{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009307 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009308 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009309 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009310 const xmlChar *ref = NULL, *refNs = NULL;
9311 int min, max;
9312
9313 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009314 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009315
9316 attr = xmlSchemaGetPropNode(node, "ref");
9317 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009318 xmlSchemaPMissingAttrErr(ctxt,
9319 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009320 NULL, node, "ref", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009321 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009322 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009323 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009324 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009325 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009326 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009327 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009328 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009329 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009330 /*
9331 * Check for illegal attributes.
9332 */
9333 attr = node->properties;
9334 while (attr != NULL) {
9335 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009336 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009337 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9338 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9339 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009340 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009341 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009342 }
9343 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009344 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009345 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009346 }
9347 attr = attr->next;
9348 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009349 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009350 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
9351 if (item == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009352 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009353 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009354 * Create a qname-reference and set as the term; it will be substituted
9355 * for the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009356 */
9357 item->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009358 xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009359 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9360 /*
9361 * And now for the children...
9362 */
9363 child = node->children;
9364 /* TODO: Is annotation even allowed for a model group reference? */
9365 if (IS_SCHEMA(child, "annotation")) {
9366 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009367 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009368 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009369 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009370 child = child->next;
9371 }
9372 if (child != NULL) {
9373 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009374 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009375 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009376 "(annotation?)");
9377 }
9378 /*
9379 * Corresponds to no component at all if minOccurs==maxOccurs==0.
9380 */
9381 if ((min == 0) && (max == 0))
9382 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009383
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009384 return ((xmlSchemaTreeItemPtr) item);
9385}
9386
9387/**
9388 * xmlSchemaParseModelGroupDefinition:
9389 * @ctxt: a schema validation context
9390 * @schema: the schema being built
9391 * @node: a subtree containing XML Schema informations
9392 *
9393 * Parses a XML schema model group definition.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009394 *
9395 * Note that the contraint src-redefine (6.2) can't be applied until
9396 * references have been resolved. So we will do this at the
9397 * component fixup level.
9398 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009399 * *WARNING* this interface is highly subject to change
9400 *
9401 * Returns -1 in case of error, 0 if the declaration is improper and
9402 * 1 in case of success.
9403 */
9404static xmlSchemaModelGroupDefPtr
9405xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9406 xmlSchemaPtr schema,
9407 xmlNodePtr node)
9408{
9409 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009410 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009411 xmlAttrPtr attr;
9412 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00009413
9414 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009415 return (NULL);
9416
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009417 attr = xmlSchemaGetPropNode(node, "name");
9418 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009419 xmlSchemaPMissingAttrErr(ctxt,
9420 XML_SCHEMAP_S4S_ATTR_MISSING,
9421 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009422 "name", NULL);
9423 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009424 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009425 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9426 return (NULL);
9427 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009428 item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9429 ctxt->targetNamespace, node);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009430 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009431 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009432 /*
9433 * Check for illegal attributes.
9434 */
9435 attr = node->properties;
9436 while (attr != NULL) {
9437 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009438 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009439 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009440 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009441 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009442 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009443 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009444 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009445 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009446 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009447 attr = attr->next;
9448 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009449 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009450 /*
9451 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009452 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009453 child = node->children;
9454 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009455 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009456 child = child->next;
9457 }
9458 if (IS_SCHEMA(child, "all")) {
9459 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9460 XML_SCHEMA_TYPE_ALL, 0);
9461 child = child->next;
9462 } else if (IS_SCHEMA(child, "choice")) {
9463 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9464 XML_SCHEMA_TYPE_CHOICE, 0);
9465 child = child->next;
9466 } else if (IS_SCHEMA(child, "sequence")) {
9467 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9468 XML_SCHEMA_TYPE_SEQUENCE, 0);
9469 child = child->next;
9470 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009471
9472
9473
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009474 if (child != NULL) {
9475 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009476 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009477 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009478 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009479 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009480 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009481}
9482
9483/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009484 * xmlSchemaCleanupDoc:
9485 * @ctxt: a schema validation context
9486 * @node: the root of the document.
9487 *
9488 * removes unwanted nodes in a schemas document tree
9489 */
9490static void
9491xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9492{
9493 xmlNodePtr delete, cur;
9494
9495 if ((ctxt == NULL) || (root == NULL)) return;
9496
9497 /*
9498 * Remove all the blank text nodes
9499 */
9500 delete = NULL;
9501 cur = root;
9502 while (cur != NULL) {
9503 if (delete != NULL) {
9504 xmlUnlinkNode(delete);
9505 xmlFreeNode(delete);
9506 delete = NULL;
9507 }
9508 if (cur->type == XML_TEXT_NODE) {
9509 if (IS_BLANK_NODE(cur)) {
9510 if (xmlNodeGetSpacePreserve(cur) != 1) {
9511 delete = cur;
9512 }
9513 }
9514 } else if ((cur->type != XML_ELEMENT_NODE) &&
9515 (cur->type != XML_CDATA_SECTION_NODE)) {
9516 delete = cur;
9517 goto skip_children;
9518 }
9519
9520 /*
9521 * Skip to next node
9522 */
9523 if (cur->children != NULL) {
9524 if ((cur->children->type != XML_ENTITY_DECL) &&
9525 (cur->children->type != XML_ENTITY_REF_NODE) &&
9526 (cur->children->type != XML_ENTITY_NODE)) {
9527 cur = cur->children;
9528 continue;
9529 }
9530 }
9531 skip_children:
9532 if (cur->next != NULL) {
9533 cur = cur->next;
9534 continue;
9535 }
9536
9537 do {
9538 cur = cur->parent;
9539 if (cur == NULL)
9540 break;
9541 if (cur == root) {
9542 cur = NULL;
9543 break;
9544 }
9545 if (cur->next != NULL) {
9546 cur = cur->next;
9547 break;
9548 }
9549 } while (cur != NULL);
9550 }
9551 if (delete != NULL) {
9552 xmlUnlinkNode(delete);
9553 xmlFreeNode(delete);
9554 delete = NULL;
9555 }
9556}
9557
William M. Brack2f2a6632004-08-20 23:09:47 +00009558
William M. Brack2f2a6632004-08-20 23:09:47 +00009559static void
9560xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9561{
9562 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9563 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9564
9565 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9566 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9567
9568 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9569 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9570 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9571 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9572 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9573 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9574 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9575 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9576
9577 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9578 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9579 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9580 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9581 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9582 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9583}
9584
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009585static int
9586xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009587 xmlSchemaPtr schema,
9588 xmlNodePtr node)
9589{
9590 xmlAttrPtr attr;
9591 const xmlChar *val;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009592 int res = 0, oldErrs = ctxt->nberrors;
William M. Brack2f2a6632004-08-20 23:09:47 +00009593
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009594 /*
9595 * Those flags should be moved to the parser context flags,
9596 * since they are not visible at the component level. I.e.
9597 * they are used if processing schema *documents* only.
9598 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009599 res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009600 HFAILURE;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009601
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009602 /*
9603 * Since the version is of type xs:token, we won't bother to
9604 * check it.
9605 */
9606 /* REMOVED:
9607 attr = xmlSchemaGetPropNode(node, "version");
9608 if (attr != NULL) {
9609 res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9610 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9611 HFAILURE;
9612 }
9613 */
9614 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9615 if (attr != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009616 res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009617 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9618 HFAILURE;
9619 if (res != 0) {
9620 ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9621 goto exit;
9622 }
9623 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009624 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009625 if (attr != NULL) {
9626 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009627 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9628 XML_SCHEMAS_QUALIF_ELEM);
9629 HFAILURE;
9630 if (res != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009631 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009632 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009633 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009634 "(qualified | unqualified)", val, NULL, NULL, NULL);
9635 }
9636 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009637 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009638 if (attr != NULL) {
9639 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009640 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9641 XML_SCHEMAS_QUALIF_ATTR);
9642 HFAILURE;
9643 if (res != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009644 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009645 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009646 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009647 "(qualified | unqualified)", val, NULL, NULL, NULL);
9648 }
9649 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009650 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009651 if (attr != NULL) {
9652 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009653 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
William M. Brack2f2a6632004-08-20 23:09:47 +00009654 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9655 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9656 -1,
9657 XML_SCHEMAS_FINAL_DEFAULT_LIST,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009658 XML_SCHEMAS_FINAL_DEFAULT_UNION);
9659 HFAILURE;
9660 if (res != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009661 xmlSchemaPSimpleTypeErr(ctxt,
9662 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009663 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009664 "(#all | List of (extension | restriction | list | union))",
9665 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009666 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009667 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009668 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009669 if (attr != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009670 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9671 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
William M. Brack2f2a6632004-08-20 23:09:47 +00009672 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9673 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009674 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9675 HFAILURE;
9676 if (res != 0) {
9677 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009678 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009679 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009680 "(#all | List of (extension | restriction | substitution))",
9681 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009682 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009683 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009684
9685exit:
9686 if (oldErrs != ctxt->nberrors)
9687 res = ctxt->err;
9688 return(res);
9689exit_failure:
9690 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009691}
9692
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009693/**
9694 * xmlSchemaParseSchemaTopLevel:
9695 * @ctxt: a schema validation context
9696 * @schema: the schemas
9697 * @nodes: the list of top level nodes
9698 *
9699 * Returns the internal XML Schema structure built from the resource or
9700 * NULL in case of error
9701 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009702static int
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009703xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9704 xmlSchemaPtr schema, xmlNodePtr nodes)
9705{
9706 xmlNodePtr child;
9707 xmlSchemaAnnotPtr annot;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009708 int res = 0, oldErrs, tmpOldErrs;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009709
9710 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009711 return(-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009712
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009713 oldErrs = ctxt->nberrors;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009714 child = nodes;
9715 while ((IS_SCHEMA(child, "include")) ||
9716 (IS_SCHEMA(child, "import")) ||
9717 (IS_SCHEMA(child, "redefine")) ||
9718 (IS_SCHEMA(child, "annotation"))) {
9719 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009720 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009721 if (schema->annot == NULL)
9722 schema->annot = annot;
9723 else
9724 xmlSchemaFreeAnnot(annot);
9725 } else if (IS_SCHEMA(child, "import")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009726 tmpOldErrs = ctxt->nberrors;
9727 res = xmlSchemaParseImport(ctxt, schema, child);
9728 HFAILURE;
9729 HSTOP(ctxt);
9730 if (tmpOldErrs != ctxt->nberrors)
9731 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009732 } else if (IS_SCHEMA(child, "include")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009733 tmpOldErrs = ctxt->nberrors;
9734 res = xmlSchemaParseInclude(ctxt, schema, child);
9735 HFAILURE;
9736 HSTOP(ctxt);
9737 if (tmpOldErrs != ctxt->nberrors)
9738 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009739 } else if (IS_SCHEMA(child, "redefine")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009740 tmpOldErrs = ctxt->nberrors;
9741 res = xmlSchemaParseRedefine(ctxt, schema, child);
9742 HFAILURE;
9743 HSTOP(ctxt);
9744 if (tmpOldErrs != ctxt->nberrors)
9745 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009746 }
9747 child = child->next;
9748 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009749 /*
9750 * URGENT TODO: Change the functions to return int results.
9751 * We need especially to catch internal errors.
9752 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009753 while (child != NULL) {
9754 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009755 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009756 child = child->next;
9757 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009758 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009759 child = child->next;
9760 } else if (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009761 xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009762 child = child->next;
9763 } else if (IS_SCHEMA(child, "attribute")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009764 xmlSchemaParseGlobalAttribute(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009765 child = child->next;
9766 } else if (IS_SCHEMA(child, "attributeGroup")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009767 xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009768 child = child->next;
9769 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009770 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009771 child = child->next;
9772 } else if (IS_SCHEMA(child, "notation")) {
9773 xmlSchemaParseNotation(ctxt, schema, child);
9774 child = child->next;
9775 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009776 xmlSchemaPContentErr(ctxt,
9777 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009778 NULL, child->parent, child,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009779 NULL, "((include | import | redefine | annotation)*, "
9780 "(((simpleType | complexType | group | attributeGroup) "
9781 "| element | attribute | notation), annotation*)*)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009782 child = child->next;
9783 }
9784 while (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009785 /*
9786 * TODO: We should add all annotations.
9787 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009788 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009789 if (schema->annot == NULL)
9790 schema->annot = annot;
9791 else
9792 xmlSchemaFreeAnnot(annot);
9793 child = child->next;
9794 }
9795 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009796exit:
Daniel Veillard01fa6152004-06-29 17:04:39 +00009797 ctxt->ctxtType = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009798 if (oldErrs != ctxt->nberrors)
9799 res = ctxt->err;
9800 return(res);
9801exit_failure:
9802 return(-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009803}
9804
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009805static xmlSchemaSchemaRelationPtr
9806xmlSchemaSchemaRelationCreate(void)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009807{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009808 xmlSchemaSchemaRelationPtr ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009809
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009810 ret = (xmlSchemaSchemaRelationPtr)
9811 xmlMalloc(sizeof(xmlSchemaSchemaRelation));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009812 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009813 xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009814 return(NULL);
9815 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009816 memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009817 return(ret);
9818}
9819
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009820#if 0
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009821static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009822xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009823{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009824 xmlFree(rel);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009825}
9826#endif
9827
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009828static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009829xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9830{
9831 xmlSchemaRedefPtr prev;
9832
9833 while (redef != NULL) {
9834 prev = redef;
9835 redef = redef->next;
9836 xmlFree(prev);
9837 }
9838}
9839
9840static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009841xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9842{
9843 /*
9844 * After the construction context has been freed, there will be
9845 * no schema graph available any more. Only the schema buckets
9846 * will stay alive, which are put into the "schemasImports" and
9847 * "includes" slots of the xmlSchema.
9848 */
9849 if (con->buckets != NULL)
9850 xmlSchemaItemListFree(con->buckets);
9851 if (con->pending != NULL)
9852 xmlSchemaItemListFree(con->pending);
9853 if (con->substGroups != NULL)
9854 xmlHashFree(con->substGroups,
9855 (xmlHashDeallocator) xmlSchemaSubstGroupFree);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009856 if (con->redefs != NULL)
9857 xmlSchemaRedefListFree(con->redefs);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009858 if (con->dict != NULL)
9859 xmlDictFree(con->dict);
9860 xmlFree(con);
9861}
9862
9863static xmlSchemaConstructionCtxtPtr
9864xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9865{
9866 xmlSchemaConstructionCtxtPtr ret;
9867
9868 ret = (xmlSchemaConstructionCtxtPtr)
9869 xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9870 if (ret == NULL) {
9871 xmlSchemaPErrMemory(NULL,
9872 "allocating schema construction context", NULL);
9873 return (NULL);
9874 }
9875 memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9876
9877 ret->buckets = xmlSchemaItemListCreate();
9878 if (ret->buckets == NULL) {
9879 xmlSchemaPErrMemory(NULL,
9880 "allocating list of schema buckets", NULL);
9881 xmlFree(ret);
9882 return (NULL);
9883 }
9884 ret->pending = xmlSchemaItemListCreate();
9885 if (ret->pending == NULL) {
9886 xmlSchemaPErrMemory(NULL,
9887 "allocating list of pending global components", NULL);
9888 xmlSchemaConstructionCtxtFree(ret);
9889 return (NULL);
9890 }
9891 ret->dict = dict;
9892 xmlDictReference(dict);
9893 return(ret);
9894}
9895
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009896static xmlSchemaParserCtxtPtr
9897xmlSchemaParserCtxtCreate(void)
9898{
9899 xmlSchemaParserCtxtPtr ret;
9900
9901 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9902 if (ret == NULL) {
9903 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9904 NULL);
9905 return (NULL);
9906 }
9907 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9908 ret->type = XML_SCHEMA_CTXT_PARSER;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009909 ret->attrProhibs = xmlSchemaItemListCreate();
9910 if (ret->attrProhibs == NULL) {
9911 xmlFree(ret);
9912 return(NULL);
9913 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009914 return(ret);
9915}
9916
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009917/**
9918 * xmlSchemaNewParserCtxtUseDict:
9919 * @URL: the location of the schema
9920 * @dict: the dictionary to be used
9921 *
9922 * Create an XML Schemas parse context for that file/resource expected
9923 * to contain an XML Schemas file.
9924 *
9925 * Returns the parser context or NULL in case of error
9926 */
9927static xmlSchemaParserCtxtPtr
9928xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9929{
9930 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009931
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009932 ret = xmlSchemaParserCtxtCreate();
9933 if (ret == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009934 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009935 ret->dict = dict;
9936 xmlDictReference(dict);
9937 if (URL != NULL)
9938 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009939 return (ret);
9940}
9941
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009942static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009943xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
9944{
9945 if (vctxt->pctxt == NULL) {
9946 if (vctxt->schema != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009947 vctxt->pctxt =
9948 xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009949 else
9950 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
9951 if (vctxt->pctxt == NULL) {
9952 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
9953 "failed to create a temp. parser context");
9954 return (-1);
9955 }
9956 /* TODO: Pass user data. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009957 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00009958 vctxt->warning, vctxt->errCtxt);
9959 xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
9960 vctxt->errCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009961 }
9962 return (0);
9963}
9964
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009965/**
9966 * xmlSchemaGetSchemaBucket:
9967 * @pctxt: the schema parser context
9968 * @schemaLocation: the URI of the schema document
9969 *
9970 * Returns a schema bucket if it was already parsed.
9971 *
9972 * Returns a schema bucket if it was already parsed from
9973 * @schemaLocation, NULL otherwise.
9974 */
9975static xmlSchemaBucketPtr
9976xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
9977 const xmlChar *schemaLocation)
9978{
9979 xmlSchemaBucketPtr cur;
9980 xmlSchemaItemListPtr list;
9981
9982 list = pctxt->constructor->buckets;
9983 if (list->nbItems == 0)
9984 return(NULL);
9985 else {
9986 int i;
9987 for (i = 0; i < list->nbItems; i++) {
9988 cur = (xmlSchemaBucketPtr) list->items[i];
9989 /* Pointer comparison! */
9990 if (cur->schemaLocation == schemaLocation)
9991 return(cur);
9992 }
9993 }
9994 return(NULL);
9995}
9996
9997static xmlSchemaBucketPtr
9998xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
9999 const xmlChar *schemaLocation,
10000 const xmlChar *targetNamespace)
10001{
10002 xmlSchemaBucketPtr cur;
10003 xmlSchemaItemListPtr list;
10004
10005 list = pctxt->constructor->buckets;
10006 if (list->nbItems == 0)
10007 return(NULL);
10008 else {
10009 int i;
10010 for (i = 0; i < list->nbItems; i++) {
10011 cur = (xmlSchemaBucketPtr) list->items[i];
10012 /* Pointer comparison! */
10013 if ((cur->origTargetNamespace == NULL) &&
10014 (cur->schemaLocation == schemaLocation) &&
10015 (cur->targetNamespace == targetNamespace))
10016 return(cur);
10017 }
10018 }
10019 return(NULL);
10020}
10021
10022
10023#define IS_BAD_SCHEMA_DOC(b) \
10024 (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10025
10026static xmlSchemaBucketPtr
10027xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10028 const xmlChar *targetNamespace,
10029 int imported)
10030{
10031 xmlSchemaBucketPtr cur;
10032 xmlSchemaItemListPtr list;
10033
10034 list = pctxt->constructor->buckets;
10035 if (list->nbItems == 0)
10036 return(NULL);
10037 else {
10038 int i;
10039 for (i = 0; i < list->nbItems; i++) {
10040 cur = (xmlSchemaBucketPtr) list->items[i];
10041 if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10042 (cur->origTargetNamespace == targetNamespace) &&
10043 ((imported && cur->imported) ||
10044 ((!imported) && (!cur->imported))))
10045 return(cur);
10046 }
10047 }
10048 return(NULL);
10049}
10050
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010051static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010052xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10053 xmlSchemaPtr schema,
10054 xmlSchemaBucketPtr bucket)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010055{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010056 int oldFlags;
10057 xmlDocPtr oldDoc;
10058 xmlNodePtr node;
10059 int ret, oldErrs;
10060 xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10061
10062 /*
10063 * Save old values; reset the *main* schema.
10064 * URGENT TODO: This is not good; move the per-document information
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000010065 * to the parser. Get rid of passing the main schema to the
10066 * parsing functions.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010067 */
10068 oldFlags = schema->flags;
10069 oldDoc = schema->doc;
10070 if (schema->flags != 0)
10071 xmlSchemaClearSchemaDefaults(schema);
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000010072 schema->doc = bucket->doc;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010073 pctxt->schema = schema;
10074 /*
10075 * Keep the current target namespace on the parser *not* on the
10076 * main schema.
10077 */
10078 pctxt->targetNamespace = bucket->targetNamespace;
10079 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010080
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010081 if ((bucket->targetNamespace != NULL) &&
10082 xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010083 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010084 * We are parsing the schema for schemas!
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010085 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010086 pctxt->isS4S = 1;
10087 }
10088 /* Mark it as parsed, even if parsing fails. */
10089 bucket->parsed++;
10090 /* Compile the schema doc. */
10091 node = xmlDocGetRootElement(bucket->doc);
10092 ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10093 if (ret != 0)
10094 goto exit;
10095 /* An empty schema; just get out. */
10096 if (node->children == NULL)
10097 goto exit;
10098 oldErrs = pctxt->nberrors;
10099 ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10100 if (ret != 0)
10101 goto exit;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010102 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010103 * TODO: Not nice, but I'm not 100% sure we will get always an error
10104 * as a result of the obove functions; so better rely on pctxt->err
10105 * as well.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010106 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010107 if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10108 ret = pctxt->err;
10109 goto exit;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010110 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010111
10112exit:
10113 WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10114 /* Restore schema values. */
10115 schema->doc = oldDoc;
10116 schema->flags = oldFlags;
10117 return(ret);
10118}
10119
10120static int
10121xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10122 xmlSchemaPtr schema,
10123 xmlSchemaBucketPtr bucket)
10124{
10125 xmlSchemaParserCtxtPtr newpctxt;
10126 int res = 0;
10127
10128 if (bucket == NULL)
10129 return(0);
10130 if (bucket->parsed) {
10131 PERROR_INT("xmlSchemaParseNewDoc",
10132 "reparsing a schema doc");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010133 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010134 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010135 if (bucket->doc == NULL) {
10136 PERROR_INT("xmlSchemaParseNewDoc",
10137 "parsing a schema doc, but there's no doc");
10138 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000010139 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010140 if (pctxt->constructor == NULL) {
10141 PERROR_INT("xmlSchemaParseNewDoc",
10142 "no constructor");
10143 return(-1);
10144 }
10145 /* Create and init the temporary parser context. */
10146 newpctxt = xmlSchemaNewParserCtxtUseDict(
10147 (const char *) bucket->schemaLocation, pctxt->dict);
10148 if (newpctxt == NULL)
10149 return(-1);
10150 newpctxt->constructor = pctxt->constructor;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010151 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010152 * TODO: Can we avoid that the parser knows about the main schema?
10153 * It would be better if he knows about the current schema bucket
10154 * only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010155 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010156 newpctxt->schema = schema;
10157 xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000010158 pctxt->errCtxt);
10159 xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10160 pctxt->errCtxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010161 newpctxt->counter = pctxt->counter;
10162
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010163
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010164 res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10165
10166 /* Channel back errors and cleanup the temporary parser context. */
10167 if (res != 0)
10168 pctxt->err = res;
10169 pctxt->nberrors += newpctxt->nberrors;
10170 pctxt->counter = newpctxt->counter;
10171 newpctxt->constructor = NULL;
10172 /* Free the parser context. */
10173 xmlSchemaFreeParserCtxt(newpctxt);
10174 return(res);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010175}
William M. Brack2f2a6632004-08-20 23:09:47 +000010176
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010177static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010178xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10179 xmlSchemaSchemaRelationPtr rel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010180{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010181 xmlSchemaSchemaRelationPtr cur = bucket->relations;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010182
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010183 if (cur == NULL) {
10184 bucket->relations = rel;
10185 return;
10186 }
10187 while (cur->next != NULL)
10188 cur = cur->next;
10189 cur->next = rel;
10190}
10191
10192
10193static const xmlChar *
10194xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10195 xmlNodePtr ctxtNode)
10196{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010197 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010198 * Build an absolue location URI.
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010199 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010200 if (location != NULL) {
10201 if (ctxtNode == NULL)
10202 return(location);
10203 else {
10204 xmlChar *base, *URI;
10205 const xmlChar *ret = NULL;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010206
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010207 base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10208 if (base == NULL) {
10209 URI = xmlBuildURI(location, ctxtNode->doc->URL);
10210 } else {
10211 URI = xmlBuildURI(location, base);
10212 xmlFree(base);
10213 }
10214 if (URI != NULL) {
10215 ret = xmlDictLookup(dict, URI, -1);
10216 xmlFree(URI);
10217 return(ret);
10218 }
10219 }
10220 }
10221 return(NULL);
10222}
10223
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010224
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010225
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010226/**
10227 * xmlSchemaAddSchemaDoc:
10228 * @pctxt: a schema validation context
10229 * @schema: the schema being built
10230 * @node: a subtree containing XML Schema informations
10231 *
10232 * Parse an included (and to-be-redefined) XML schema document.
10233 *
10234 * Returns 0 on success, a positive error code on errors and
10235 * -1 in case of an internal or API error.
10236 */
10237
10238static int
10239xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10240 int type, /* import or include or redefine */
10241 const xmlChar *schemaLocation,
10242 xmlDocPtr schemaDoc,
10243 const char *schemaBuffer,
10244 int schemaBufferLen,
10245 xmlNodePtr invokingNode,
10246 const xmlChar *sourceTargetNamespace,
10247 const xmlChar *importNamespace,
10248 xmlSchemaBucketPtr *bucket)
10249{
10250 const xmlChar *targetNamespace = NULL;
10251 xmlSchemaSchemaRelationPtr relation = NULL;
10252 xmlDocPtr doc = NULL;
10253 int res = 0, err = 0, located = 0, preserveDoc = 0;
10254 xmlSchemaBucketPtr bkt = NULL;
10255
10256 if (bucket != NULL)
10257 *bucket = NULL;
10258
10259 switch (type) {
10260 case XML_SCHEMA_SCHEMA_IMPORT:
10261 case XML_SCHEMA_SCHEMA_MAIN:
10262 err = XML_SCHEMAP_SRC_IMPORT;
10263 break;
10264 case XML_SCHEMA_SCHEMA_INCLUDE:
10265 err = XML_SCHEMAP_SRC_INCLUDE;
10266 break;
10267 case XML_SCHEMA_SCHEMA_REDEFINE:
10268 err = XML_SCHEMAP_SRC_REDEFINE;
10269 break;
10270 }
10271
10272
10273 /* Special handling for the main schema:
10274 * skip the location and relation logic and just parse the doc.
10275 * We need just a bucket to be returned in this case.
10276 */
10277 if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10278 goto doc_load;
10279
10280 /* Note that we expect the location to be an absulute URI. */
10281 if (schemaLocation != NULL) {
10282 bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10283 if ((bkt != NULL) &&
10284 (pctxt->constructor->bucket == bkt)) {
10285 /* Report self-imports/inclusions/redefinitions. */
10286
10287 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10288 invokingNode, NULL,
10289 "The schema must not import/include/redefine itself",
10290 NULL, NULL);
10291 goto exit;
10292 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010293 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010294 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010295 * Create a relation for the graph of schemas.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010296 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010297 relation = xmlSchemaSchemaRelationCreate();
10298 if (relation == NULL)
10299 return(-1);
10300 xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10301 relation);
10302 relation->type = type;
10303
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010304 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010305 * Save the namespace import information.
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010306 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010307 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010308 relation->importNamespace = importNamespace;
10309 if (schemaLocation == NULL) {
10310 /*
10311 * No location; this is just an import of the namespace.
10312 * Note that we don't assign a bucket to the relation
10313 * in this case.
10314 */
10315 goto exit;
10316 }
10317 targetNamespace = importNamespace;
10318 }
10319
10320 /* Did we already fetch the doc? */
10321 if (bkt != NULL) {
10322 /* TODO: The following nasty cases will produce an error. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010323 if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010324 /* We included/redefined and then try to import a schema. */
10325 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10326 invokingNode, NULL,
10327 "The schema document '%s' cannot be imported, since "
10328 "it was already included or redefined",
10329 schemaLocation, NULL);
10330 goto exit;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010331 } else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010332 /* We imported and then try to include/redefine a schema. */
10333 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10334 invokingNode, NULL,
10335 "The schema document '%s' cannot be included or "
10336 "redefined, since it was already imported",
10337 schemaLocation, NULL);
10338 goto exit;
10339 }
10340 }
10341
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010342 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010343 /*
10344 * Given that the schemaLocation [attribute] is only a hint, it is open
10345 * to applications to ignore all but the first <import> for a given
10346 * namespace, regardless of the ·actual value· of schemaLocation, but
10347 * such a strategy risks missing useful information when new
10348 * schemaLocations are offered.
10349 *
10350 * We will use the first <import> that comes with a location.
10351 * Further <import>s *with* a location, will result in an error.
10352 * TODO: Better would be to just report a warning here, but
10353 * we'll try it this way until someone complains.
10354 *
10355 * Schema Document Location Strategy:
10356 * 3 Based on the namespace name, identify an existing schema document,
10357 * either as a resource which is an XML document or a <schema> element
10358 * information item, in some local schema repository;
10359 * 5 Attempt to resolve the namespace name to locate such a resource.
10360 *
10361 * NOTE: (3) and (5) are not supported.
10362 */
10363 if (bkt != NULL) {
10364 relation->bucket = bkt;
10365 goto exit;
10366 }
10367 bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10368 importNamespace, 1);
10369
10370 if (bkt != NULL) {
10371 relation->bucket = bkt;
10372 if (bkt->schemaLocation == NULL) {
10373 /* First given location of the schema; load the doc. */
10374 bkt->schemaLocation = schemaLocation;
10375 } else {
10376 if (!xmlStrEqual(schemaLocation,
10377 bkt->schemaLocation)) {
10378 /*
10379 * Additional location given; just skip it.
10380 * URGENT TODO: We should report a warning here.
10381 * res = XML_SCHEMAP_SRC_IMPORT;
10382 */
10383 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10384 XML_SCHEMAP_WARN_SKIP_SCHEMA,
10385 invokingNode, NULL,
10386 "Skipping import of schema located at '%s' for the "
10387 "namespace '%s', since this namespace was already "
10388 "imported with the schema located at '%s'",
10389 schemaLocation, importNamespace, bkt->schemaLocation);
10390 }
10391 goto exit;
10392 }
10393 }
10394 /*
10395 * No bucket + first location: load the doc and create a
10396 * bucket.
10397 */
10398 } else {
10399 /* <include> and <redefine> */
10400 if (bkt != NULL) {
10401
10402 if ((bkt->origTargetNamespace == NULL) &&
10403 (bkt->targetNamespace != sourceTargetNamespace)) {
10404 xmlSchemaBucketPtr chamel;
10405
10406 /*
10407 * Chameleon include/redefine: skip loading only if it was
10408 * aleady build for the targetNamespace of the including
10409 * schema.
10410 */
10411 /*
10412 * URGENT TODO: If the schema is a chameleon-include then copy
10413 * the components into the including schema and modify the
10414 * targetNamespace of those components, do nothing otherwise.
10415 * NOTE: This is currently worked-around by compiling the
10416 * chameleon for every destinct including targetNamespace; thus
10417 * not performant at the moment.
10418 * TODO: Check when the namespace in wildcards for chameleons
10419 * needs to be converted: before we built wildcard intersections
10420 * or after.
10421 * Answer: after!
10422 */
10423 chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10424 schemaLocation, sourceTargetNamespace);
10425 if (chamel != NULL) {
10426 /* A fitting chameleon was already parsed; NOP. */
10427 relation->bucket = chamel;
10428 goto exit;
10429 }
10430 /*
10431 * We need to parse the chameleon again for a different
10432 * targetNamespace.
10433 * CHAMELEON TODO: Optimize this by only parsing the
10434 * chameleon once, and then copying the components to
10435 * the new targetNamespace.
10436 */
10437 bkt = NULL;
10438 } else {
10439 relation->bucket = bkt;
10440 goto exit;
10441 }
10442 }
10443 }
10444 if ((bkt != NULL) && (bkt->doc != NULL)) {
10445 PERROR_INT("xmlSchemaAddSchemaDoc",
10446 "trying to load a schema doc, but a doc is already "
10447 "assigned to the schema bucket");
10448 goto exit_failure;
10449 }
10450
10451doc_load:
10452 /*
10453 * Load the document.
10454 */
10455 if (schemaDoc != NULL) {
10456 doc = schemaDoc;
10457 /* Don' free this one, since it was provided by the caller. */
10458 preserveDoc = 1;
10459 /* TODO: Does the context or the doc hold the location? */
10460 if (schemaDoc->URL != NULL)
10461 schemaLocation = xmlDictLookup(pctxt->dict,
10462 schemaDoc->URL, -1);
10463
10464 } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10465 xmlParserCtxtPtr parserCtxt;
10466
10467 parserCtxt = xmlNewParserCtxt();
10468 if (parserCtxt == NULL) {
10469 xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10470 "allocating a parser context", NULL);
10471 goto exit_failure;
10472 }
10473 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10474 /*
10475 * TODO: Do we have to burden the schema parser dict with all
10476 * the content of the schema doc?
10477 */
10478 xmlDictFree(parserCtxt->dict);
10479 parserCtxt->dict = pctxt->dict;
10480 xmlDictReference(parserCtxt->dict);
10481 }
10482 if (schemaLocation != NULL) {
10483 /* Parse from file. */
10484 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10485 NULL, SCHEMAS_PARSE_OPTIONS);
10486 } else if (schemaBuffer != NULL) {
10487 /* Parse from memory buffer. */
10488 doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10489 NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10490 schemaLocation = xmlStrdup(BAD_CAST "in_memory_buffer");
10491 if (doc != NULL)
10492 doc->URL = schemaLocation;
10493 }
10494 /*
10495 * For <import>:
10496 * 2.1 The referent is (a fragment of) a resource which is an
10497 * XML document (see clause 1.1), which in turn corresponds to
10498 * a <schema> element information item in a well-formed information
10499 * set, which in turn corresponds to a valid schema.
10500 * TODO: (2.1) fragments of XML documents are not supported.
10501 *
10502 * 2.2 The referent is a <schema> element information item in
10503 * a well-formed information set, which in turn corresponds
10504 * to a valid schema.
10505 * TODO: (2.2) is not supported.
10506 */
10507 if (doc == NULL) {
10508 xmlErrorPtr lerr;
10509 lerr = xmlGetLastError();
10510 /*
10511 * Check if this a parser error, or if the document could
10512 * just not be located.
10513 * TODO: Try to find specific error codes to react only on
10514 * localisation failures.
10515 */
10516 if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10517 /*
10518 * We assume a parser error here.
10519 */
10520 located = 1;
10521 /* TODO: Error code ?? */
10522 res = XML_SCHEMAP_SRC_IMPORT_2_1;
10523 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10524 invokingNode, NULL,
10525 "Failed to parse the XML resource '%s'",
10526 schemaLocation, NULL);
10527 }
10528 }
10529 xmlFreeParserCtxt(parserCtxt);
10530 if ((doc == NULL) && located)
10531 goto exit_error;
10532 } else {
10533 xmlSchemaPErr(pctxt, NULL,
10534 XML_SCHEMAP_NOTHING_TO_PARSE,
10535 "No information for parsing was provided with the "
10536 "given schema parser context.\n",
10537 NULL, NULL);
10538 goto exit_failure;
10539 }
10540 /*
10541 * Preprocess the document.
10542 */
10543 if (doc != NULL) {
10544 xmlNodePtr docElem = NULL;
10545
10546 located = 1;
10547 docElem = xmlDocGetRootElement(doc);
10548 if (docElem == NULL) {
10549 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10550 invokingNode, NULL,
10551 "The document '%s' has no document element",
10552 schemaLocation, NULL);
10553 xmlFreeDoc(doc);
10554 doc = NULL;
10555 goto exit_error;
10556 }
10557 /*
10558 * Remove all the blank text nodes.
10559 */
10560 xmlSchemaCleanupDoc(pctxt, docElem);
10561 /*
10562 * Check the schema's top level element.
10563 */
10564 if (!IS_SCHEMA(docElem, "schema")) {
10565 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10566 invokingNode, NULL,
10567 "The XML document '%s' is not a schema document",
10568 schemaLocation, NULL);
10569 xmlFreeDoc(doc);
10570 doc = NULL;
10571 goto exit_error;
10572 }
10573 /*
10574 * Note that we don't apply a type check for the
10575 * targetNamespace value here.
10576 */
10577 targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10578 "targetNamespace");
10579 }
10580
10581/* after_doc_loading: */
10582 if ((bkt == NULL) && located) {
10583 /* Only create a bucket if the schema was located. */
10584 bkt = xmlSchemaBucketCreate(pctxt, type,
10585 targetNamespace);
10586 if (bkt == NULL)
10587 goto exit_failure;
10588 }
10589 if (bkt != NULL) {
10590 bkt->schemaLocation = schemaLocation;
10591 bkt->located = located;
10592 if (doc != NULL) {
10593 bkt->doc = doc;
10594 bkt->targetNamespace = targetNamespace;
10595 bkt->origTargetNamespace = targetNamespace;
10596 if (preserveDoc)
10597 bkt->preserveDoc = 1;
10598 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010599 if (WXS_IS_BUCKET_IMPMAIN(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010600 bkt->imported++;
10601 /*
10602 * Add it to the graph of schemas.
10603 */
10604 if (relation != NULL)
10605 relation->bucket = bkt;
10606 }
10607
10608exit:
10609 /*
10610 * Return the bucket explicitely; this is needed for the
10611 * main schema.
10612 */
10613 if (bucket != NULL)
10614 *bucket = bkt;
10615 return (0);
10616
10617exit_error:
10618 if ((doc != NULL) && (! preserveDoc)) {
10619 xmlFreeDoc(doc);
10620 if (bkt != NULL)
10621 bkt->doc = NULL;
10622 }
10623 return(pctxt->err);
10624
10625exit_failure:
10626 if ((doc != NULL) && (! preserveDoc)) {
10627 xmlFreeDoc(doc);
10628 if (bkt != NULL)
10629 bkt->doc = NULL;
10630 }
10631 return (-1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010632}
10633
William M. Brack2f2a6632004-08-20 23:09:47 +000010634/**
10635 * xmlSchemaParseImport:
10636 * @ctxt: a schema validation context
10637 * @schema: the schema being built
10638 * @node: a subtree containing XML Schema informations
10639 *
10640 * parse a XML schema Import definition
10641 * *WARNING* this interface is highly subject to change
10642 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010643 * Returns 0 in case of success, a positive error code if
10644 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +000010645 */
10646static int
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010647xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +000010648 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010649{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010650 xmlNodePtr child;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010651 const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10652 const xmlChar *thisTargetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +000010653 xmlAttrPtr attr;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010654 int ret = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010655 xmlSchemaBucketPtr bucket = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000010656
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010657 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
William M. Brack2f2a6632004-08-20 23:09:47 +000010658 return (-1);
10659
10660 /*
10661 * Check for illegal attributes.
10662 */
10663 attr = node->properties;
10664 while (attr != NULL) {
10665 if (attr->ns == NULL) {
10666 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10667 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10668 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010669 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010670 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010671 }
10672 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010673 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010674 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010675 }
10676 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010677 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010678 /*
10679 * Extract and validate attributes.
10680 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010681 if (xmlSchemaPValAttr(pctxt, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010682 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010683 &namespaceName) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010684 xmlSchemaPSimpleTypeErr(pctxt,
10685 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010686 NULL, node,
10687 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010688 NULL, namespaceName, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010689 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010690 }
10691
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010692 if (xmlSchemaPValAttr(pctxt, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010693 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +000010694 &schemaLocation) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010695 xmlSchemaPSimpleTypeErr(pctxt,
10696 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010697 NULL, node,
10698 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010699 NULL, namespaceName, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010700 return (pctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010701 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010702 /*
10703 * And now for the children...
10704 */
10705 child = node->children;
10706 if (IS_SCHEMA(child, "annotation")) {
10707 /*
10708 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010709 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +000010710 */
10711 child = child->next;
10712 }
10713 if (child != NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010714 xmlSchemaPContentErr(pctxt,
10715 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010716 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010717 "(annotation?)");
10718 }
10719 /*
10720 * Apply additional constraints.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010721 *
10722 * Note that it is important to use the original @targetNamespace
10723 * (or none at all), to rule out imports of schemas _with_ a
10724 * @targetNamespace if the importing schema is a chameleon schema
10725 * (with no @targetNamespace).
William M. Brack2f2a6632004-08-20 23:09:47 +000010726 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010727 thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010728 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000010729 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010730 * 1.1 If the namespace [attribute] is present, then its ·actual value·
10731 * must not match the ·actual value· of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +000010732 * targetNamespace [attribute].
10733 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010734 if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010735 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000010736 XML_SCHEMAP_SRC_IMPORT_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010737 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +000010738 "The value of the attribute 'namespace' must not match "
10739 "the target namespace '%s' of the importing schema",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010740 thisTargetNamespace);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010741 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010742 }
10743 } else {
10744 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010745 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +000010746 * <schema> must have a targetNamespace [attribute].
10747 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010748 if (thisTargetNamespace == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010749 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000010750 XML_SCHEMAP_SRC_IMPORT_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010751 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +000010752 "The attribute 'namespace' must be existent if "
10753 "the importing schema has no target namespace",
10754 NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010755 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010756 }
10757 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010758 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000010759 * Locate and acquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +000010760 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010761 if (schemaLocation != NULL)
10762 schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10763 schemaLocation, node);
10764 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010765 schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010766 namespaceName, &bucket);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010767
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010768 if (ret != 0)
10769 return(ret);
10770
10771 /*
10772 * For <import>: "It is *not* an error for the application
10773 * schema reference strategy to fail."
10774 * So just don't parse if no schema document was found.
10775 * Note that we will get no bucket if the schema could not be
10776 * located or if there was no schemaLocation.
10777 */
10778 if ((bucket == NULL) && (schemaLocation != NULL)) {
10779 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10780 XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10781 node, NULL,
10782 "Failed to locate a schema at location '%s'. "
10783 "Skipping the import", schemaLocation, NULL, NULL);
10784 }
10785
10786 if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10787 ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10788 }
10789
10790 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000010791}
10792
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010793static int
10794xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10795 xmlSchemaPtr schema,
10796 xmlNodePtr node,
10797 xmlChar **schemaLocation,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010798 int type)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010799{
10800 xmlAttrPtr attr;
10801
10802 if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10803 (schemaLocation == NULL))
10804 return (-1);
10805
10806 *schemaLocation = NULL;
10807 /*
10808 * Check for illegal attributes.
10809 * Applies for both <include> and <redefine>.
10810 */
10811 attr = node->properties;
10812 while (attr != NULL) {
10813 if (attr->ns == NULL) {
10814 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10815 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10816 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010817 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010818 }
10819 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10820 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010821 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010822 }
10823 attr = attr->next;
10824 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010825 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010826 /*
10827 * Preliminary step, extract the URI-Reference and make an URI
10828 * from the base.
10829 */
10830 /*
10831 * Attribute "schemaLocation" is mandatory.
10832 */
10833 attr = xmlSchemaGetPropNode(node, "schemaLocation");
10834 if (attr != NULL) {
10835 xmlChar *base = NULL;
10836 xmlChar *uri = NULL;
10837
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010838 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010839 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10840 (const xmlChar **) schemaLocation) != 0)
10841 goto exit_error;
10842 base = xmlNodeGetBase(node->doc, node);
10843 if (base == NULL) {
10844 uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10845 } else {
10846 uri = xmlBuildURI(*schemaLocation, base);
10847 xmlFree(base);
10848 }
10849 if (uri == NULL) {
10850 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10851 "could not build an URI from the schemaLocation")
10852 goto exit_failure;
10853 }
10854 (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10855 xmlFree(uri);
10856 } else {
10857 xmlSchemaPMissingAttrErr(pctxt,
10858 XML_SCHEMAP_S4S_ATTR_MISSING,
10859 NULL, node, "schemaLocation", NULL);
10860 goto exit_error;
10861 }
10862 /*
10863 * Report self-inclusion and self-redefinition.
10864 */
10865 if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010866 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010867 xmlSchemaPCustomErr(pctxt,
10868 XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010869 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010870 "The schema document '%s' cannot redefine itself.",
10871 *schemaLocation);
10872 } else {
10873 xmlSchemaPCustomErr(pctxt,
10874 XML_SCHEMAP_SRC_INCLUDE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010875 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010876 "The schema document '%s' cannot include itself.",
10877 *schemaLocation);
10878 }
10879 goto exit_error;
10880 }
10881
10882 return(0);
10883exit_error:
10884 return(pctxt->err);
10885exit_failure:
10886 return(-1);
10887}
10888
10889static int
10890xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10891 xmlSchemaPtr schema,
10892 xmlNodePtr node,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010893 int type)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010894{
10895 xmlNodePtr child = NULL;
10896 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000010897 int res = 0; /* hasRedefinitions = 0 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010898 int isChameleon = 0, wasChameleon = 0;
10899 xmlSchemaBucketPtr bucket = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010900
10901 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10902 return (-1);
10903
10904 /*
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010905 * Parse attributes. Note that the returned schemaLocation will
10906 * be already converted to an absolute URI.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010907 */
10908 res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010909 node, (xmlChar **) (&schemaLocation), type);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010910 if (res != 0)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010911 return(res);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010912 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010913 * Load and add the schema document.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010914 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010915 res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10916 NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010917 if (res != 0)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010918 return(res);
10919 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010920 * If we get no schema bucket back, then this means that the schema
10921 * document could not be located or was broken XML or was not
10922 * a schema document.
10923 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010924 if ((bucket == NULL) || (bucket->doc == NULL)) {
10925 if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10926 /*
10927 * WARNING for <include>:
10928 * We will raise an error if the schema cannot be located
10929 * for inclusions, since the that was the feedback from the
10930 * schema people. I.e. the following spec piece will *not* be
10931 * satisfied:
10932 * SPEC src-include: "It is not an error for the ·actual value· of the
10933 * schemaLocation [attribute] to fail to resolve it all, in which
10934 * case no corresponding inclusion is performed.
10935 * So do we need a warning report here?"
10936 */
10937 res = XML_SCHEMAP_SRC_INCLUDE;
10938 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10939 node, NULL,
10940 "Failed to load the document '%s' for inclusion",
10941 schemaLocation, NULL);
10942 } else {
10943 /*
10944 * NOTE: This was changed to raise an error even if no redefinitions
10945 * are specified.
10946 *
10947 * SPEC src-redefine (1)
10948 * "If there are any element information items among the [children]
10949 * other than <annotation> then the ·actual value· of the
10950 * schemaLocation [attribute] must successfully resolve."
10951 * TODO: Ask the WG if a the location has always to resolve
10952 * here as well!
10953 */
10954 res = XML_SCHEMAP_SRC_REDEFINE;
10955 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10956 node, NULL,
10957 "Failed to load the document '%s' for redefinition",
10958 schemaLocation, NULL);
10959 }
10960 } else {
10961 /*
10962 * Check targetNamespace sanity before parsing the new schema.
10963 * TODO: Note that we won't check further content if the
10964 * targetNamespace was bad.
10965 */
10966 if (bucket->origTargetNamespace != NULL) {
10967 /*
10968 * SPEC src-include (2.1)
10969 * "SII has a targetNamespace [attribute], and its ·actual
10970 * value· is identical to the ·actual value· of the targetNamespace
10971 * [attribute] of SIIÂ’ (which must have such an [attribute])."
10972 */
10973 if (pctxt->targetNamespace == NULL) {
10974 xmlSchemaCustomErr(ACTXT_CAST pctxt,
10975 XML_SCHEMAP_SRC_INCLUDE,
10976 node, NULL,
10977 "The target namespace of the included/redefined schema "
10978 "'%s' has to be absent, since the including/redefining "
10979 "schema has no target namespace",
10980 schemaLocation, NULL);
10981 goto exit_error;
10982 } else if (!xmlStrEqual(bucket->origTargetNamespace,
10983 pctxt->targetNamespace)) {
10984 /* TODO: Change error function. */
10985 xmlSchemaPCustomErrExt(pctxt,
10986 XML_SCHEMAP_SRC_INCLUDE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010987 NULL, node,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010988 "The target namespace '%s' of the included/redefined "
10989 "schema '%s' differs from '%s' of the "
10990 "including/redefining schema",
10991 bucket->origTargetNamespace, schemaLocation,
10992 pctxt->targetNamespace);
10993 goto exit_error;
10994 }
10995 } else if (pctxt->targetNamespace != NULL) {
10996 /*
10997 * Chameleons: the original target namespace will
10998 * differ from the resulting namespace.
10999 */
11000 isChameleon = 1;
11001 if (bucket->parsed &&
11002 (bucket->targetNamespace != pctxt->targetNamespace)) {
11003 /*
11004 * This is a sanity check, I dunno yet if this can happen.
11005 */
11006 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
11007 "trying to use an already parsed schema for a "
11008 "different targetNamespace");
11009 return(-1);
11010 }
11011 bucket->targetNamespace = pctxt->targetNamespace;
11012 }
11013 }
11014 /*
11015 * Parse the schema.
11016 */
11017 if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11018 if (isChameleon) {
11019 /* TODO: Get rid of this flag on the schema itself. */
11020 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11021 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11022 } else
11023 wasChameleon = 1;
11024 }
11025 xmlSchemaParseNewDoc(pctxt, schema, bucket);
11026 /* Restore chameleon flag. */
11027 if (isChameleon && (!wasChameleon))
11028 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11029 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011030 /*
11031 * And now for the children...
11032 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011033 child = node->children;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011034 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011035 /*
11036 * Parse (simpleType | complexType | group | attributeGroup))*
11037 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011038 pctxt->redefined = bucket;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011039 /*
11040 * How to proceed if the redefined schema was not located?
11041 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011042 pctxt->isRedefine = 1;
11043 while (IS_SCHEMA(child, "annotation") ||
11044 IS_SCHEMA(child, "simpleType") ||
11045 IS_SCHEMA(child, "complexType") ||
11046 IS_SCHEMA(child, "group") ||
11047 IS_SCHEMA(child, "attributeGroup")) {
11048 if (IS_SCHEMA(child, "annotation")) {
11049 /*
11050 * TODO: discard or not?
11051 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011052 } else if (IS_SCHEMA(child, "simpleType")) {
11053 xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11054 } else if (IS_SCHEMA(child, "complexType")) {
11055 xmlSchemaParseComplexType(pctxt, schema, child, 1);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011056 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011057 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011058 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011059 xmlSchemaParseModelGroupDefinition(pctxt,
11060 schema, child);
11061 } else if (IS_SCHEMA(child, "attributeGroup")) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011062 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011063 xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11064 child);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011065 }
11066 child = child->next;
11067 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011068 pctxt->redefined = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011069 pctxt->isRedefine = 0;
11070 } else {
11071 if (IS_SCHEMA(child, "annotation")) {
11072 /*
11073 * TODO: discard or not?
11074 */
11075 child = child->next;
11076 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011077 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011078 if (child != NULL) {
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011079 res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011080 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11081 xmlSchemaPContentErr(pctxt, res,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011082 NULL, node, child, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011083 "(annotation | (simpleType | complexType | group | attributeGroup))*");
11084 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011085 xmlSchemaPContentErr(pctxt, res,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011086 NULL, node, child, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011087 "(annotation?)");
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011088 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011089 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011090 return(res);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011091
11092exit_error:
11093 return(pctxt->err);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011094}
11095
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011096static int
11097xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11098 xmlNodePtr node)
11099{
11100 int res;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011101#ifndef ENABLE_REDEFINE
11102 TODO
11103 return(0);
11104#endif
11105 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11106 XML_SCHEMA_SCHEMA_REDEFINE);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011107 if (res != 0)
11108 return(res);
11109 return(0);
11110}
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011111
11112static int
11113xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11114 xmlNodePtr node)
11115{
11116 int res;
11117
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011118 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11119 XML_SCHEMA_SCHEMA_INCLUDE);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011120 if (res != 0)
11121 return(res);
11122 return(0);
11123}
11124
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011125/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011126 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011127 * @ctxt: a schema validation context
11128 * @schema: the schema being built
11129 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011130 * @type: the "compositor" type
11131 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +000011132 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011133 * parse a XML schema Sequence definition.
11134 * Applies parts of:
11135 * Schema Representation Constraint:
11136 * Redefinition Constraints and Semantics (src-redefine)
11137 * (6.1), (6.1.1), (6.1.2)
11138 *
11139 * Schema Component Constraint:
11140 * All Group Limited (cos-all-limited) (2)
11141 * TODO: Actually this should go to component-level checks,
11142 * but is done here due to performance. Move it to an other layer
11143 * is schema construction via an API is implemented.
11144 *
Daniel Veillard4255d502002-04-16 15:50:10 +000011145 * *WARNING* this interface is highly subject to change
11146 *
William M. Bracke7091952004-05-11 15:09:58 +000011147 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +000011148 * 1 in case of success.
11149 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011150static xmlSchemaTreeItemPtr
11151xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11152 xmlNodePtr node, xmlSchemaTypeType type,
11153 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +000011154{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011155 xmlSchemaModelGroupPtr item;
11156 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011157 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000011158 xmlAttrPtr attr;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011159 int min = 1, max = 1, isElemRef, hasRefs = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000011160
11161 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011162 return (NULL);
11163 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011164 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +000011165 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011166 item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011167 if (item == NULL)
11168 return (NULL);
11169
11170 if (withParticle) {
11171 if (type == XML_SCHEMA_TYPE_ALL) {
11172 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011173 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011174 } else {
11175 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011176 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11177 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11178 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011179 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011180 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11181 /*
11182 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011183 */
11184 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
11185 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011186 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011187 particle->children = (xmlSchemaTreeItemPtr) item;
11188 /*
11189 * Check for illegal attributes.
11190 */
11191 attr = node->properties;
11192 while (attr != NULL) {
11193 if (attr->ns == NULL) {
11194 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11195 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11196 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011197 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011198 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011199 }
11200 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011201 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011202 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011203 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011204 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000011205 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011206 } else {
11207 /*
11208 * Check for illegal attributes.
11209 */
11210 attr = node->properties;
11211 while (attr != NULL) {
11212 if (attr->ns == NULL) {
11213 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011214 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011215 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011216 }
11217 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011218 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011219 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011220 }
11221 attr = attr->next;
11222 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011223 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011224
William M. Brack2f2a6632004-08-20 23:09:47 +000011225 /*
11226 * Extract and validate attributes.
11227 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011228 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000011229 /*
11230 * And now for the children...
11231 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011232 child = node->children;
11233 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000011234 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011235 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011236 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011237 if (type == XML_SCHEMA_TYPE_ALL) {
11238 xmlSchemaParticlePtr part, last = NULL;
11239
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011240 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011241 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011242 schema, child, &isElemRef, 0);
11243 /*
11244 * SPEC cos-all-limited (2)
11245 * "The {max occurs} of all the particles in the {particles}
11246 * of the ('all') group must be 0 or 1.
11247 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011248 if (part != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011249 if (isElemRef)
11250 hasRefs++;
11251 if (part->minOccurs > 1) {
11252 xmlSchemaPCustomErr(ctxt,
11253 XML_SCHEMAP_COS_ALL_LIMITED,
11254 NULL, child,
11255 "Invalid value for minOccurs (must be 0 or 1)",
11256 NULL);
11257 /* Reset to 1. */
11258 part->minOccurs = 1;
11259 }
11260 if (part->maxOccurs > 1) {
11261 xmlSchemaPCustomErr(ctxt,
11262 XML_SCHEMAP_COS_ALL_LIMITED,
11263 NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011264 "Invalid value for maxOccurs (must be 0 or 1)",
11265 NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011266 /* Reset to 1. */
11267 part->maxOccurs = 1;
11268 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011269 if (last == NULL)
11270 item->children = (xmlSchemaTreeItemPtr) part;
11271 else
11272 last->next = (xmlSchemaTreeItemPtr) part;
11273 last = part;
11274 }
11275 child = child->next;
11276 }
11277 if (child != NULL) {
11278 xmlSchemaPContentErr(ctxt,
11279 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011280 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011281 "(annotation?, (annotation?, element*)");
11282 }
11283 } else {
11284 /* choice + sequence */
11285 xmlSchemaTreeItemPtr part = NULL, last = NULL;
11286
11287 while ((IS_SCHEMA(child, "element")) ||
11288 (IS_SCHEMA(child, "group")) ||
11289 (IS_SCHEMA(child, "any")) ||
11290 (IS_SCHEMA(child, "choice")) ||
11291 (IS_SCHEMA(child, "sequence"))) {
11292
11293 if (IS_SCHEMA(child, "element")) {
11294 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011295 xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11296 if (part && isElemRef)
11297 hasRefs++;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011298 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011299 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011300 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011301 if (part != NULL)
11302 hasRefs++;
11303 /*
11304 * Handle redefinitions.
11305 */
11306 if (ctxt->isRedefine && ctxt->redef &&
11307 (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11308 part && part->children)
11309 {
11310 if ((xmlSchemaGetQNameRefName(part->children) ==
11311 ctxt->redef->refName) &&
11312 (xmlSchemaGetQNameRefTargetNs(part->children) ==
11313 ctxt->redef->refTargetNs))
11314 {
11315 /*
11316 * SPEC src-redefine:
11317 * (6.1) "If it has a <group> among its contents at
11318 * some level the ·actual value· of whose ref
11319 * [attribute] is the same as the ·actual value· of
11320 * its own name attribute plus target namespace, then
11321 * all of the following must be true:"
11322 * (6.1.1) "It must have exactly one such group."
11323 */
11324 if (ctxt->redefCounter != 0) {
11325 xmlChar *str = NULL;
11326
11327 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11328 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11329 "The redefining model group definition "
11330 "'%s' must not contain more than one "
11331 "reference to the redefined definition",
11332 xmlSchemaFormatQName(&str,
11333 ctxt->redef->refTargetNs,
11334 ctxt->redef->refName),
11335 NULL);
11336 FREE_AND_NULL(str)
11337 part = NULL;
11338 } else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11339 ((WXS_PARTICLE(part))->maxOccurs != 1))
11340 {
11341 xmlChar *str = NULL;
11342 /*
11343 * SPEC src-redefine:
11344 * (6.1.2) "The ·actual value· of both that
11345 * group's minOccurs and maxOccurs [attribute]
11346 * must be 1 (or ·absent·).
11347 */
11348 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11349 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11350 "The redefining model group definition "
11351 "'%s' must not contain a reference to the "
11352 "redefined definition with a "
11353 "maxOccurs/minOccurs other than 1",
11354 xmlSchemaFormatQName(&str,
11355 ctxt->redef->refTargetNs,
11356 ctxt->redef->refName),
11357 NULL);
11358 FREE_AND_NULL(str)
11359 part = NULL;
11360 }
11361 ctxt->redef->reference = WXS_BASIC_CAST part;
11362 ctxt->redefCounter++;
11363 }
11364 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011365 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011366 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011367 xmlSchemaParseAny(ctxt, schema, child);
11368 } else if (IS_SCHEMA(child, "choice")) {
11369 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11370 XML_SCHEMA_TYPE_CHOICE, 1);
11371 } else if (IS_SCHEMA(child, "sequence")) {
11372 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11373 XML_SCHEMA_TYPE_SEQUENCE, 1);
11374 }
11375 if (part != NULL) {
11376 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011377 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011378 else
11379 last->next = part;
11380 last = part;
11381 }
11382 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011383 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011384 if (child != NULL) {
11385 xmlSchemaPContentErr(ctxt,
11386 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011387 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011388 "(annotation?, (element | group | choice | sequence | any)*)");
11389 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011390 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011391 if ((max == 0) && (min == 0))
11392 return (NULL);
11393 if (hasRefs) {
11394 /*
11395 * We need to resolve references.
11396 */
11397 WXS_ADD_PENDING(ctxt, item);
11398 }
11399 if (withParticle)
11400 return ((xmlSchemaTreeItemPtr) particle);
11401 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011402 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +000011403}
11404
11405/**
11406 * xmlSchemaParseRestriction:
11407 * @ctxt: a schema validation context
11408 * @schema: the schema being built
11409 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +000011410 *
11411 * parse a XML schema Restriction definition
11412 * *WARNING* this interface is highly subject to change
11413 *
11414 * Returns the type definition or NULL in case of error
11415 */
11416static xmlSchemaTypePtr
11417xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011418 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000011419{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011420 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011421 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000011422 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011423
11424 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11425 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011426 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011427 type = ctxt->ctxtType;
11428 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011429
11430 /*
William M. Brack2f2a6632004-08-20 23:09:47 +000011431 * Check for illegal attributes.
11432 */
11433 attr = node->properties;
11434 while (attr != NULL) {
11435 if (attr->ns == NULL) {
11436 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11437 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011438 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011439 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011440 }
11441 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011442 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011443 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011444 }
11445 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011446 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011447 /*
11448 * Extract and validate attributes.
11449 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011450 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000011451 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011452 * Attribute
William M. Brack2f2a6632004-08-20 23:09:47 +000011453 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011454 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011455 * Extract the base type. The "base" attribute is mandatory if inside
11456 * a complex type or if redefining.
11457 *
11458 * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011459 * among its [children]), the simple type definition which is
11460 * the {content type} of the type definition ·resolved· to by
11461 * the ·actual value· of the base [attribute]"
11462 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011463 if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011464 &(type->baseNs), &(type->base)) == 0)
11465 {
11466 if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11467 xmlSchemaPMissingAttrErr(ctxt,
11468 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011469 NULL, node, "base", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011470 } else if ((ctxt->isRedefine) &&
11471 (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11472 {
11473 if (type->base == NULL) {
11474 xmlSchemaPMissingAttrErr(ctxt,
11475 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011476 NULL, node, "base", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011477 } else if ((! xmlStrEqual(type->base, type->name)) ||
11478 (! xmlStrEqual(type->baseNs, type->targetNamespace)))
11479 {
11480 xmlChar *str1 = NULL, *str2 = NULL;
11481 /*
11482 * REDEFINE: SPEC src-redefine (5)
11483 * "Within the [children], each <simpleType> must have a
11484 * <restriction> among its [children] ... the ·actual value· of
11485 * whose base [attribute] must be the same as the ·actual value·
11486 * of its own name attribute plus target namespace;"
11487 */
11488 xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011489 NULL, node, "This is a redefinition, but the QName "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011490 "value '%s' of the 'base' attribute does not match the "
11491 "type's designation '%s'",
11492 xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11493 xmlSchemaFormatQName(&str1, type->targetNamespace,
11494 type->name), NULL);
11495 FREE_AND_NULL(str1);
11496 FREE_AND_NULL(str2);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011497 /* Avoid confusion and erase the values. */
11498 type->base = NULL;
11499 type->baseNs = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011500 }
11501 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011502 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011503 /*
11504 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011505 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011506 child = node->children;
11507 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011508 /*
11509 * Add the annotation to the simple type ancestor.
11510 */
11511 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000011512 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011513 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011514 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011515 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11516 /*
11517 * Corresponds to <simpleType><restriction><simpleType>.
11518 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011519 if (IS_SCHEMA(child, "simpleType")) {
11520 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011521 /*
William M. Brack2f2a6632004-08-20 23:09:47 +000011522 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011523 * Either the base [attribute] or the simpleType [child] of the
11524 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +000011525 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011526 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000011527 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011528 NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +000011529 "The attribute 'base' and the <simpleType> child are "
11530 "mutually exclusive", NULL);
11531 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011532 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +000011533 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011534 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011535 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011536 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011537 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011538 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011539 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011540 "Either the attribute 'base' or a <simpleType> child "
11541 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000011542 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011543 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11544 /*
11545 * Corresponds to <complexType><complexContent><restriction>...
11546 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011547 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011548 * Model groups <all>, <choice> and <sequence>.
11549 */
11550 if (IS_SCHEMA(child, "all")) {
11551 type->subtypes = (xmlSchemaTypePtr)
11552 xmlSchemaParseModelGroup(ctxt, schema, child,
11553 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011554 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011555 } else if (IS_SCHEMA(child, "choice")) {
11556 type->subtypes = (xmlSchemaTypePtr)
11557 xmlSchemaParseModelGroup(ctxt,
11558 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11559 child = child->next;
11560 } else if (IS_SCHEMA(child, "sequence")) {
11561 type->subtypes = (xmlSchemaTypePtr)
11562 xmlSchemaParseModelGroup(ctxt, schema, child,
11563 XML_SCHEMA_TYPE_SEQUENCE, 1);
11564 child = child->next;
11565 /*
11566 * Model group reference <group>.
11567 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011568 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011569 type->subtypes = (xmlSchemaTypePtr)
11570 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011571 /*
11572 * Note that the reference will be resolved in
11573 * xmlSchemaResolveTypeReferences();
11574 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011575 child = child->next;
11576 }
11577 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011578 /*
11579 * Corresponds to <complexType><simpleContent><restriction>...
11580 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011581 * "1.1 the simple type definition corresponding to the <simpleType>
11582 * among the [children] of <restriction> if there is one;"
11583 */
11584 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011585 /*
11586 * We will store the to-be-restricted simple type in
11587 * type->contentTypeDef *temporarily*.
11588 */
11589 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011590 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011591 if ( type->contentTypeDef == NULL)
11592 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011593 child = child->next;
11594 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011595 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011596
11597 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011598 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011599 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011600 /*
11601 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011602 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011603 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011604
Daniel Veillard01fa6152004-06-29 17:04:39 +000011605 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011606 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011607 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011608 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011609 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11610 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +000011611 * *Single Facet Value*
11612 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011613 while ((IS_SCHEMA(child, "minInclusive")) ||
11614 (IS_SCHEMA(child, "minExclusive")) ||
11615 (IS_SCHEMA(child, "maxInclusive")) ||
11616 (IS_SCHEMA(child, "maxExclusive")) ||
11617 (IS_SCHEMA(child, "totalDigits")) ||
11618 (IS_SCHEMA(child, "fractionDigits")) ||
11619 (IS_SCHEMA(child, "pattern")) ||
11620 (IS_SCHEMA(child, "enumeration")) ||
11621 (IS_SCHEMA(child, "whiteSpace")) ||
11622 (IS_SCHEMA(child, "length")) ||
11623 (IS_SCHEMA(child, "maxLength")) ||
11624 (IS_SCHEMA(child, "minLength"))) {
11625 facet = xmlSchemaParseFacet(ctxt, schema, child);
11626 if (facet != NULL) {
11627 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011628 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011629 else
11630 lastfacet->next = facet;
11631 lastfacet = facet;
11632 lastfacet->next = NULL;
11633 }
11634 child = child->next;
11635 }
11636 /*
11637 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011638 */
11639 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011640 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11641
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011642 facet = type->facets;
11643 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011644 facetLink = (xmlSchemaFacetLinkPtr)
11645 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +000011646 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011647 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011648 xmlFree(facetLink);
11649 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011650 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011651 facetLink->facet = facet;
11652 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011653 if (lastFacetLink == NULL)
11654 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011655 else
11656 lastFacetLink->next = facetLink;
11657 lastFacetLink = facetLink;
11658 facet = facet->next;
11659 } while (facet != NULL);
11660 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011661 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011662 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11663 /*
11664 * Attribute uses/declarations.
11665 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011666 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11667 (xmlSchemaItemListPtr *) &(type->attrUses),
11668 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11669 return(NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011670 /*
11671 * Attribute wildcard.
11672 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011673 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011674 type->attributeWildcard =
11675 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011676 child = child->next;
11677 }
11678 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011679 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011680 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11681 xmlSchemaPContentErr(ctxt,
11682 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011683 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011684 "annotation?, (group | all | choice | sequence)?, "
11685 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011686 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011687 xmlSchemaPContentErr(ctxt,
11688 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011689 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011690 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11691 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11692 "length | minLength | maxLength | enumeration | whiteSpace | "
11693 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11694 } else {
11695 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011696 xmlSchemaPContentErr(ctxt,
11697 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011698 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011699 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11700 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11701 "length | minLength | maxLength | enumeration | whiteSpace | "
11702 "pattern)*))");
11703 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011704 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011705 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011706}
11707
11708/**
11709 * xmlSchemaParseExtension:
11710 * @ctxt: a schema validation context
11711 * @schema: the schema being built
11712 * @node: a subtree containing XML Schema informations
11713 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011714 * Parses an <extension>, which is found inside a
11715 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011716 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000011717 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011718 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000011719 */
11720static xmlSchemaTypePtr
11721xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011722 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000011723{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011724 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011725 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011726 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011727
11728 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11729 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011730 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011731 type = ctxt->ctxtType;
11732 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000011733
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011734 /*
11735 * Check for illegal attributes.
11736 */
11737 attr = node->properties;
11738 while (attr != NULL) {
11739 if (attr->ns == NULL) {
11740 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11741 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011742 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011743 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011744 }
11745 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011746 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011747 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011748 }
11749 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011750 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011751
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011752 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011753
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011754 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011755 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011756 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011757 if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11758 "base", &(type->baseNs), &(type->base)) == 0) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011759 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011760 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011761 XML_SCHEMAP_S4S_ATTR_MISSING,
11762 NULL, node, "base", NULL);
11763 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011764 /*
11765 * And now for the children...
11766 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011767 child = node->children;
11768 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011769 /*
11770 * Add the annotation to the type ancestor.
11771 */
11772 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000011773 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011774 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011775 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011776 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11777 /*
11778 * Corresponds to <complexType><complexContent><extension>... and:
11779 *
11780 * Model groups <all>, <choice>, <sequence> and <group>.
11781 */
11782 if (IS_SCHEMA(child, "all")) {
11783 type->subtypes = (xmlSchemaTypePtr)
11784 xmlSchemaParseModelGroup(ctxt, schema,
11785 child, XML_SCHEMA_TYPE_ALL, 1);
11786 child = child->next;
11787 } else if (IS_SCHEMA(child, "choice")) {
11788 type->subtypes = (xmlSchemaTypePtr)
11789 xmlSchemaParseModelGroup(ctxt, schema,
11790 child, XML_SCHEMA_TYPE_CHOICE, 1);
11791 child = child->next;
11792 } else if (IS_SCHEMA(child, "sequence")) {
11793 type->subtypes = (xmlSchemaTypePtr)
11794 xmlSchemaParseModelGroup(ctxt, schema,
11795 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11796 child = child->next;
11797 } else if (IS_SCHEMA(child, "group")) {
11798 type->subtypes = (xmlSchemaTypePtr)
11799 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011800 /*
11801 * Note that the reference will be resolved in
11802 * xmlSchemaResolveTypeReferences();
11803 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011804 child = child->next;
11805 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011806 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011807 if (child != NULL) {
11808 /*
11809 * Attribute uses/declarations.
11810 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011811 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11812 (xmlSchemaItemListPtr *) &(type->attrUses),
11813 XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11814 return(NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011815 /*
11816 * Attribute wildcard.
11817 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011818 if (IS_SCHEMA(child, "anyAttribute")) {
11819 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011820 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11821 child = child->next;
11822 }
11823 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011824 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011825 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11826 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011827 xmlSchemaPContentErr(ctxt,
11828 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011829 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011830 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011831 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011832 } else {
11833 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011834 xmlSchemaPContentErr(ctxt,
11835 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011836 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011837 "(annotation?, ((attribute | attributeGroup)*, "
11838 "anyAttribute?))");
11839 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011840 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011841 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011842}
11843
11844/**
11845 * xmlSchemaParseSimpleContent:
11846 * @ctxt: a schema validation context
11847 * @schema: the schema being built
11848 * @node: a subtree containing XML Schema informations
11849 *
11850 * parse a XML schema SimpleContent definition
11851 * *WARNING* this interface is highly subject to change
11852 *
11853 * Returns the type definition or NULL in case of error
11854 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011855static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011856xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011857 xmlSchemaPtr schema, xmlNodePtr node,
11858 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000011859{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011860 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011861 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011862 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011863
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011864 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11865 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011866 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011867 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011868 /* Not a component, don't create it. */
11869 type = ctxt->ctxtType;
11870 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11871 /*
11872 * Check for illegal attributes.
11873 */
11874 attr = node->properties;
11875 while (attr != NULL) {
11876 if (attr->ns == NULL) {
11877 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011878 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011879 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011880 }
11881 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011882 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011883 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011884 }
11885 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011886 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011887
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011888 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000011889
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011890 /*
11891 * And now for the children...
11892 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011893 child = node->children;
11894 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011895 /*
11896 * Add the annotation to the complex type ancestor.
11897 */
11898 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000011899 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011900 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011901 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011902 if (child == NULL) {
11903 xmlSchemaPContentErr(ctxt,
11904 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011905 NULL, node, NULL, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011906 "(annotation?, (restriction | extension))");
11907 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011908 if (child == NULL) {
11909 xmlSchemaPContentErr(ctxt,
11910 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011911 NULL, node, NULL, NULL,
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011912 "(annotation?, (restriction | extension))");
11913 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011914 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011915 xmlSchemaParseRestriction(ctxt, schema, child,
11916 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011917 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011918 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011919 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011920 xmlSchemaParseExtension(ctxt, schema, child,
11921 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011922 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011923 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011924 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011925 if (child != NULL) {
11926 xmlSchemaPContentErr(ctxt,
11927 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011928 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011929 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000011930 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011931 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000011932}
11933
11934/**
11935 * xmlSchemaParseComplexContent:
11936 * @ctxt: a schema validation context
11937 * @schema: the schema being built
11938 * @node: a subtree containing XML Schema informations
11939 *
11940 * parse a XML schema ComplexContent definition
11941 * *WARNING* this interface is highly subject to change
11942 *
11943 * Returns the type definition or NULL in case of error
11944 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011945static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011946xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011947 xmlSchemaPtr schema, xmlNodePtr node,
11948 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000011949{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011950 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011951 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011952 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011953
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011954 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11955 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011956 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011957 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011958 /* Not a component, don't create it. */
11959 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011960 /*
11961 * Check for illegal attributes.
11962 */
11963 attr = node->properties;
11964 while (attr != NULL) {
11965 if (attr->ns == NULL) {
11966 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011967 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011968 {
11969 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011970 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011971 }
11972 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11973 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011974 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011975 }
11976 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011977 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011978
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011979 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011980
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011981 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011982 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011983 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011984 if (xmlGetBooleanProp(ctxt, node, "mixed", 0)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011985 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
11986 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011987 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011988 child = node->children;
11989 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011990 /*
11991 * Add the annotation to the complex type ancestor.
11992 */
11993 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000011994 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011995 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011996 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011997 if (child == NULL) {
11998 xmlSchemaPContentErr(ctxt,
11999 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012000 NULL, node, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012001 NULL, "(annotation?, (restriction | extension))");
12002 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012003 if (child == NULL) {
12004 xmlSchemaPContentErr(ctxt,
12005 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012006 NULL, node, NULL,
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012007 NULL, "(annotation?, (restriction | extension))");
12008 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012009 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012010 xmlSchemaParseRestriction(ctxt, schema, child,
12011 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012012 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012013 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012014 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012015 xmlSchemaParseExtension(ctxt, schema, child,
12016 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012017 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012018 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012019 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012020 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012021 xmlSchemaPContentErr(ctxt,
12022 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012023 NULL, node, child,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012024 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000012025 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012026 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000012027}
12028
12029/**
12030 * xmlSchemaParseComplexType:
12031 * @ctxt: a schema validation context
12032 * @schema: the schema being built
12033 * @node: a subtree containing XML Schema informations
12034 *
12035 * parse a XML schema Complex Type definition
12036 * *WARNING* this interface is highly subject to change
12037 *
12038 * Returns the type definition or NULL in case of error
12039 */
12040static xmlSchemaTypePtr
12041xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000012042 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000012043{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012044 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000012045 xmlNodePtr child = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012046 const xmlChar *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012047 xmlAttrPtr attr;
12048 const xmlChar *attrValue;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012049#ifdef ENABLE_NAMED_LOCALS
Daniel Veillard1a380b82004-10-21 16:00:06 +000012050 char buf[40];
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012051#endif
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012052 int final = 0, block = 0, hasRestrictionOrExtension = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000012053
Daniel Veillard4255d502002-04-16 15:50:10 +000012054
12055 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12056 return (NULL);
12057
Daniel Veillard01fa6152004-06-29 17:04:39 +000012058 ctxtType = ctxt->ctxtType;
12059
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012060 if (topLevel) {
12061 attr = xmlSchemaGetPropNode(node, "name");
12062 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012063 xmlSchemaPMissingAttrErr(ctxt,
12064 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012065 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012066 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012067 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12068 return (NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012069 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012070 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012071
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012072 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012073 /*
12074 * Parse as local complex type definition.
12075 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012076#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000012077 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012078 type = xmlSchemaAddType(ctxt, schema,
12079 XML_SCHEMA_TYPE_COMPLEX,
12080 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012081 ctxt->targetNamespace, node, 0);
12082#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012083 type = xmlSchemaAddType(ctxt, schema,
12084 XML_SCHEMA_TYPE_COMPLEX,
12085 NULL, ctxt->targetNamespace, node, 0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012086#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012087 if (type == NULL)
12088 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012089 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012090 type->node = node;
12091 type->type = XML_SCHEMA_TYPE_COMPLEX;
12092 /*
12093 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012094 */
12095 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012096 /*
12097 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012098 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012099 type = xmlSchemaAddType(ctxt, schema,
12100 XML_SCHEMA_TYPE_COMPLEX,
12101 name, ctxt->targetNamespace, node, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012102 if (type == NULL)
12103 return (NULL);
12104 type->node = node;
12105 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012106 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000012107 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012108 type->targetNamespace = ctxt->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012109 /*
12110 * Handle attributes.
12111 */
12112 attr = node->properties;
12113 while (attr != NULL) {
12114 if (attr->ns == NULL) {
12115 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12116 /*
12117 * Attribute "id".
12118 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012119 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012120 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12121 /*
12122 * Attribute "mixed".
12123 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012124 if (xmlSchemaPGetBoolNodeValue(ctxt,
12125 NULL, (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012126 type->flags |= XML_SCHEMAS_TYPE_MIXED;
12127 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012128 /*
12129 * Attributes of global complex type definitions.
12130 */
12131 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12132 /* Pass. */
12133 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12134 /*
12135 * Attribute "abstract".
12136 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012137 if (xmlSchemaPGetBoolNodeValue(ctxt,
12138 NULL, (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012139 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12140 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12141 /*
12142 * Attribute "final".
12143 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012144 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012145 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012146 if (xmlSchemaPValAttrBlockFinal(attrValue,
12147 &(type->flags),
12148 -1,
12149 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12150 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12151 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012152 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012153 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012154 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012155 NULL, (xmlNodePtr) attr, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012156 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012157 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012158 } else
12159 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012160 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12161 /*
12162 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012163 */
12164 attrValue = xmlSchemaGetNodeContent(ctxt,
12165 (xmlNodePtr) attr);
12166 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012167 -1,
12168 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012169 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012170 -1, -1, -1) != 0) {
12171 xmlSchemaPSimpleTypeErr(ctxt,
12172 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012173 NULL, (xmlNodePtr) attr, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012174 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012175 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012176 } else
12177 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012178 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012179 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012180 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012181 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012182 } else {
12183 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012184 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012185 }
12186 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012187 xmlSchemaPIllegalAttrErr(ctxt,
12188 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012189 }
12190 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012191 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012192 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000012193 /*
12194 * Apply default "block" values.
12195 */
12196 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12197 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12198 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12199 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12200 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012201 if (! final) {
12202 /*
12203 * Apply default "block" values.
12204 */
12205 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12206 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12207 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12208 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12209 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012210 /*
12211 * And now for the children...
12212 */
Daniel Veillard4255d502002-04-16 15:50:10 +000012213 child = node->children;
12214 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000012215 type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012216 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012217 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012218 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000012219 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012220 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012221 * <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012222 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012223 * Specifying mixed='true' when the <simpleContent>
12224 * alternative is chosen has no effect
12225 */
William M. Bracke7091952004-05-11 15:09:58 +000012226 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12227 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012228 xmlSchemaParseSimpleContent(ctxt, schema, child,
12229 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012230 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012231 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012232 /*
12233 * <complexType><complexContent>...
12234 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012235 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012236 xmlSchemaParseComplexContent(ctxt, schema, child,
12237 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012238 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012239 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012240 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012241 * E.g <complexType><sequence>... or <complexType><attribute>... etc.
12242 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012243 * SPEC
12244 * "...the third alternative (neither <simpleContent> nor
12245 * <complexContent>) is chosen. This case is understood as shorthand
12246 * for complex content restricting the ·ur-type definition·, and the
12247 * details of the mappings should be modified as necessary.
12248 */
12249 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12250 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012251 /*
12252 * Parse model groups.
12253 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012254 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012255 type->subtypes = (xmlSchemaTypePtr)
12256 xmlSchemaParseModelGroup(ctxt, schema, child,
12257 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012258 child = child->next;
12259 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012260 type->subtypes = (xmlSchemaTypePtr)
12261 xmlSchemaParseModelGroup(ctxt, schema, child,
12262 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012263 child = child->next;
12264 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012265 type->subtypes = (xmlSchemaTypePtr)
12266 xmlSchemaParseModelGroup(ctxt, schema, child,
12267 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012268 child = child->next;
12269 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012270 type->subtypes = (xmlSchemaTypePtr)
12271 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012272 /*
12273 * Note that the reference will be resolved in
12274 * xmlSchemaResolveTypeReferences();
12275 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012276 child = child->next;
12277 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012278 /*
12279 * Parse attribute decls/refs.
12280 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012281 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12282 (xmlSchemaItemListPtr *) &(type->attrUses),
12283 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12284 return(NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012285 /*
12286 * Parse attribute wildcard.
12287 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012288 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012289 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12290 child = child->next;
12291 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012292 }
12293 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012294 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012295 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012296 NULL, node, child,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012297 NULL, "(annotation?, (simpleContent | complexContent | "
12298 "((group | all | choice | sequence)?, ((attribute | "
12299 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000012300 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012301 /*
12302 * REDEFINE: SPEC src-redefine (5)
12303 */
12304 if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12305 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012306 NULL, node, "This is a redefinition, thus the "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012307 "<complexType> must have a <restriction> or <extension> "
12308 "grand-child", NULL);
12309 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012310 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000012311 return (type);
12312}
12313
Daniel Veillard4255d502002-04-16 15:50:10 +000012314/************************************************************************
12315 * *
12316 * Validating using Schemas *
12317 * *
12318 ************************************************************************/
12319
12320/************************************************************************
12321 * *
12322 * Reading/Writing Schemas *
12323 * *
12324 ************************************************************************/
12325
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012326#if 0 /* Will be enabled if it is clear what options are needed. */
12327/**
12328 * xmlSchemaParserCtxtSetOptions:
12329 * @ctxt: a schema parser context
12330 * @options: a combination of xmlSchemaParserOption
12331 *
12332 * Sets the options to be used during the parse.
12333 *
12334 * Returns 0 in case of success, -1 in case of an
12335 * API error.
12336 */
12337static int
12338xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12339 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012340
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012341{
12342 int i;
12343
12344 if (ctxt == NULL)
12345 return (-1);
12346 /*
12347 * WARNING: Change the start value if adding to the
12348 * xmlSchemaParseOption.
12349 */
12350 for (i = 1; i < (int) sizeof(int) * 8; i++) {
12351 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012352 return (-1);
12353 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012354 }
12355 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012356 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012357}
12358
12359/**
12360 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012361 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012362 *
12363 * Returns the option combination of the parser context.
12364 */
12365static int
12366xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012367
12368{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012369 if (ctxt == NULL)
12370 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012371 else
12372 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012373}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012374#endif
12375
Daniel Veillard4255d502002-04-16 15:50:10 +000012376/**
12377 * xmlSchemaNewParserCtxt:
12378 * @URL: the location of the schema
12379 *
12380 * Create an XML Schemas parse context for that file/resource expected
12381 * to contain an XML Schemas file.
12382 *
12383 * Returns the parser context or NULL in case of error
12384 */
12385xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012386xmlSchemaNewParserCtxt(const char *URL)
12387{
Daniel Veillard4255d502002-04-16 15:50:10 +000012388 xmlSchemaParserCtxtPtr ret;
12389
12390 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012391 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000012392
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012393 ret = xmlSchemaParserCtxtCreate();
12394 if (ret == NULL)
12395 return(NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012396 ret->dict = xmlDictCreate();
12397 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012398 return (ret);
12399}
12400
12401/**
Daniel Veillard6045c902002-10-09 21:13:59 +000012402 * xmlSchemaNewMemParserCtxt:
12403 * @buffer: a pointer to a char array containing the schemas
12404 * @size: the size of the array
12405 *
12406 * Create an XML Schemas parse context for that memory buffer expected
12407 * to contain an XML Schemas file.
12408 *
12409 * Returns the parser context or NULL in case of error
12410 */
12411xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012412xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12413{
Daniel Veillard6045c902002-10-09 21:13:59 +000012414 xmlSchemaParserCtxtPtr ret;
12415
12416 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012417 return (NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012418 ret = xmlSchemaParserCtxtCreate();
12419 if (ret == NULL)
12420 return(NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000012421 ret->buffer = buffer;
12422 ret->size = size;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012423 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000012424 return (ret);
12425}
12426
12427/**
Daniel Veillard9d751502003-10-29 13:21:47 +000012428 * xmlSchemaNewDocParserCtxt:
12429 * @doc: a preparsed document tree
12430 *
12431 * Create an XML Schemas parse context for that document.
12432 * NB. The document may be modified during the parsing process.
12433 *
12434 * Returns the parser context or NULL in case of error
12435 */
12436xmlSchemaParserCtxtPtr
12437xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12438{
12439 xmlSchemaParserCtxtPtr ret;
12440
12441 if (doc == NULL)
12442 return (NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012443 ret = xmlSchemaParserCtxtCreate();
12444 if (ret == NULL)
12445 return(NULL);
Daniel Veillard9d751502003-10-29 13:21:47 +000012446 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000012447 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000012448 /* The application has responsibility for the document */
12449 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000012450
12451 return (ret);
12452}
12453
12454/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012455 * xmlSchemaFreeParserCtxt:
12456 * @ctxt: the schema parser context
12457 *
12458 * Free the resources associated to the schema parser context
12459 */
12460void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012461xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12462{
Daniel Veillard4255d502002-04-16 15:50:10 +000012463 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012464 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000012465 if (ctxt->doc != NULL && !ctxt->preserve)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012466 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012467 if (ctxt->vctxt != NULL) {
12468 xmlSchemaFreeValidCtxt(ctxt->vctxt);
12469 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012470 if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12471 xmlSchemaConstructionCtxtFree(ctxt->constructor);
12472 ctxt->constructor = NULL;
12473 ctxt->ownsConstructor = 0;
12474 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012475 if (ctxt->attrProhibs != NULL)
12476 xmlSchemaItemListFree(ctxt->attrProhibs);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012477 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000012478 xmlFree(ctxt);
12479}
12480
12481/************************************************************************
12482 * *
12483 * Building the content models *
12484 * *
12485 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012486
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012487static void
12488xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012489 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012490{
Daniel Veillarda980bef2005-07-18 21:34:03 +000012491 xmlAutomataStatePtr start, tmp;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012492 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012493 xmlSchemaSubstGroupPtr substGroup;
12494 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012495
12496 elemDecl = (xmlSchemaElementPtr) particle->children;
12497 /*
12498 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012499 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012500 start = pctxt->state;
Daniel Veillarda980bef2005-07-18 21:34:03 +000012501 if (end == NULL)
12502 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012503 substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012504 if (substGroup == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012505 xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012506 XML_SCHEMAP_INTERNAL,
12507 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12508 "declaration is marked having a subst. group but none "
12509 "available.\n", elemDecl->name, NULL);
12510 return;
12511 }
Daniel Veillarda980bef2005-07-18 21:34:03 +000012512 if (counter >= 0) {
12513 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012514 * NOTE that we put the declaration in, even if it's abstract.
12515 * However, an error will be raised during *validation* if an element
12516 * information item shall be validated against an abstract element
12517 * declaration.
Daniel Veillarda980bef2005-07-18 21:34:03 +000012518 */
12519 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12520 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12521 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12522 /*
12523 * Add subst. group members.
12524 */
12525 for (i = 0; i < substGroup->members->nbItems; i++) {
12526 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12527 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12528 member->name, member->targetNamespace, member);
12529 }
12530 } else if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012531 /*
12532 * NOTE that we put the declaration in, even if it's abstract,
12533 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012534 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012535 xmlAutomataNewTransition2(pctxt->am,
12536 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012537 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12538 /*
12539 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012540 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012541 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012542 member = (xmlSchemaElementPtr) substGroup->members->items[i];
Daniel Veillarda980bef2005-07-18 21:34:03 +000012543 tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12544 member->name, member->targetNamespace,
12545 1, 1, member);
12546 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012547 }
12548 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012549 xmlAutomataStatePtr hop;
12550 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12551 UNBOUNDED : particle->maxOccurs - 1;
12552 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12553
12554 counter =
12555 xmlAutomataNewCounter(pctxt->am, minOccurs,
12556 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012557 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012558
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012559 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012560 xmlAutomataNewTransition2(pctxt->am,
12561 start, NULL,
12562 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012563 hop);
12564 /*
Daniel Veillarda980bef2005-07-18 21:34:03 +000012565 * Add subst. group members.
12566 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012567 for (i = 0; i < substGroup->members->nbItems; i++) {
12568 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12569 xmlAutomataNewEpsilon(pctxt->am,
12570 xmlAutomataNewTransition2(pctxt->am,
12571 start, NULL,
12572 member->name, member->targetNamespace, member),
12573 hop);
12574 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012575 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12576 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12577 }
12578 if (particle->minOccurs == 0)
12579 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012580 pctxt->state = end;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012581}
12582
12583static void
12584xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12585 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012586{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012587 if (((xmlSchemaElementPtr) particle->children)->flags &
12588 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012589 /*
12590 * Substitution groups.
12591 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000012592 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012593 } else {
12594 xmlSchemaElementPtr elemDecl;
12595 xmlAutomataStatePtr start;
12596
12597 elemDecl = (xmlSchemaElementPtr) particle->children;
12598
12599 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012600 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012601 if (particle->maxOccurs == 1) {
12602 start = ctxt->state;
12603 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012604 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12605 } else if ((particle->maxOccurs >= UNBOUNDED) &&
12606 (particle->minOccurs < 2)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012607 /* Special case. */
Kasimier T. Buchcik7ca5aed2005-12-12 15:13:40 +000012608 start = ctxt->state;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012609 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Kasimier T. Buchcik7ca5aed2005-12-12 15:13:40 +000012610 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12611 ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12612 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012613 } else {
12614 int counter;
12615 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12616 UNBOUNDED : particle->maxOccurs - 1;
12617 int minOccurs = particle->minOccurs < 1 ?
12618 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012619
12620 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012621 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12622 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12623 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12624 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12625 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12626 NULL, counter);
12627 }
12628 if (particle->minOccurs == 0)
12629 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12630 }
12631}
12632
Daniel Veillard4255d502002-04-16 15:50:10 +000012633/**
12634 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000012635 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012636 * @particle: the particle component
12637 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000012638 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012639 * Create the automaton for the {content type} of a complex type.
12640 *
Daniel Veillard4255d502002-04-16 15:50:10 +000012641 */
12642static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012643xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012644 xmlSchemaParticlePtr particle)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012645{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012646 if (particle == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012647 PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012648 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000012649 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012650 if (particle->children == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012651 /*
12652 * Just return in this case. A missing "term" of the particle
12653 * might arise due to an invalid "term" component.
12654 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012655 return;
12656 }
12657
12658 switch (particle->children->type) {
12659 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012660 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012661 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012662 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000012663
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012664 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012665
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012666 start = pctxt->state;
12667 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012668
12669 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012670 if (wild->any == 1) {
12671 /*
12672 * We need to add both transitions:
12673 *
12674 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012675 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012676 pctxt->state =
12677 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012678 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012679 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012680 /*
12681 * 2. the {"*"} for elements in no namespace.
12682 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012683 pctxt->state =
12684 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012685 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012686 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012687
12688 } else if (wild->nsSet != NULL) {
12689 ns = wild->nsSet;
12690 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012691 pctxt->state = start;
12692 pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12693 pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12694 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012695 ns = ns->next;
12696 } while (ns != NULL);
12697
12698 } else if (wild->negNsSet != NULL) {
Daniel Veillard6e65e152005-08-09 11:09:52 +000012699 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12700 start, end, BAD_CAST "*", wild->negNsSet->value,
12701 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012702 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012703 } else {
12704 int counter;
12705 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012706 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012707 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012708 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012709 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012710
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012711 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12712 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012713 if (wild->any == 1) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012714 pctxt->state =
12715 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012716 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012717 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12718 pctxt->state =
12719 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012720 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012721 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012722 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012723 ns = wild->nsSet;
12724 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012725 pctxt->state =
12726 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012727 start, NULL, BAD_CAST "*", ns->value, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012728 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012729 ns = ns->next;
12730 } while (ns != NULL);
12731
12732 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012733 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
Daniel Veillard9efc4762005-07-19 14:33:55 +000012734 start, hop, BAD_CAST "*", wild->negNsSet->value,
12735 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012736 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012737 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12738 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012739 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012740 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012741 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012742 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012743 pctxt->state = end;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012744 break;
12745 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012746 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012747 xmlSchemaBuildContentModelForElement(pctxt, particle);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012748 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012749 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012750 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012751
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012752 /*
12753 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012754 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012755 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012756 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12757 sub = particle->children->children;
12758 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012759 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012760 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012761 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012762 }
12763 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012764 xmlAutomataStatePtr oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012765
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012766 if (particle->maxOccurs >= UNBOUNDED) {
12767 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012768 xmlAutomataStatePtr tmp;
12769 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012770
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012771 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012772 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012773 oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012774
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012775 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012776 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000012777
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012778 sub = particle->children->children;
12779 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012780 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012781 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012782 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012783 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012784 tmp = pctxt->state;
12785 xmlAutomataNewCountedTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012786 oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012787 pctxt->state =
12788 xmlAutomataNewCounterTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012789 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000012790
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012791 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012792 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Daniel Veillardafc05b62005-07-17 06:11:19 +000012793 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012794 oldstate = pctxt->state;
Daniel Veillardafc05b62005-07-17 06:11:19 +000012795
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012796 sub = particle->children->children;
12797 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012798 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012799 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012800 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012801 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012802 xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012803 oldstate);
Daniel Veillardafc05b62005-07-17 06:11:19 +000012804 /*
12805 * epsilon needed to block previous trans from
12806 * being allowed to enter back from another
12807 * construct
12808 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012809 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12810 pctxt->state, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012811 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012812 xmlAutomataNewEpsilon(pctxt->am,
12813 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012814 }
12815 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012816 } else if ((particle->maxOccurs > 1)
12817 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012818 xmlAutomataStatePtr tmp;
12819 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012820
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012821 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012822 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012823 oldstate = pctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000012824
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012825 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012826 particle->minOccurs - 1,
12827 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012828
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012829 sub = particle->children->children;
12830 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012831 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012832 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012833 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012834 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012835 tmp = pctxt->state;
12836 xmlAutomataNewCountedTrans(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012837 tmp, oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012838 pctxt->state =
12839 xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012840 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012841 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012842 xmlAutomataNewEpsilon(pctxt->am,
12843 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012844 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012845 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012846 sub = particle->children->children;
12847 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012848 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012849 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012850 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012851 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012852 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012853 xmlAutomataNewEpsilon(pctxt->am, oldstate,
12854 pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012855 }
12856 }
12857 }
12858 break;
12859 }
12860 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012861 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012862 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000012863
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012864 start = pctxt->state;
12865 end = xmlAutomataNewState(pctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000012866
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012867 /*
12868 * iterate over the subtypes and remerge the end with an
12869 * epsilon transition
12870 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012871 if (particle->maxOccurs == 1) {
12872 sub = particle->children->children;
12873 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012874 pctxt->state = start;
12875 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012876 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012877 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012878 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012879 }
12880 } else {
12881 int counter;
Daniel Veillardafc05b62005-07-17 06:11:19 +000012882 xmlAutomataStatePtr hop, base;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012883 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12884 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012885 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012886 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000012887
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012888 /*
12889 * use a counter to keep track of the number of transtions
12890 * which went through the choice.
12891 */
12892 counter =
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012893 xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12894 hop = xmlAutomataNewState(pctxt->am);
12895 base = xmlAutomataNewState(pctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000012896
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012897 sub = particle->children->children;
12898 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012899 pctxt->state = base;
12900 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012901 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012902 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012903 sub = sub->next;
Daniel Veillarda980bef2005-07-18 21:34:03 +000012904 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012905 xmlAutomataNewEpsilon(pctxt->am, start, base);
12906 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
12907 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012908 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012909 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012910 xmlAutomataNewEpsilon(pctxt->am, start, end);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012911 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012912 pctxt->state = end;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012913 break;
12914 }
12915 case XML_SCHEMA_TYPE_ALL:{
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +000012916 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012917 xmlSchemaParticlePtr sub;
12918 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012919 int lax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012920
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012921 sub = (xmlSchemaParticlePtr) particle->children->children;
12922 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012923 break;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012924 start = pctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012925 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012926 pctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012927
12928 elemDecl = (xmlSchemaElementPtr) sub->children;
12929 if (elemDecl == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012930 PERROR_INT("xmlSchemaBuildAContentModel",
12931 "<element> particle has no term");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012932 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012933 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012934 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012935 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000012936 * {particles} of the group must be 0 or 1; this is
12937 * already ensured during the parse of the content of
12938 * <all>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012939 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000012940 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12941 int counter;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012942
Daniel Veillarda980bef2005-07-18 21:34:03 +000012943 /*
12944 * This is an abstract group, we need to share
12945 * the same counter for all the element transitions
12946 * derived from the group
12947 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012948 counter = xmlAutomataNewCounter(pctxt->am,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012949 sub->minOccurs, sub->maxOccurs);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012950 xmlSchemaBuildContentModelForSubstGroup(pctxt,
12951 sub, counter, pctxt->state);
Daniel Veillarda980bef2005-07-18 21:34:03 +000012952 } else {
12953 if ((sub->minOccurs == 1) &&
12954 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012955 xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
12956 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012957 elemDecl->name,
12958 elemDecl->targetNamespace,
12959 1, 1, elemDecl);
12960 } else if ((sub->minOccurs == 0) &&
12961 (sub->maxOccurs == 1)) {
12962
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012963 xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
12964 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012965 elemDecl->name,
12966 elemDecl->targetNamespace,
12967 0,
12968 1,
12969 elemDecl);
12970 }
12971 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012972 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012973 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012974 lax = particle->minOccurs == 0;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012975 pctxt->state =
12976 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012977 break;
12978 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012979 case XML_SCHEMA_TYPE_GROUP:
12980 /*
12981 * If we hit a model group definition, then this means that
12982 * it was empty, thus was not substituted for the containing
12983 * model group. Just do nothing in this case.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012984 * TODO: But the group should be substituted and not occur at
12985 * all in the content model at this point. Fix this.
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012986 */
12987 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012988 default:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012989 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
12990 "xmlSchemaBuildAContentModel",
12991 "found unexpected term of type '%s' in content model",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012992 WXS_ITEM_TYPE_NAME(particle->children), NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012993 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000012994 }
12995}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012996
Daniel Veillard4255d502002-04-16 15:50:10 +000012997/**
12998 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000012999 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013000 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000013001 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000013002 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013003 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000013004 */
13005static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013006xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013007 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013008{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013009 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13010 (type->contModel != NULL) ||
13011 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13012 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013013 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013014
13015#ifdef DEBUG_CONTENT
13016 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013017 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013018#endif
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013019 ctxt->am = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013020 ctxt->am = xmlNewAutomata();
13021 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013022 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013023 "Cannot create automata for complex type %s\n", type->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013024 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000013025 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000013026 ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013027 /*
13028 * Build the automaton.
13029 */
13030 xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
Daniel Veillard4255d502002-04-16 15:50:10 +000013031 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013032 type->contModel = xmlAutomataCompile(ctxt->am);
13033 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013034 xmlSchemaPCustomErr(ctxt,
13035 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013036 WXS_BASIC_CAST type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013037 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013038 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013039 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013040 XML_SCHEMAP_NOT_DETERMINISTIC,
13041 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013042 WXS_BASIC_CAST type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013043 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000013044 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000013045#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013046 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013047 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013048 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000013049#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000013050 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000013051 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013052 xmlFreeAutomata(ctxt->am);
13053 ctxt->am = NULL;
13054}
13055
13056/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013057 * xmlSchemaResolveElementReferences:
Daniel Veillard4255d502002-04-16 15:50:10 +000013058 * @elem: the schema element context
13059 * @ctxt: the schema parser context
13060 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000013061 * Resolves the references of an element declaration
13062 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013063 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000013064 */
13065static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013066xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13067 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000013068{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013069 if ((ctxt == NULL) || (elemDecl == NULL) ||
13070 ((elemDecl != NULL) &&
13071 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013072 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013073 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013074
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013075 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013076 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013077
13078 /* (type definition) ... otherwise the type definition ·resolved·
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013079 * to by the ·actual value· of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013080 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013081 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013082 elemDecl->namedTypeNs);
13083 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013084 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013085 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013086 WXS_BASIC_CAST elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013087 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013088 XML_SCHEMA_TYPE_BASIC, "type definition");
13089 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013090 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013091 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013092 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013093 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013094
Daniel Veillardc0826a72004-08-10 14:17:33 +000013095 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013096 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013097 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000013098 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013099 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13100 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013101 if (substHead == NULL) {
13102 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013103 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013104 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013105 "substitutionGroup", elemDecl->substGroup,
13106 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013107 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013108 xmlSchemaResolveElementReferences(substHead, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013109 /*
13110 * Set the "substitution group affiliation".
13111 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013112 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013113 WXS_SUBST_HEAD(elemDecl) = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013114 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013115 * The type definitions is set to:
13116 * SPEC "...the {type definition} of the element
13117 * declaration ·resolved· to by the ·actual value·
13118 * of the substitutionGroup [attribute], if present"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013119 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013120 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013121 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013122 }
13123 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013124 /*
13125 * SPEC "The definition of anyType serves as the default type definition
13126 * for element declarations whose XML representation does not specify one."
13127 */
13128 if ((elemDecl->subtypes == NULL) &&
13129 (elemDecl->namedType == NULL) &&
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013130 (elemDecl->substGroup == NULL))
13131 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000013132}
13133
13134/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013135 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000013136 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013137 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000013138 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013139 * Checks and builds the "member type definitions" property of the union
13140 * simple type. This handles part (1), part (2) is done in
13141 * xmlSchemaFinishMemberTypeDefinitionsProperty()
13142 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000013143 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000013144 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013145static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013146xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13147 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000013148{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013149
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013150 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013151 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000013152
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013153 /*
13154 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13155 * define the explicit members as the type definitions ·resolved·
13156 * to by the items in the ·actual value· of the memberTypes [attribute],
13157 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013158 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000013159 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013160 /*
13161 * Resolve references.
13162 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013163 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013164 lastLink = NULL;
13165 while (link != NULL) {
13166 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013167
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013168 name = ((xmlSchemaQNameRefPtr) link->type)->name;
13169 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13170
13171 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013172 if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013173 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013174 WXS_BASIC_CAST type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013175 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13176 /*
13177 * Remove the member type link.
13178 */
13179 if (lastLink == NULL)
13180 type->memberTypes = link->next;
13181 else
13182 lastLink->next = link->next;
13183 newLink = link;
13184 link = link->next;
13185 xmlFree(newLink);
13186 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013187 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013188 lastLink = link;
13189 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013190 }
13191 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013192 /*
13193 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013194 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013195 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013196 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013197 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13198 if (link == NULL) {
13199 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13200 return (-1);
13201 }
13202 link->type = memberType;
13203 link->next = NULL;
13204 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013205 type->memberTypes = link;
13206 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000013207 lastLink->next = link;
13208 lastLink = link;
13209 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013210 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013211 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000013212}
13213
Daniel Veillard4255d502002-04-16 15:50:10 +000013214/**
Daniel Veillard3646d642004-06-02 19:19:14 +000013215 * xmlSchemaIsDerivedFromBuiltInType:
13216 * @ctxt: the schema parser context
13217 * @type: the type definition
13218 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013219 *
Daniel Veillard3646d642004-06-02 19:19:14 +000013220 *
13221 * Returns 1 if the type has the given value type, or
13222 * is derived from such a type.
13223 */
William M. Brack803812b2004-06-03 02:11:24 +000013224static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013225xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000013226{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013227 if (type == NULL)
13228 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013229 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013230 return (0);
13231 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13232 if (type->builtInType == valType)
13233 return(1);
13234 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13235 (type->builtInType == XML_SCHEMAS_ANYTYPE))
13236 return (0);
13237 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard6a0baa02005-12-10 11:11:12 +000013238 }
13239 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000013240}
13241
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013242#if 0
13243/**
13244 * xmlSchemaIsDerivedFromBuiltInType:
13245 * @ctxt: the schema parser context
13246 * @type: the type definition
13247 * @valType: the value type
13248 *
13249 *
13250 * Returns 1 if the type has the given value type, or
13251 * is derived from such a type.
13252 */
13253static int
13254xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13255{
13256 if (type == NULL)
13257 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013258 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013259 return (0);
13260 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13261 if (type->builtInType == valType)
13262 return(1);
13263 return (0);
13264 } else
13265 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13266
13267 return (0);
13268}
13269#endif
13270
13271static xmlSchemaTypePtr
13272xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13273{
13274 if (type == NULL)
13275 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013276 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013277 return (NULL);
13278 if (type->type == XML_SCHEMA_TYPE_BASIC)
Daniel Veillard6a0baa02005-12-10 11:11:12 +000013279 return(type);
13280 return(xmlSchemaQueryBuiltInType(type->subtypes));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013281}
13282
Daniel Veillard3646d642004-06-02 19:19:14 +000013283/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013284 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013285 * @type: the simpleType definition
13286 *
13287 * Returns the primitive type of the given type or
13288 * NULL in case of error.
13289 */
13290static xmlSchemaTypePtr
13291xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13292{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013293
Daniel Veillard01fa6152004-06-29 17:04:39 +000013294 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013295 /*
13296 * Note that anySimpleType is actually not a primitive type
13297 * but we need that here.
13298 */
13299 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13300 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013301 return (type);
13302 type = type->baseType;
13303 }
13304
13305 return (NULL);
13306}
13307
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013308#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013309/**
13310 * xmlSchemaGetBuiltInTypeAncestor:
13311 * @type: the simpleType definition
13312 *
13313 * Returns the primitive type of the given type or
13314 * NULL in case of error.
13315 */
13316static xmlSchemaTypePtr
13317xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13318{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013319 if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013320 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013321 while (type != NULL) {
13322 if (type->type == XML_SCHEMA_TYPE_BASIC)
13323 return (type);
13324 type = type->baseType;
13325 }
13326
13327 return (NULL);
13328}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013329#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013330
Daniel Veillard01fa6152004-06-29 17:04:39 +000013331/**
Daniel Veillard50355f02004-06-08 17:52:16 +000013332 * xmlSchemaCloneWildcardNsConstraints:
13333 * @ctxt: the schema parser context
13334 * @dest: the destination wildcard
13335 * @source: the source wildcard
13336 *
13337 * Clones the namespace constraints of source
13338 * and assignes them to dest.
13339 * Returns -1 on internal error, 0 otherwise.
13340 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013341static int
13342xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013343 xmlSchemaWildcardPtr dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013344 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000013345{
13346 xmlSchemaWildcardNsPtr cur, tmp, last;
13347
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013348 if ((source == NULL) || (dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013349 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013350 dest->any = source->any;
Daniel Veillard3646d642004-06-02 19:19:14 +000013351 cur = source->nsSet;
13352 last = NULL;
13353 while (cur != NULL) {
13354 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13355 if (tmp == NULL)
13356 return(-1);
13357 tmp->value = cur->value;
13358 if (last == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013359 dest->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013360 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013361 last->next = tmp;
13362 last = tmp;
13363 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013364 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013365 if (dest->negNsSet != NULL)
13366 xmlSchemaFreeWildcardNsSet(dest->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000013367 if (source->negNsSet != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013368 dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13369 if (dest->negNsSet == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013370 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013371 dest->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000013372 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013373 dest->negNsSet = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000013374 return(0);
13375}
13376
Daniel Veillard50355f02004-06-08 17:52:16 +000013377/**
13378 * xmlSchemaUnionWildcards:
13379 * @ctxt: the schema parser context
13380 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013381 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013382 *
13383 * Unions the namespace constraints of the given wildcards.
13384 * @completeWild will hold the resulting union.
13385 * Returns a positive error code on failure, -1 in case of an
13386 * internal error, 0 otherwise.
13387 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013388static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013389xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000013390 xmlSchemaWildcardPtr completeWild,
13391 xmlSchemaWildcardPtr curWild)
13392{
13393 xmlSchemaWildcardNsPtr cur, curB, tmp;
13394
13395 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013396 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013397 * value.
13398 */
13399 if ((completeWild->any == curWild->any) &&
13400 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13401 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013402
Daniel Veillard3646d642004-06-02 19:19:14 +000013403 if ((completeWild->negNsSet == NULL) ||
13404 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013405
Daniel Veillard3646d642004-06-02 19:19:14 +000013406 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000013407 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013408
13409 /*
13410 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000013411 */
13412 cur = completeWild->nsSet;
13413 while (cur != NULL) {
13414 found = 0;
13415 curB = curWild->nsSet;
13416 while (curB != NULL) {
13417 if (cur->value == curB->value) {
13418 found = 1;
13419 break;
13420 }
13421 curB = curB->next;
13422 }
13423 if (!found)
13424 break;
13425 cur = cur->next;
13426 }
13427 if (found)
13428 return(0);
13429 } else
13430 return(0);
13431 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013432 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013433 /*
13434 * 2 If either O1 or O2 is any, then any must be the value
13435 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013436 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013437 if (completeWild->any == 0) {
13438 completeWild->any = 1;
13439 if (completeWild->nsSet != NULL) {
13440 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13441 completeWild->nsSet = NULL;
13442 }
13443 if (completeWild->negNsSet != NULL) {
13444 xmlFree(completeWild->negNsSet);
13445 completeWild->negNsSet = NULL;
13446 }
13447 }
Daniel Veillard50355f02004-06-08 17:52:16 +000013448 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013449 }
13450 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013451 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000013452 * then the union of those sets must be the value.
13453 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013454 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013455 int found;
13456 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013457
Daniel Veillard3646d642004-06-02 19:19:14 +000013458 cur = curWild->nsSet;
13459 start = completeWild->nsSet;
13460 while (cur != NULL) {
13461 found = 0;
13462 curB = start;
13463 while (curB != NULL) {
13464 if (cur->value == curB->value) {
13465 found = 1;
13466 break;
13467 }
13468 curB = curB->next;
13469 }
13470 if (!found) {
13471 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013472 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013473 return (-1);
13474 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013475 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000013476 completeWild->nsSet = tmp;
13477 }
13478 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013479 }
13480
Daniel Veillard3646d642004-06-02 19:19:14 +000013481 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013482 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013483 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013484 * 4 If the two are negations of different values (namespace names
Daniel Veillard3646d642004-06-02 19:19:14 +000013485 * or ·absent·), then a pair of not and ·absent· must be the value.
13486 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013487 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013488 (curWild->negNsSet != NULL) &&
13489 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
13490 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000013491
13492 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013493 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013494 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013495 * 5.
13496 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013497 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013498 (completeWild->negNsSet->value != NULL) &&
13499 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013500 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013501 (curWild->negNsSet->value != NULL) &&
13502 (completeWild->nsSet != NULL))) {
13503
13504 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013505
Daniel Veillard3646d642004-06-02 19:19:14 +000013506 if (completeWild->nsSet != NULL) {
13507 cur = completeWild->nsSet;
13508 curB = curWild->negNsSet;
13509 } else {
13510 cur = curWild->nsSet;
13511 curB = completeWild->negNsSet;
13512 }
13513 nsFound = 0;
13514 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013515 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013516 absentFound = 1;
13517 else if (cur->value == curB->value)
13518 nsFound = 1;
13519 if (nsFound && absentFound)
13520 break;
13521 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013522 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013523
13524 if (nsFound && absentFound) {
13525 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013526 * 5.1 If the set S includes both the negated namespace
Daniel Veillard3646d642004-06-02 19:19:14 +000013527 * name and ·absent·, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013528 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013529 completeWild->any = 1;
13530 if (completeWild->nsSet != NULL) {
13531 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13532 completeWild->nsSet = NULL;
13533 }
13534 if (completeWild->negNsSet != NULL) {
13535 xmlFree(completeWild->negNsSet);
13536 completeWild->negNsSet = NULL;
13537 }
13538 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013539 /*
13540 * 5.2 If the set S includes the negated namespace name
13541 * but not ·absent·, then a pair of not and ·absent· must
Daniel Veillard3646d642004-06-02 19:19:14 +000013542 * be the value.
13543 */
13544 if (completeWild->nsSet != NULL) {
13545 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13546 completeWild->nsSet = NULL;
13547 }
13548 if (completeWild->negNsSet == NULL) {
13549 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13550 if (completeWild->negNsSet == NULL)
13551 return (-1);
13552 }
13553 completeWild->negNsSet->value = NULL;
13554 } else if ((!nsFound) && absentFound) {
13555 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013556 * 5.3 If the set S includes ·absent· but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000013557 * namespace name, then the union is not expressible.
13558 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013559 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000013560 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013561 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013562 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000013563 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000013564 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013565 /*
13566 * 5.4 If the set S does not include either the negated namespace
13567 * name or ·absent·, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000013568 * and a namespace name must be the value.
13569 */
13570 if (completeWild->negNsSet == NULL) {
13571 if (completeWild->nsSet != NULL) {
13572 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13573 completeWild->nsSet = NULL;
13574 }
13575 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13576 if (completeWild->negNsSet == NULL)
13577 return (-1);
13578 completeWild->negNsSet->value = curWild->negNsSet->value;
13579 }
13580 }
13581 return (0);
13582 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013583 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013584 * 6.
13585 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013586 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013587 (completeWild->negNsSet->value == NULL) &&
13588 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013589 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013590 (curWild->negNsSet->value == NULL) &&
13591 (completeWild->nsSet != NULL))) {
13592
13593 if (completeWild->nsSet != NULL) {
13594 cur = completeWild->nsSet;
13595 } else {
13596 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013597 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013598 while (cur != NULL) {
13599 if (cur->value == NULL) {
13600 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013601 * 6.1 If the set S includes ·absent·, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013602 * value.
13603 */
13604 completeWild->any = 1;
13605 if (completeWild->nsSet != NULL) {
13606 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13607 completeWild->nsSet = NULL;
13608 }
13609 if (completeWild->negNsSet != NULL) {
13610 xmlFree(completeWild->negNsSet);
13611 completeWild->negNsSet = NULL;
13612 }
13613 return (0);
13614 }
13615 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013616 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013617 if (completeWild->negNsSet == NULL) {
13618 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013619 * 6.2 If the set S does not include ·absent·, then a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000013620 * and ·absent· must be the value.
13621 */
13622 if (completeWild->nsSet != NULL) {
13623 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13624 completeWild->nsSet = NULL;
13625 }
13626 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13627 if (completeWild->negNsSet == NULL)
13628 return (-1);
13629 completeWild->negNsSet->value = NULL;
13630 }
13631 return (0);
13632 }
13633 return (0);
13634
13635}
13636
Daniel Veillard50355f02004-06-08 17:52:16 +000013637/**
13638 * xmlSchemaIntersectWildcards:
13639 * @ctxt: the schema parser context
13640 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013641 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013642 *
13643 * Intersects the namespace constraints of the given wildcards.
13644 * @completeWild will hold the resulting intersection.
13645 * Returns a positive error code on failure, -1 in case of an
13646 * internal error, 0 otherwise.
13647 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013648static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013649xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000013650 xmlSchemaWildcardPtr completeWild,
13651 xmlSchemaWildcardPtr curWild)
13652{
William M. Brack803812b2004-06-03 02:11:24 +000013653 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013654
13655 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013656 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013657 * value.
13658 */
13659 if ((completeWild->any == curWild->any) &&
13660 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13661 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013662
Daniel Veillard3646d642004-06-02 19:19:14 +000013663 if ((completeWild->negNsSet == NULL) ||
13664 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013665
Daniel Veillard3646d642004-06-02 19:19:14 +000013666 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000013667 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013668
13669 /*
13670 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000013671 */
13672 cur = completeWild->nsSet;
13673 while (cur != NULL) {
13674 found = 0;
13675 curB = curWild->nsSet;
13676 while (curB != NULL) {
13677 if (cur->value == curB->value) {
13678 found = 1;
13679 break;
13680 }
13681 curB = curB->next;
13682 }
13683 if (!found)
13684 break;
13685 cur = cur->next;
13686 }
13687 if (found)
13688 return(0);
13689 } else
13690 return(0);
13691 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013692 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013693 /*
13694 * 2 If either O1 or O2 is any, then the other must be the value.
13695 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013696 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013697 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013698 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000013699 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013700 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013701 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013702 * 3 If either O1 or O2 is a pair of not and a value (a namespace
13703 * name or ·absent·) and the other is a set of (namespace names or
13704 * ·absent·), then that set, minus the negated value if it was in
Daniel Veillard3646d642004-06-02 19:19:14 +000013705 * the set, minus ·absent· if it was in the set, must be the value.
13706 */
13707 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13708 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13709 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013710
Daniel Veillard3646d642004-06-02 19:19:14 +000013711 if (completeWild->nsSet == NULL) {
13712 neg = completeWild->negNsSet->value;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013713 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
Daniel Veillard3646d642004-06-02 19:19:14 +000013714 return(-1);
13715 } else
13716 neg = curWild->negNsSet->value;
13717 /*
13718 * Remove absent and negated.
13719 */
13720 prev = NULL;
13721 cur = completeWild->nsSet;
13722 while (cur != NULL) {
13723 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013724 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013725 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013726 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013727 prev->next = cur->next;
13728 xmlFree(cur);
13729 break;
13730 }
13731 prev = cur;
13732 cur = cur->next;
13733 }
13734 if (neg != NULL) {
13735 prev = NULL;
13736 cur = completeWild->nsSet;
13737 while (cur != NULL) {
13738 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013739 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013740 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013741 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013742 prev->next = cur->next;
13743 xmlFree(cur);
13744 break;
13745 }
13746 prev = cur;
13747 cur = cur->next;
13748 }
13749 }
13750
13751 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013752 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013753 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013754 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000013755 * then the intersection of those sets must be the value.
13756 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013757 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013758 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013759
Daniel Veillard3646d642004-06-02 19:19:14 +000013760 cur = completeWild->nsSet;
13761 prev = NULL;
13762 while (cur != NULL) {
13763 found = 0;
13764 curB = curWild->nsSet;
13765 while (curB != NULL) {
13766 if (cur->value == curB->value) {
13767 found = 1;
13768 break;
13769 }
13770 curB = curB->next;
13771 }
13772 if (!found) {
13773 if (prev == NULL)
13774 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013775 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013776 prev->next = cur->next;
13777 tmp = cur->next;
13778 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013779 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013780 continue;
13781 }
13782 prev = cur;
13783 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013784 }
13785
Daniel Veillard3646d642004-06-02 19:19:14 +000013786 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013787 }
13788 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000013789 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013790 */
13791 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013792 (curWild->negNsSet != NULL) &&
13793 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013794 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013795 (curWild->negNsSet->value != NULL)) {
13796
13797 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013798 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013799 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000013800 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013801 }
13802 /*
13803 * 6 If the one is a negation of a namespace name and the other
13804 * is a negation of ·absent·, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000013805 * of a namespace name must be the value.
13806 */
13807 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13808 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013809 (completeWild->negNsSet->value == NULL)) {
13810 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000013811 }
13812 return(0);
13813}
13814
Daniel Veillard50355f02004-06-08 17:52:16 +000013815/**
13816 * xmlSchemaIsWildcardNsConstraintSubset:
13817 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013818 * @sub: the first wildcard
13819 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013820 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013821 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13822 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013823 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013824 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000013825 */
13826static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013827xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13828 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013829{
Daniel Veillard50355f02004-06-08 17:52:16 +000013830 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013831 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000013832 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013833 if (super->any)
13834 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000013835 /*
13836 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
13837 * 2.2 super must be a pair of not and the same value.
13838 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013839 if ((sub->negNsSet != NULL) &&
13840 (super->negNsSet != NULL) &&
13841 (sub->negNsSet->value == sub->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013842 return (0);
13843 /*
13844 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
Daniel Veillard50355f02004-06-08 17:52:16 +000013845 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013846 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013847 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013848 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000013849 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013850 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013851 xmlSchemaWildcardNsPtr cur, curB;
13852 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013853
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013854 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000013855 while (cur != NULL) {
13856 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013857 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000013858 while (curB != NULL) {
13859 if (cur->value == curB->value) {
13860 found = 1;
13861 break;
13862 }
13863 curB = curB->next;
13864 }
13865 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013866 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013867 cur = cur->next;
13868 }
13869 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013870 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013871 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013872 xmlSchemaWildcardNsPtr cur;
13873 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013874 * 3.2.2 super must be a pair of not and a namespace name or
13875 * ·absent· and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000013876 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013877 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013878 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013879 if (cur->value == super->negNsSet->value)
13880 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013881 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013882 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013883 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000013884 }
13885 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013886 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013887}
13888
Daniel Veillard50355f02004-06-08 17:52:16 +000013889static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013890xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013891 int *fixed,
13892 const xmlChar **value,
13893 xmlSchemaValPtr *val)
13894{
13895 *fixed = 0;
13896 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013897 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013898 *val = NULL;
13899
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013900 if (attruse->defValue != NULL) {
13901 *value = attruse->defValue;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000013902 if (val != NULL)
13903 *val = attruse->defVal;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013904 if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013905 *fixed = 1;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013906 return(1);
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000013907 } else if ((attruse->attrDecl != NULL) &&
13908 (attruse->attrDecl->defValue != NULL)) {
13909 *value = attruse->attrDecl->defValue;
13910 if (val != NULL)
13911 *val = attruse->attrDecl->defVal;
13912 if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013913 *fixed = 1;
13914 return(1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013915 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013916 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013917}
Daniel Veillard3646d642004-06-02 19:19:14 +000013918/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013919 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000013920 * @wild: the wildcard
13921 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013922 *
13923 * Validation Rule: Wildcard allows Namespace Name
13924 * (cvc-wildcard-namespace)
13925 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013926 * Returns 0 if the given namespace matches the wildcard,
13927 * 1 otherwise and -1 on API errors.
Daniel Veillard3646d642004-06-02 19:19:14 +000013928 */
13929static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013930xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
13931 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000013932{
13933 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013934 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000013935
13936 if (wild->any)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013937 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013938 else if (wild->nsSet != NULL) {
13939 xmlSchemaWildcardNsPtr cur;
13940
13941 cur = wild->nsSet;
13942 while (cur != NULL) {
13943 if (xmlStrEqual(cur->value, ns))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013944 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013945 cur = cur->next;
13946 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013947 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013948 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013949 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013950
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013951 return(1);
13952}
13953
13954#define XML_SCHEMA_ACTION_DERIVE 0
13955#define XML_SCHEMA_ACTION_REDEFINE 1
13956
13957#define WXS_ACTION_STR(a) \
13958((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
13959
13960/*
13961* Schema Component Constraint:
13962* Derivation Valid (Restriction, Complex)
13963* derivation-ok-restriction (2) - (4)
13964*
13965* ATTENTION:
13966* In XML Schema 1.1 this will be:
13967* Validation Rule:
13968* Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
13969*
13970*/
13971static int
13972xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
13973 int action,
13974 xmlSchemaBasicItemPtr item,
13975 xmlSchemaBasicItemPtr baseItem,
13976 xmlSchemaItemListPtr uses,
13977 xmlSchemaItemListPtr baseUses,
13978 xmlSchemaWildcardPtr wild,
13979 xmlSchemaWildcardPtr baseWild)
13980{
13981 xmlSchemaAttributeUsePtr cur = NULL, bcur;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000013982 int i, j, found; /* err = 0; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013983 const xmlChar *bEffValue;
13984 int effFixed;
13985
13986 if (uses != NULL) {
13987 for (i = 0; i < uses->nbItems; i++) {
13988 cur = uses->items[i];
13989 found = 0;
13990 if (baseUses == NULL)
13991 goto not_found;
13992 for (j = 0; j < baseUses->nbItems; j++) {
13993 bcur = baseUses->items[j];
13994 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
13995 WXS_ATTRUSE_DECL_NAME(bcur)) &&
13996 (WXS_ATTRUSE_DECL_TNS(cur) ==
13997 WXS_ATTRUSE_DECL_TNS(bcur)))
13998 {
13999 /*
14000 * (2.1) "If there is an attribute use in the {attribute
14001 * uses} of the {base type definition} (call this B) whose
14002 * {attribute declaration} has the same {name} and {target
14003 * namespace}, then all of the following must be true:"
14004 */
14005 found = 1;
14006
14007 if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14008 (bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14009 {
14010 xmlChar *str = NULL;
14011 /*
14012 * (2.1.1) "one of the following must be true:"
14013 * (2.1.1.1) "B's {required} is false."
14014 * (2.1.1.2) "R's {required} is true."
14015 */
14016 xmlSchemaPAttrUseErr4(pctxt,
14017 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14018 WXS_ITEM_NODE(item), item, cur,
14019 "The 'optional' attribute use is inconsistent "
14020 "with the corresponding 'required' attribute use of "
14021 "the %s %s",
14022 WXS_ACTION_STR(action),
14023 xmlSchemaGetComponentDesignation(&str, baseItem),
14024 NULL, NULL);
14025 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014026 /* err = pctxt->err; */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014027 } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014028 WXS_ATTRUSE_TYPEDEF(cur),
14029 WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14030 {
14031 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14032
14033 /*
14034 * SPEC (2.1.2) "R's {attribute declaration}'s
14035 * {type definition} must be validly derived from
14036 * B's {type definition} given the empty set as
14037 * defined in Type Derivation OK (Simple) (§3.14.6)."
14038 */
14039 xmlSchemaPAttrUseErr4(pctxt,
14040 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14041 WXS_ITEM_NODE(item), item, cur,
14042 "The attribute declaration's %s "
14043 "is not validly derived from "
14044 "the corresponding %s of the "
14045 "attribute declaration in the %s %s",
14046 xmlSchemaGetComponentDesignation(&strA,
14047 WXS_ATTRUSE_TYPEDEF(cur)),
14048 xmlSchemaGetComponentDesignation(&strB,
14049 WXS_ATTRUSE_TYPEDEF(bcur)),
14050 WXS_ACTION_STR(action),
14051 xmlSchemaGetComponentDesignation(&strC, baseItem));
14052 /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14053 FREE_AND_NULL(strA);
14054 FREE_AND_NULL(strB);
14055 FREE_AND_NULL(strC);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014056 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014057 } else {
14058 /*
14059 * 2.1.3 [Definition:] Let the effective value
14060 * constraint of an attribute use be its {value
14061 * constraint}, if present, otherwise its {attribute
14062 * declaration}'s {value constraint} .
14063 */
14064 xmlSchemaGetEffectiveValueConstraint(bcur,
14065 &effFixed, &bEffValue, NULL);
14066 /*
14067 * 2.1.3 ... one of the following must be true
14068 *
14069 * 2.1.3.1 B's ·effective value constraint· is
14070 * ·absent· or default.
14071 */
14072 if ((bEffValue != NULL) &&
14073 (effFixed == 1)) {
14074 const xmlChar *rEffValue = NULL;
14075
14076 xmlSchemaGetEffectiveValueConstraint(bcur,
14077 &effFixed, &rEffValue, NULL);
14078 /*
14079 * 2.1.3.2 R's ·effective value constraint· is
14080 * fixed with the same string as B's.
14081 * MAYBE TODO: Compare the computed values.
14082 * Hmm, it says "same string" so
14083 * string-equality might really be sufficient.
14084 */
14085 if ((effFixed == 0) ||
14086 (! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14087 {
14088 xmlChar *str = NULL;
14089
14090 xmlSchemaPAttrUseErr4(pctxt,
14091 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14092 WXS_ITEM_NODE(item), item, cur,
14093 "The effective value constraint of the "
14094 "attribute use is inconsistent with "
14095 "its correspondent in the %s %s",
14096 WXS_ACTION_STR(action),
14097 xmlSchemaGetComponentDesignation(&str,
14098 baseItem),
14099 NULL, NULL);
14100 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014101 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014102 }
14103 }
14104 }
14105 break;
14106 }
14107 }
14108not_found:
14109 if (!found) {
14110 /*
14111 * (2.2) "otherwise the {base type definition} must have an
14112 * {attribute wildcard} and the {target namespace} of the
14113 * R's {attribute declaration} must be ·valid· with respect
14114 * to that wildcard, as defined in Wildcard allows Namespace
14115 * Name (§3.10.4)."
14116 */
14117 if ((baseWild == NULL) ||
14118 (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14119 (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14120 {
14121 xmlChar *str = NULL;
14122
14123 xmlSchemaPAttrUseErr4(pctxt,
14124 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14125 WXS_ITEM_NODE(item), item, cur,
14126 "Neither a matching attribute use, "
14127 "nor a matching wildcard exists in the %s %s",
14128 WXS_ACTION_STR(action),
14129 xmlSchemaGetComponentDesignation(&str, baseItem),
14130 NULL, NULL);
14131 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014132 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014133 }
14134 }
14135 }
14136 }
14137 /*
14138 * SPEC derivation-ok-restriction (3):
14139 * (3) "For each attribute use in the {attribute uses} of the {base type
14140 * definition} whose {required} is true, there must be an attribute
14141 * use with an {attribute declaration} with the same {name} and
14142 * {target namespace} as its {attribute declaration} in the {attribute
14143 * uses} of the complex type definition itself whose {required} is true.
14144 */
14145 if (baseUses != NULL) {
14146 for (j = 0; j < baseUses->nbItems; j++) {
14147 bcur = baseUses->items[j];
14148 if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14149 continue;
14150 found = 0;
14151 if (uses != NULL) {
14152 for (i = 0; i < uses->nbItems; i++) {
14153 cur = uses->items[i];
14154 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14155 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14156 (WXS_ATTRUSE_DECL_TNS(cur) ==
14157 WXS_ATTRUSE_DECL_TNS(bcur))) {
14158 found = 1;
14159 break;
14160 }
14161 }
14162 }
14163 if (!found) {
14164 xmlChar *strA = NULL, *strB = NULL;
14165
14166 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14167 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14168 NULL, item,
14169 "A matching attribute use for the "
14170 "'required' %s of the %s %s is missing",
14171 xmlSchemaGetComponentDesignation(&strA, bcur),
14172 WXS_ACTION_STR(action),
14173 xmlSchemaGetComponentDesignation(&strB, baseItem),
14174 NULL);
14175 FREE_AND_NULL(strA);
14176 FREE_AND_NULL(strB);
14177 }
14178 }
14179 }
14180 /*
14181 * derivation-ok-restriction (4)
14182 */
14183 if (wild != NULL) {
14184 /*
14185 * (4) "If there is an {attribute wildcard}, all of the
14186 * following must be true:"
14187 */
14188 if (baseWild == NULL) {
14189 xmlChar *str = NULL;
14190
14191 /*
14192 * (4.1) "The {base type definition} must also have one."
14193 */
14194 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14195 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14196 NULL, item,
14197 "The %s has an attribute wildcard, "
14198 "but the %s %s '%s' does not have one",
14199 WXS_ITEM_TYPE_NAME(item),
14200 WXS_ACTION_STR(action),
14201 WXS_ITEM_TYPE_NAME(baseItem),
14202 xmlSchemaGetComponentQName(&str, baseItem));
14203 FREE_AND_NULL(str);
14204 return(pctxt->err);
14205 } else if ((baseWild->any == 0) &&
14206 xmlSchemaCheckCOSNSSubset(wild, baseWild))
14207 {
14208 xmlChar *str = NULL;
14209 /*
14210 * (4.2) "The complex type definition's {attribute wildcard}'s
14211 * {namespace constraint} must be a subset of the {base type
14212 * definition}'s {attribute wildcard}'s {namespace constraint},
14213 * as defined by Wildcard Subset (§3.10.6)."
14214 */
14215 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14216 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14217 NULL, item,
14218 "The attribute wildcard is not a valid "
14219 "subset of the wildcard in the %s %s '%s'",
14220 WXS_ACTION_STR(action),
14221 WXS_ITEM_TYPE_NAME(baseItem),
14222 xmlSchemaGetComponentQName(&str, baseItem),
14223 NULL);
14224 FREE_AND_NULL(str);
14225 return(pctxt->err);
14226 }
14227 /* 4.3 Unless the {base type definition} is the ·ur-type
14228 * definition·, the complex type definition's {attribute
14229 * wildcard}'s {process contents} must be identical to or
14230 * stronger than the {base type definition}'s {attribute
14231 * wildcard}'s {process contents}, where strict is stronger
14232 * than lax is stronger than skip.
14233 */
14234 if ((! WXS_IS_ANYTYPE(baseItem)) &&
14235 (wild->processContents < baseWild->processContents)) {
14236 xmlChar *str = NULL;
14237 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14238 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14239 NULL, baseItem,
14240 "The {process contents} of the attribute wildcard is "
14241 "weaker than the one in the %s %s '%s'",
14242 WXS_ACTION_STR(action),
14243 WXS_ITEM_TYPE_NAME(baseItem),
14244 xmlSchemaGetComponentQName(&str, baseItem),
14245 NULL);
14246 FREE_AND_NULL(str)
14247 return(pctxt->err);
14248 }
14249 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014250 return(0);
14251}
14252
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014253
14254static int
14255xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14256 xmlSchemaBasicItemPtr item,
14257 xmlSchemaWildcardPtr *completeWild,
14258 xmlSchemaItemListPtr list,
14259 xmlSchemaItemListPtr prohibs);
Daniel Veillard3646d642004-06-02 19:19:14 +000014260/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014261 * xmlSchemaFixupTypeAttributeUses:
Daniel Veillard3646d642004-06-02 19:19:14 +000014262 * @ctxt: the schema parser context
14263 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014264 *
Daniel Veillard3646d642004-06-02 19:19:14 +000014265 *
14266 * Builds the wildcard and the attribute uses on the given complex type.
14267 * Returns -1 if an internal error occurs, 0 otherwise.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014268 *
14269 * ATTENTION TODO: Experimantally this uses pointer comparisons for
14270 * strings, so recheck this if we start to hardcode some schemata, since
14271 * they might not be in the same dict.
14272 * NOTE: It is allowed to "extend" the xs:anyType type.
Daniel Veillard3646d642004-06-02 19:19:14 +000014273 */
14274static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014275xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014276 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000014277{
14278 xmlSchemaTypePtr baseType = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014279 xmlSchemaAttributeUsePtr use;
14280 xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000014281
Daniel Veillard01fa6152004-06-29 17:04:39 +000014282 if (type->baseType == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014283 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014284 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014285 return (-1);
14286 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014287 baseType = type->baseType;
14288 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014289 if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014290 return(-1);
14291
14292 uses = type->attrUses;
14293 baseUses = baseType->attrUses;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014294 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014295 * Expand attribute group references. And build the 'complete'
14296 * wildcard, i.e. intersect multiple wildcards.
14297 * Move attribute prohibitions into a separate list.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014298 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014299 if (uses != NULL) {
14300 if (WXS_IS_RESTRICTION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014301 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014302 * This one will transfer all attr. prohibitions
14303 * into pctxt->attrProhibs.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014304 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014305 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14306 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14307 pctxt->attrProhibs) == -1)
14308 {
14309 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14310 "failed to expand attributes");
14311 }
14312 if (pctxt->attrProhibs->nbItems != 0)
14313 prohibs = pctxt->attrProhibs;
14314 } else {
14315 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14316 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14317 NULL) == -1)
14318 {
14319 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14320 "failed to expand attributes");
14321 }
14322 }
14323 }
14324 /*
14325 * Inherit the attribute uses of the base type.
14326 */
14327 if (baseUses != NULL) {
14328 int i, j;
14329 xmlSchemaAttributeUseProhibPtr pro;
14330
14331 if (WXS_IS_RESTRICTION(type)) {
14332 int usesCount;
14333 xmlSchemaAttributeUsePtr tmp;
14334
14335 if (uses != NULL)
14336 usesCount = uses->nbItems;
14337 else
14338 usesCount = 0;
14339
14340 /* Restriction. */
14341 for (i = 0; i < baseUses->nbItems; i++) {
14342 use = baseUses->items[i];
14343 if (prohibs) {
14344 /*
14345 * Filter out prohibited uses.
14346 */
14347 for (j = 0; j < prohibs->nbItems; j++) {
14348 pro = prohibs->items[j];
14349 if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14350 (WXS_ATTRUSE_DECL_TNS(use) ==
14351 pro->targetNamespace))
14352 {
14353 goto inherit_next;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014354 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014355 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014356 }
14357 if (usesCount) {
14358 /*
14359 * Filter out existing uses.
14360 */
14361 for (j = 0; j < usesCount; j++) {
14362 tmp = uses->items[j];
14363 if ((WXS_ATTRUSE_DECL_NAME(use) ==
14364 WXS_ATTRUSE_DECL_NAME(tmp)) &&
14365 (WXS_ATTRUSE_DECL_TNS(use) ==
14366 WXS_ATTRUSE_DECL_TNS(tmp)))
14367 {
14368 goto inherit_next;
14369 }
14370 }
14371 }
14372 if (uses == NULL) {
14373 type->attrUses = xmlSchemaItemListCreate();
14374 if (type->attrUses == NULL)
14375 goto exit_failure;
14376 uses = type->attrUses;
14377 }
14378 xmlSchemaItemListAddSize(uses, 2, use);
14379inherit_next: {}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014380 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014381 } else {
14382 /* Extension. */
14383 for (i = 0; i < baseUses->nbItems; i++) {
14384 use = baseUses->items[i];
14385 if (uses == NULL) {
14386 type->attrUses = xmlSchemaItemListCreate();
14387 if (type->attrUses == NULL)
14388 goto exit_failure;
14389 uses = type->attrUses;
14390 }
14391 xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14392 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014393 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014394 }
14395 /*
14396 * Shrink attr. uses.
14397 */
14398 if (uses) {
14399 if (uses->nbItems == 0) {
14400 xmlSchemaItemListFree(uses);
14401 type->attrUses = NULL;
14402 }
14403 /*
14404 * TODO: We could shrink the size of the array
14405 * to fit the actual number of items.
14406 */
14407 }
14408 /*
14409 * Compute the complete wildcard.
14410 */
14411 if (WXS_IS_EXTENSION(type)) {
14412 if (baseType->attributeWildcard != NULL) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014413 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014414 * (3.2.2.1) "If the ·base wildcard· is non-·absent·, then
14415 * the appropriate case among the following:"
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014416 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014417 if (type->attributeWildcard != NULL) {
14418 /*
14419 * Union the complete wildcard with the base wildcard.
14420 * SPEC {attribute wildcard}
14421 * (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14422 * and {annotation} are those of the ·complete wildcard·,
14423 * and whose {namespace constraint} is the intensional union
14424 * of the {namespace constraint} of the ·complete wildcard·
14425 * and of the ·base wildcard·, as defined in Attribute
14426 * Wildcard Union (§3.10.6)."
14427 */
14428 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14429 baseType->attributeWildcard) == -1)
14430 goto exit_failure;
14431 } else {
14432 /*
14433 * (3.2.2.1.1) "If the ·complete wildcard· is ·absent·,
14434 * then the ·base wildcard·."
14435 */
14436 type->attributeWildcard = baseType->attributeWildcard;
14437 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014438 } else {
14439 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014440 * (3.2.2.2) "otherwise (the ·base wildcard· is ·absent·) the
14441 * ·complete wildcard"
14442 * NOOP
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014443 */
Daniel Veillard50355f02004-06-08 17:52:16 +000014444 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014445 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014446 /*
14447 * SPEC {attribute wildcard}
14448 * (3.1) "If the <restriction> alternative is chosen, then the
14449 * ·complete wildcard·;"
14450 * NOOP
14451 */
Daniel Veillard50355f02004-06-08 17:52:16 +000014452 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014453
Daniel Veillard3646d642004-06-02 19:19:14 +000014454 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014455
14456exit_failure:
14457 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000014458}
14459
14460/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000014461 * xmlSchemaTypeFinalContains:
14462 * @schema: the schema
14463 * @type: the type definition
14464 * @final: the final
14465 *
14466 * Evaluates if a type definition contains the given "final".
14467 * This does take "finalDefault" into account as well.
14468 *
14469 * Returns 1 if the type does containt the given "final",
14470 * 0 otherwise.
14471 */
14472static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014473xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014474{
Daniel Veillard01fa6152004-06-29 17:04:39 +000014475 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014476 return (0);
14477 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014478 return (1);
14479 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014480 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014481}
14482
14483/**
14484 * xmlSchemaGetUnionSimpleTypeMemberTypes:
14485 * @type: the Union Simple Type
14486 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014487 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014488 * returns NULL otherwise.
14489 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014490static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000014491xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14492{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014493 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014494 if (type->memberTypes != NULL)
14495 return (type->memberTypes);
14496 else
14497 type = type->baseType;
14498 }
14499 return (NULL);
14500}
14501
14502/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014503 * xmlSchemaGetParticleTotalRangeMin:
14504 * @particle: the particle
14505 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014506 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014507 * (all and sequence) + (choice)
14508 *
14509 * Returns the minimun Effective Total Range.
14510 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014511static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014512xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014513{
14514 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014515 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014516 return (0);
14517 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014518 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014519 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014520 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014521
14522 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014523 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014524 while (part != NULL) {
14525 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14526 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014527 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014528 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014529 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014530 if (cur == 0)
14531 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014532 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014533 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014534 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014535 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014536 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014537 } else {
14538 /* <all> and <sequence> */
14539 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014540 xmlSchemaParticlePtr part =
14541 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014542
14543 if (part == NULL)
14544 return (0);
14545 do {
14546 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14547 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014548 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014549 else
14550 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014551 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014552 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014553 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014554 }
14555}
14556
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014557/**
14558 * xmlSchemaGetParticleTotalRangeMax:
14559 * @particle: the particle
14560 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014561 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014562 * (all and sequence) + (choice)
14563 *
14564 * Returns the maximum Effective Total Range.
14565 */
14566static int
14567xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14568{
14569 if ((particle->children == NULL) ||
14570 (particle->children->children == NULL))
14571 return (0);
14572 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14573 int max = -1, cur;
14574 xmlSchemaParticlePtr part =
14575 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014576
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014577 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14578 if (part->children == NULL)
14579 continue;
14580 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14581 (part->children->type == XML_SCHEMA_TYPE_ANY))
14582 cur = part->maxOccurs;
14583 else
14584 cur = xmlSchemaGetParticleTotalRangeMax(part);
14585 if (cur == UNBOUNDED)
14586 return (UNBOUNDED);
14587 if ((max < cur) || (max == -1))
14588 max = cur;
14589 }
14590 /* TODO: Handle overflows? */
14591 return (particle->maxOccurs * max);
14592 } else {
14593 /* <all> and <sequence> */
14594 int sum = 0, cur;
14595 xmlSchemaParticlePtr part =
14596 (xmlSchemaParticlePtr) particle->children->children;
14597
14598 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14599 if (part->children == NULL)
14600 continue;
14601 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14602 (part->children->type == XML_SCHEMA_TYPE_ANY))
14603 cur = part->maxOccurs;
14604 else
14605 cur = xmlSchemaGetParticleTotalRangeMax(part);
14606 if (cur == UNBOUNDED)
14607 return (UNBOUNDED);
14608 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14609 return (UNBOUNDED);
14610 sum += cur;
14611 }
14612 /* TODO: Handle overflows? */
14613 return (particle->maxOccurs * sum);
14614 }
14615}
14616
14617/**
14618 * xmlSchemaIsParticleEmptiable:
14619 * @particle: the particle
14620 *
14621 * Schema Component Constraint: Particle Emptiable
14622 * Checks whether the given particle is emptiable.
14623 *
14624 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014625 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014626static int
14627xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14628{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014629 /*
14630 * SPEC (1) "Its {min occurs} is 0."
14631 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014632 if ((particle == NULL) || (particle->minOccurs == 0) ||
14633 (particle->children == NULL))
14634 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014635 /*
14636 * SPEC (2) "Its {term} is a group and the minimum part of the
14637 * effective total range of that group, [...] is 0."
14638 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014639 if (WXS_IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014640 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014641 return (1);
14642 }
14643 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014644}
14645
14646/**
14647 * xmlSchemaCheckCOSSTDerivedOK:
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014648 * @actxt: a context
Daniel Veillard01fa6152004-06-29 17:04:39 +000014649 * @type: the derived simple type definition
14650 * @baseType: the base type definition
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014651 * @subset: the subset of ('restriction', ect.)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014652 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014653 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014654 * Type Derivation OK (Simple) (cos-st-derived-OK)
14655 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014656 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000014657 * derived from @baseType.
14658 *
14659 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014660 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014661static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014662xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014663 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014664 xmlSchemaTypePtr baseType,
14665 int subset)
14666{
Daniel Veillard01fa6152004-06-29 17:04:39 +000014667 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014668 * 1 They are the same type definition.
14669 * TODO: The identy check might have to be more complex than this.
14670 */
14671 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014672 return (0);
14673 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014674 * 2.1 restriction is not in the subset, or in the {final}
14675 * of its own {base type definition};
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014676 *
14677 * NOTE that this will be used also via "xsi:type".
14678 *
14679 * TODO: Revise this, it looks strange. How can the "type"
14680 * not be fixed or *in* fixing?
Daniel Veillard01fa6152004-06-29 17:04:39 +000014681 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014682 if (WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014683 if (xmlSchemaTypeFixup(type, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014684 return(-1);
14685 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014686 if (xmlSchemaTypeFixup(baseType, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014687 return(-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014688 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014689 (xmlSchemaTypeFinalContains(type->baseType,
14690 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14691 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014692 }
14693 /* 2.2 */
14694 if (type->baseType == baseType) {
14695 /*
14696 * 2.2.1 D's ·base type definition· is B.
14697 */
14698 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014699 }
14700 /*
14701 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
14702 * and is validly derived from B given the subset, as defined by this
14703 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014704 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014705 if ((! WXS_IS_ANYTYPE(type->baseType)) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014706 (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014707 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014708 return (0);
14709 }
14710 /*
14711 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
Daniel Veillard01fa6152004-06-29 17:04:39 +000014712 * definition·.
14713 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014714 if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14715 (WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014716 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014717 }
14718 /*
14719 * 2.2.4 B's {variety} is union and D is validly derived from a type
14720 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000014721 * defined by this constraint.
14722 *
14723 * NOTE: This seems not to involve built-in types, since there is no
14724 * built-in Union Simple Type.
14725 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014726 if (WXS_IS_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014727 xmlSchemaTypeLinkPtr cur;
14728
14729 cur = baseType->memberTypes;
14730 while (cur != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014731 if (WXS_IS_TYPE_NOT_FIXED(cur->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014732 if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014733 return(-1);
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014734 if (xmlSchemaCheckCOSSTDerivedOK(actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014735 type, cur->type, subset) == 0)
14736 {
14737 /*
14738 * It just has to be validly derived from at least one
14739 * member-type.
14740 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014741 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014742 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014743 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014744 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014745 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014746 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14747}
14748
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014749/**
14750 * xmlSchemaCheckTypeDefCircularInternal:
14751 * @pctxt: the schema parser context
14752 * @ctxtType: the type definition
14753 * @ancestor: an ancestor of @ctxtType
14754 *
14755 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014756 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014757 *
14758 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14759 * circular, 0 otherwise.
14760 */
14761static int
14762xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14763 xmlSchemaTypePtr ctxtType,
14764 xmlSchemaTypePtr ancestor)
14765{
14766 int ret;
14767
14768 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14769 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014770
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014771 if (ctxtType == ancestor) {
14772 xmlSchemaPCustomErr(pctxt,
14773 XML_SCHEMAP_ST_PROPS_CORRECT_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014774 WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014775 "The definition is circular", NULL);
14776 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14777 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014778 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14779 /*
14780 * Avoid inifinite recursion on circular types not yet checked.
14781 */
14782 return (0);
14783 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014784 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14785 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14786 ancestor->baseType);
14787 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14788 return (ret);
14789}
14790
14791/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014792 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014793 * @item: the complex/simple type definition
14794 * @ctxt: the parser context
14795 * @name: the name
14796 *
14797 * Checks for circular type definitions.
14798 */
14799static void
14800xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014801 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014802{
14803 if ((item == NULL) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014804 (item->type == XML_SCHEMA_TYPE_BASIC) ||
14805 (item->baseType == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014806 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014807 xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14808 item->baseType);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014809}
Daniel Veillard01fa6152004-06-29 17:04:39 +000014810
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014811/*
14812* Simple Type Definition Representation OK (src-simple-type) 4
14813*
14814* "4 Circular union type definition is disallowed. That is, if the
14815* <union> alternative is chosen, there must not be any entries in the
14816* memberTypes [attribute] at any depth which resolve to the component
14817* corresponding to the <simpleType>."
14818*
14819* Note that this should work on the *representation* of a component,
14820* thus assumes any union types in the member types not being yet
14821* substituted. At this stage we need the variety of the types
14822* to be already computed.
14823*/
14824static int
14825xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14826 xmlSchemaTypePtr ctxType,
14827 xmlSchemaTypeLinkPtr members)
14828{
14829 xmlSchemaTypeLinkPtr member;
14830 xmlSchemaTypePtr memberType;
14831
14832 member = members;
14833 while (member != NULL) {
14834 memberType = member->type;
14835 while ((memberType != NULL) &&
14836 (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14837 if (memberType == ctxType) {
14838 xmlSchemaPCustomErr(pctxt,
14839 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014840 WXS_BASIC_CAST ctxType, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014841 "The union type definition is circular", NULL);
14842 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14843 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014844 if ((WXS_IS_UNION(memberType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014845 ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14846 {
14847 int res;
14848 memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14849 res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
14850 ctxType,
14851 xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
14852 memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
14853 if (res != 0)
14854 return(res);
14855 }
14856 memberType = memberType->baseType;
14857 }
14858 member = member->next;
14859 }
14860 return(0);
14861}
14862
14863static int
14864xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
14865 xmlSchemaTypePtr type)
14866{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014867 if (! WXS_IS_UNION(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014868 return(0);
14869 return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
14870 type->memberTypes));
14871}
14872
Daniel Veillard01fa6152004-06-29 17:04:39 +000014873/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014874 * xmlSchemaResolveTypeReferences:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014875 * @item: the complex/simple type definition
14876 * @ctxt: the parser context
14877 * @name: the name
14878 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014879 * Resolvese type definition references
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014880 */
14881static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014882xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014883 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014884{
14885 if (typeDef == NULL)
14886 return;
14887
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014888 /*
14889 * Resolve the base type.
14890 */
14891 if (typeDef->baseType == NULL) {
14892 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
14893 typeDef->base, typeDef->baseNs);
14894 if (typeDef->baseType == NULL) {
14895 xmlSchemaPResCompAttrErr(ctxt,
14896 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014897 WXS_BASIC_CAST typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014898 "base", typeDef->base, typeDef->baseNs,
14899 XML_SCHEMA_TYPE_SIMPLE, NULL);
14900 return;
14901 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014902 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014903 if (WXS_IS_SIMPLE(typeDef)) {
14904 if (WXS_IS_UNION(typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014905 /*
14906 * Resolve the memberTypes.
14907 */
14908 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
14909 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014910 } else if (WXS_IS_LIST(typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014911 /*
14912 * Resolve the itemType.
14913 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014914 if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
14915
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014916 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014917 typeDef->base, typeDef->baseNs);
14918
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014919 if ((typeDef->subtypes == NULL) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014920 (! WXS_IS_SIMPLE(typeDef->subtypes)))
14921 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014922 typeDef->subtypes = NULL;
14923 xmlSchemaPResCompAttrErr(ctxt,
14924 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014925 WXS_BASIC_CAST typeDef, typeDef->node,
14926 "itemType", typeDef->base, typeDef->baseNs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014927 XML_SCHEMA_TYPE_SIMPLE, NULL);
14928 }
14929 }
14930 return;
14931 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014932 }
14933 /*
14934 * The ball of letters below means, that if we have a particle
14935 * which has a QName-helper component as its {term}, we want
14936 * to resolve it...
14937 */
14938 else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
14939 ((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
14940 XML_SCHEMA_TYPE_PARTICLE) &&
14941 (WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
14942 ((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
14943 XML_SCHEMA_EXTRA_QNAMEREF))
14944 {
14945 xmlSchemaQNameRefPtr ref =
14946 WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
14947 xmlSchemaModelGroupDefPtr groupDef;
14948
14949 /*
14950 * URGENT TODO: Test this.
14951 */
14952 WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
14953 /*
14954 * Resolve the MG definition reference.
14955 */
14956 groupDef =
14957 WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
14958 ref->itemType, ref->name, ref->targetNamespace);
14959 if (groupDef == NULL) {
14960 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
14961 NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
14962 "ref", ref->name, ref->targetNamespace, ref->itemType,
14963 NULL);
14964 /* Remove the particle. */
14965 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
14966 } else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
14967 /* Remove the particle. */
14968 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
14969 else {
14970 /*
14971 * Assign the MG definition's {model group} to the
14972 * particle's {term}.
14973 */
14974 WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
14975
14976 if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
14977 /*
14978 * SPEC cos-all-limited (1.2)
14979 * "1.2 the {term} property of a particle with
14980 * {max occurs}=1 which is part of a pair which constitutes
14981 * the {content type} of a complex type definition."
14982 */
14983 if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
14984 xmlSchemaCustomErr(ACTXT_CAST ctxt,
14985 /* TODO: error code */
14986 XML_SCHEMAP_COS_ALL_LIMITED,
14987 WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
14988 "The particle's {max occurs} must be 1, since the "
14989 "reference resolves to an 'all' model group",
14990 NULL, NULL);
14991 }
14992 }
14993 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014994 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014995}
14996
14997
14998
14999/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000015000 * xmlSchemaCheckSTPropsCorrect:
15001 * @ctxt: the schema parser context
15002 * @type: the simple type definition
15003 *
15004 * Checks st-props-correct.
15005 *
15006 * Returns 0 if the properties are correct,
15007 * if not, a positive error code and -1 on internal
15008 * errors.
15009 */
15010static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015011xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015012 xmlSchemaTypePtr type)
15013{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015014 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015015 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015016
Daniel Veillardc0826a72004-08-10 14:17:33 +000015017 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015018 /*
15019 * Schema Component Constraint: Simple Type Definition Properties Correct
15020 *
15021 * NOTE: This is somehow redundant, since we actually built a simple type
15022 * to have all the needed information; this acts as an self test.
15023 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015024 /* Base type: If the datatype has been ·derived· by ·restriction·
15025 * then the Simple Type Definition component from which it is ·derived·,
15026 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000015027 */
15028 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015029 /*
15030 * TODO: Think about: "modulo the impact of Missing
15031 * Sub-components (§5.3)."
15032 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015033 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015034 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015035 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015036 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015037 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015038
Daniel Veillard01fa6152004-06-29 17:04:39 +000015039 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015040 if (! WXS_IS_SIMPLE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015041 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015042 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015043 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015044 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015045 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015046 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015047 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15048 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015049 if ( (WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015050 (WXS_IS_RESTRICTION(type) == 0) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015051 (! WXS_IS_ANY_SIMPLE_TYPE(baseType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015052 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015053 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015054 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015055 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015056 "the simple ur-type definition as base type, not '%s'",
15057 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015058 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015059 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15060 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015061 /*
15062 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015063 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015064 if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15065 (! WXS_IS_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015066 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015067 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015068 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015069 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015070 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15071 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015072 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015073
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015074 /*
15075 * 3 The {final} of the {base type definition} must not contain restriction.
15076 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015077 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015078 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15079 xmlSchemaPCustomErr(ctxt,
15080 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015081 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015082 "The 'final' of its base type '%s' must not contain "
15083 "'restriction'",
15084 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015085 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015086 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015087 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015088
15089 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015090 * 2 All simple type definitions must be derived ultimately from the ·simple
15091 * ur-type definition (so· circular definitions are disallowed). That is, it
15092 * must be possible to reach a built-in primitive datatype or the ·simple
15093 * ur-type definition· by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015094 *
15095 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000015096 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015097 return (0);
15098}
15099
15100/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015101 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000015102 * @ctxt: the schema parser context
15103 * @type: the simple type definition
15104 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015105 * Schema Component Constraint:
15106 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15107
15108 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015109 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000015110 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015111 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015112 * a positive error code otherwise.
15113 */
15114static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015115xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015116 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015117{
Daniel Veillardc0826a72004-08-10 14:17:33 +000015118 xmlChar *str = NULL;
15119
Daniel Veillard01fa6152004-06-29 17:04:39 +000015120 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015121 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15122 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015123 return (-1);
15124 }
15125
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015126 if (WXS_IS_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015127 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015128 /*
15129 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000015130 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015131 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015132 if (! WXS_IS_ATOMIC(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015133 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015134 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015135 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015136 "The base type '%s' is not an atomic simple type",
15137 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015138 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015139 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15140 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015141 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000015142 * restriction.
15143 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015144 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015145 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015146 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015147 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015148 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015149 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015150 "The final of its base type '%s' must not contain 'restriction'",
15151 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015152 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015153 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15154 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015155
15156 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000015157 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015158 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000015159 * Primitive datatypes.
15160 */
15161 if (type->facets != NULL) {
15162 xmlSchemaFacetPtr facet;
15163 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015164
Daniel Veillard01fa6152004-06-29 17:04:39 +000015165 primitive = xmlSchemaGetPrimitiveType(type);
15166 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015167 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15168 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015169 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015170 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015171 facet = type->facets;
15172 do {
15173 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015174 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015175 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015176 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015177 type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015178 }
15179 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015180 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015181 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015182 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015183 }
15184 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015185 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15186 * of the {base type definition} (call this BF),then the DF's {value}
15187 * must be a valid restriction of BF's {value} as defined in
15188 * [XML Schemas: Datatypes]."
15189 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015190 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015191 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015192 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015193 } else if (WXS_IS_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015194 xmlSchemaTypePtr itemType = NULL;
15195
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015196 itemType = type->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015197 if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015198 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15199 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015200 return (-1);
15201 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015202 if (WXS_IS_TYPE_NOT_FIXED(itemType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015203 xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015204 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015205 * 2.1 The {item type definition} must have a {variety} of atomic or
15206 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000015207 * must be atomic).
15208 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015209 if ((! WXS_IS_ATOMIC(itemType)) &&
15210 (! WXS_IS_UNION(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015211 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015212 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015213 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015214 "The item type '%s' does not have a variety of atomic or union",
15215 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015216 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015217 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015218 } else if (WXS_IS_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015219 xmlSchemaTypeLinkPtr member;
15220
15221 member = itemType->memberTypes;
15222 while (member != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015223 if (! WXS_IS_ATOMIC(member->type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015224 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015225 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015226 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015227 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015228 "member type '%s' of this item type is not atomic",
15229 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015230 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015231 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15232 }
15233 member = member->next;
15234 }
15235 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015236
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015237 if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015238 xmlSchemaFacetPtr facet;
15239 /*
15240 * This is the case if we have: <simpleType><list ..
15241 */
15242 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015243 * 2.3.1
15244 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000015245 * contain list.
15246 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015247 if (xmlSchemaTypeFinalContains(itemType,
15248 XML_SCHEMAS_TYPE_FINAL_LIST)) {
15249 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015250 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015251 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015252 "The final of its item type '%s' must not contain 'list'",
15253 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015254 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015255 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15256 }
15257 /*
15258 * 2.3.1.2 The {facets} must only contain the whiteSpace
15259 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015260 * OPTIMIZE TODO: the S4S already disallows any facet
15261 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015262 */
15263 if (type->facets != NULL) {
15264 facet = type->facets;
15265 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015266 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015267 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015268 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015269 type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015270 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15271 }
15272 facet = facet->next;
15273 } while (facet != NULL);
15274 }
15275 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015276 * MAYBE TODO: (Hmm, not really) Datatypes states:
15277 * A ·list· datatype can be ·derived· from an ·atomic· datatype
15278 * whose ·lexical space· allows space (such as string or anyURI)or
15279 * a ·union· datatype any of whose {member type definitions}'s
Daniel Veillard01fa6152004-06-29 17:04:39 +000015280 * ·lexical space· allows space.
15281 */
15282 } else {
15283 /*
15284 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015285 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015286 */
15287 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015288 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000015289 * 2.3.2.1 The {base type definition} must have a {variety} of list.
15290 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015291 if (! WXS_IS_LIST(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015292 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015293 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015294 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015295 "The base type '%s' must be a list type",
15296 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015297 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015298 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15299 }
15300 /*
15301 * 2.3.2.2 The {final} of the {base type definition} must not
15302 * contain restriction.
15303 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015304 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015305 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015306 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015307 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015308 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015309 "The 'final' of the base type '%s' must not contain 'restriction'",
15310 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015311 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015312 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15313 }
15314 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015315 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000015316 * from the {base type definition}'s {item type definition} given
15317 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
15318 */
15319 {
15320 xmlSchemaTypePtr baseItemType;
15321
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015322 baseItemType = type->baseType->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015323 if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015324 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15325 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015326 return (-1);
15327 }
15328 if ((itemType != baseItemType) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015329 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015330 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015331 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015332 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015333 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015334 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015335 "The item type '%s' is not validly derived from "
15336 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015337 xmlSchemaGetComponentQName(&str, itemType),
15338 xmlSchemaGetComponentQName(&strBIT, baseItemType),
15339 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015340
15341 FREE_AND_NULL(str)
15342 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015343 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015344 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15345 }
15346 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015347
Daniel Veillard01fa6152004-06-29 17:04:39 +000015348 if (type->facets != NULL) {
15349 xmlSchemaFacetPtr facet;
15350 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015351 /*
15352 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000015353 * and enumeration facet components are allowed among the {facets}.
15354 */
15355 facet = type->facets;
15356 do {
15357 switch (facet->type) {
15358 case XML_SCHEMA_FACET_LENGTH:
15359 case XML_SCHEMA_FACET_MINLENGTH:
15360 case XML_SCHEMA_FACET_MAXLENGTH:
15361 case XML_SCHEMA_FACET_WHITESPACE:
15362 /*
15363 * TODO: 2.5.1.2 List datatypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015364 * The value of ·whiteSpace· is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015365 */
15366 case XML_SCHEMA_FACET_PATTERN:
15367 case XML_SCHEMA_FACET_ENUMERATION:
15368 break;
15369 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015370 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015371 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015372 type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015373 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015374 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000015375 * invalid facets.
15376 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015377 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015378 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015379 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015380 facet = facet->next;
15381 } while (facet != NULL);
15382 if (ok == 0)
15383 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15384 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015385 * SPEC (2.3.2.5) (same as 1.3.2)
15386 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015387 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015388 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015389 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015390 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015391 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015392 } else if (WXS_IS_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015393 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015394 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000015395 * atomic or list.
15396 */
15397 xmlSchemaTypeLinkPtr member;
15398
15399 member = type->memberTypes;
15400 while (member != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015401 if (WXS_IS_TYPE_NOT_FIXED(member->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015402 xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015403
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015404 if ((! WXS_IS_ATOMIC(member->type)) &&
15405 (! WXS_IS_LIST(member->type))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015406 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015407 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015408 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015409 "The member type '%s' is neither an atomic, nor a list type",
15410 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015411 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015412 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15413 }
15414 member = member->next;
15415 }
15416 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015417 * 3.3.1 If the {base type definition} is the ·simple ur-type
15418 * definition·
Daniel Veillard01fa6152004-06-29 17:04:39 +000015419 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015420 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015421 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015422 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000015423 * {final} which does not contain union.
15424 */
15425 member = type->memberTypes;
15426 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015427 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015428 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015429 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015430 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015431 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015432 "The 'final' of member type '%s' contains 'union'",
15433 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015434 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015435 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15436 }
15437 member = member->next;
15438 }
15439 /*
15440 * 3.3.1.2 The {facets} must be empty.
15441 */
15442 if (type->facetSet != NULL) {
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_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015445 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015446 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015447 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15448 }
15449 } else {
15450 /*
15451 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015452 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015453 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015454 if (! WXS_IS_UNION(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015455 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015456 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015457 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015458 "The base type '%s' is not a union type",
15459 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015460 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015461 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15462 }
15463 /*
15464 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15465 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015466 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015467 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015468 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015469 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015470 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015471 "The 'final' of its base type '%s' must not contain 'restriction'",
15472 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015473 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015474 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15475 }
15476 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015477 * 3.3.2.3 The {member type definitions}, in order, must be validly
15478 * derived from the corresponding type definitions in the {base
15479 * type definition}'s {member type definitions} given the empty set,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015480 * as defined in Type Derivation OK (Simple) (§3.14.6).
15481 */
15482 {
15483 xmlSchemaTypeLinkPtr baseMember;
15484
15485 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015486 * OPTIMIZE: if the type is restricting, it has no local defined
15487 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015488 * thus a check for equality can be skipped.
15489 */
15490 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015491 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015492 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000015493 * types of it's base type. This check seems not necessary with
15494 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015495 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015496 */
15497 if (type->memberTypes != NULL) {
15498 member = type->memberTypes;
15499 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015500 if ((member == NULL) && (baseMember != NULL)) {
15501 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15502 "different number of member types in base");
15503 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015504 while (member != NULL) {
15505 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015506 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15507 "different number of member types in base");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015508 }
15509 if ((member->type != baseMember->type) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015510 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015511 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015512 xmlChar *strBMT = NULL, *strBT = NULL;
15513
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015514 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015515 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015516 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015517 "The member type %s is not validly "
15518 "derived from its corresponding member "
15519 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015520 xmlSchemaGetComponentQName(&str, member->type),
15521 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15522 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015523 FREE_AND_NULL(str)
15524 FREE_AND_NULL(strBMT)
15525 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015526 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015527 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015528 member = member->next;
15529 baseMember = baseMember->next;
15530 }
15531 }
15532 }
15533 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015534 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000015535 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015536 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015537 if (type->facets != NULL) {
15538 xmlSchemaFacetPtr facet;
15539 int ok = 1;
15540
15541 facet = type->facets;
15542 do {
15543 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15544 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015545 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015546 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015547 type, facet);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015548 ok = 0;
15549 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015550 facet = facet->next;
15551 } while (facet != NULL);
15552 if (ok == 0)
15553 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015554
Daniel Veillard01fa6152004-06-29 17:04:39 +000015555 }
15556 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015557 * SPEC (3.3.2.5) (same as 1.3.2)
15558 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015559 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015560 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015561 */
15562 }
15563 }
15564
15565 return (0);
15566}
15567
15568/**
15569 * xmlSchemaCheckSRCSimpleType:
15570 * @ctxt: the schema parser context
15571 * @type: the simple type definition
15572 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015573 * Checks crc-simple-type constraints.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015574 *
15575 * Returns 0 if the constraints are satisfied,
15576 * if not a positive error code and -1 on internal
15577 * errors.
15578 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015579#if 0
Daniel Veillard01fa6152004-06-29 17:04:39 +000015580static int
15581xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15582 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015583{
15584 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000015585 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015586 * must satisfy the conditions set out in Constraints on Simple Type
15587 * Definition Schema Components (§3.14.6).
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015588 */
15589 if (WXS_IS_RESTRICTION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015590 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015591 * src-simple-type.2 "If the <restriction> alternative is chosen,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015592 * either it must have a base [attribute] or a <simpleType> among its
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015593 * [children], but not both."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015594 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015595 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015596 /*
15597 *
15598 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015599 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015600 /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015601 * an itemType [attribute] or a <simpleType> among its [children],
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015602 * but not both."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015603 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015604 * NOTE: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015605 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015606 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015607 /*
15608 * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015609 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015610 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015611 return (0);
15612}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015613#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000015614
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015615static int
15616xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15617{
15618 if (ctxt->vctxt == NULL) {
15619 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15620 if (ctxt->vctxt == NULL) {
15621 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015622 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015623 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015624 "failed to create a temp. validation context.\n",
15625 NULL, NULL);
15626 return (-1);
15627 }
15628 /* TODO: Pass user data. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015629 xmlSchemaSetValidErrors(ctxt->vctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000015630 ctxt->error, ctxt->warning, ctxt->errCtxt);
15631 xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15632 ctxt->serror, ctxt->errCtxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015633 }
15634 return (0);
15635}
15636
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015637static int
15638xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15639 xmlNodePtr node,
15640 xmlSchemaTypePtr type,
15641 const xmlChar *value,
15642 xmlSchemaValPtr *retVal,
15643 int fireErrors,
15644 int normalize,
15645 int isNormalized);
15646
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015647/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015648 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015649 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015650 * @type: the simple type definition
15651 * @value: the default value
15652 * @node: an optional node (the holder of the value)
15653 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015654 * Schema Component Constraint: Element Default Valid (Immediate)
15655 * (cos-valid-default)
15656 * This will be used by the parser only. For the validator there's
15657 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015658 *
15659 * Returns 0 if the constraints are satisfied,
15660 * if not, a positive error code and -1 on internal
15661 * errors.
15662 */
15663static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015664xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15665 xmlNodePtr node,
15666 xmlSchemaTypePtr type,
15667 const xmlChar *value,
15668 xmlSchemaValPtr *val)
15669{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015670 int ret = 0;
15671
15672 /*
15673 * cos-valid-default:
15674 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015675 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015676 * definition the appropriate case among the following must be true:
15677 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015678 if WXS_IS_COMPLEX(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015679 /*
15680 * Complex type.
15681 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015682 * SPEC (2.1) "its {content type} must be a simple type definition
15683 * or mixed."
15684 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015685 * type}'s particle must be ·emptiable· as defined by
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015686 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000015687 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015688 if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15689 ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015690 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015691 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015692 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015693 WXS_BASIC_CAST type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015694 "For a string to be a valid default, the type definition "
15695 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015696 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015697 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15698 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015699 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015700 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015701 * 1 If the type definition is a simple type definition, then the string
15702 * must be ·valid· with respect to that definition as defined by String
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015703 * Valid (§3.14.4).
15704 *
15705 * AND
15706 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015707 * 2.2.1 If the {content type} is a simple type definition, then the
15708 * string must be ·valid· with respect to that simple type definition
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015709 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015710 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015711 if (WXS_IS_SIMPLE(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015712 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015713 type, value, val, 1, 1, 0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015714 else if (WXS_HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015715 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015716 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015717 else
15718 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015719
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015720 if (ret < 0) {
15721 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15722 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015723 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015724
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015725 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000015726}
15727
15728/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015729 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000015730 * @ctxt: the schema parser context
15731 * @type: the complex type definition
15732 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015733 *.(4.6) Constraints on Complex Type Definition Schema Components
15734 * Schema Component Constraint:
15735 * Complex Type Definition Properties Correct (ct-props-correct)
15736 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000015737 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015738 * Returns 0 if the constraints are satisfied, a positive
15739 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000015740 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015741static int
15742xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15743 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000015744{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015745 /*
15746 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15747 *
15748 * SPEC (1) "The values of the properties of a complex type definition must
15749 * be as described in the property tableau in The Complex Type Definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015750 * Schema Component (§3.4.1), modulo the impact of Missing
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015751 * Sub-components (§5.3)."
15752 */
15753 if ((type->baseType != NULL) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015754 (WXS_IS_SIMPLE(type->baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015755 (WXS_IS_EXTENSION(type) == 0)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015756 /*
15757 * SPEC (2) "If the {base type definition} is a simple type definition,
15758 * the {derivation method} must be extension."
15759 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015760 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015761 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015762 NULL, WXS_BASIC_CAST type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015763 "If the base type is a simple type, the derivation method must be "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015764 "'extension'", NULL, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015765 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015766 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015767 /*
15768 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
15769 * definition·. That is, it must be possible to reach the ·ur-type
15770 * definition by repeatedly following the {base type definition}."
15771 *
15772 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015773 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015774 /*
15775 * NOTE that (4) and (5) need the following:
15776 * - attribute uses need to be already inherited (apply attr. prohibitions)
15777 * - attribute group references need to be expanded already
15778 * - simple types need to be typefixed already
15779 */
15780 if (type->attrUses &&
15781 (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15782 {
15783 xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15784 xmlSchemaAttributeUsePtr use, tmp;
15785 int i, j, hasId = 0;
15786
15787 for (i = uses->nbItems -1; i >= 0; i--) {
15788 use = uses->items[i];
15789
15790 /*
15791 * SPEC ct-props-correct
15792 * (4) "Two distinct attribute declarations in the
15793 * {attribute uses} must not have identical {name}s and
15794 * {target namespace}s."
15795 */
15796 if (i > 0) {
15797 for (j = i -1; j >= 0; j--) {
15798 tmp = uses->items[j];
15799 if ((WXS_ATTRUSE_DECL_NAME(use) ==
15800 WXS_ATTRUSE_DECL_NAME(tmp)) &&
15801 (WXS_ATTRUSE_DECL_TNS(use) ==
15802 WXS_ATTRUSE_DECL_TNS(tmp)))
15803 {
15804 xmlChar *str = NULL;
15805
15806 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15807 XML_SCHEMAP_AG_PROPS_CORRECT,
15808 NULL, WXS_BASIC_CAST type,
15809 "Duplicate %s",
15810 xmlSchemaGetComponentDesignation(&str, use),
15811 NULL);
15812 FREE_AND_NULL(str);
15813 /*
15814 * Remove the duplicate.
15815 */
15816 if (xmlSchemaItemListRemove(uses, i) == -1)
15817 goto exit_failure;
15818 goto next_use;
15819 }
15820 }
15821 }
15822 /*
15823 * SPEC ct-props-correct
15824 * (5) "Two distinct attribute declarations in the
15825 * {attribute uses} must not have {type definition}s which
15826 * are or are derived from ID."
15827 */
15828 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15829 if (xmlSchemaIsDerivedFromBuiltInType(
15830 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15831 {
15832 if (hasId) {
15833 xmlChar *str = NULL;
15834
15835 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15836 XML_SCHEMAP_AG_PROPS_CORRECT,
15837 NULL, WXS_BASIC_CAST type,
15838 "There must not exist more than one attribute "
15839 "declaration of type 'xs:ID' "
15840 "(or derived from 'xs:ID'). The %s violates this "
15841 "constraint",
15842 xmlSchemaGetComponentDesignation(&str, use),
15843 NULL);
15844 FREE_AND_NULL(str);
15845 if (xmlSchemaItemListRemove(uses, i) == -1)
15846 goto exit_failure;
15847 }
15848
15849 hasId = 1;
15850 }
15851 }
15852next_use: {}
15853 }
15854 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015855 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015856exit_failure:
15857 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +000015858}
15859
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015860static int
15861xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
15862 xmlSchemaTypePtr typeB)
15863{
15864 /*
15865 * TODO: This should implement component-identity
15866 * in the future.
15867 */
15868 if ((typeA == NULL) || (typeB == NULL))
15869 return (0);
15870 return (typeA == typeB);
15871}
15872
15873/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015874 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015875 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015876 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015877 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015878 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015879 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015880 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015881 * Type Derivation OK (Complex) (cos-ct-derived-ok)
15882 *
15883 * STATUS: completed
15884 *
15885 * Returns 0 if the constraints are satisfied, or 1
15886 * if not.
15887 */
15888static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015889xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015890 xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015891 xmlSchemaTypePtr baseType,
15892 int set)
15893{
15894 int equal = xmlSchemaAreEqualTypes(type, baseType);
15895 /* TODO: Error codes. */
15896 /*
15897 * SPEC "For a complex type definition (call it D, for derived)
15898 * to be validly derived from a type definition (call this
15899 * B, for base) given a subset of {extension, restriction}
15900 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015901 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015902 if (! equal) {
15903 /*
15904 * SPEC (1) "If B and D are not the same type definition, then the
15905 * {derivation method} of D must not be in the subset."
15906 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015907 if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
15908 ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015909 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015910 } else {
15911 /*
15912 * SPEC (2.1) "B and D must be the same type definition."
15913 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015914 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015915 }
15916 /*
15917 * SPEC (2.2) "B must be D's {base type definition}."
15918 */
15919 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015920 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015921 /*
15922 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
15923 * definition·."
15924 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015925 if (WXS_IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015926 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015927
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015928 if (WXS_IS_COMPLEX(type->baseType)) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015929 /*
15930 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
15931 * must be validly derived from B given the subset as defined by this
15932 * constraint."
15933 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015934 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015935 baseType, set));
15936 } else {
15937 /*
15938 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
15939 * must be validly derived from B given the subset as defined in Type
15940 * Derivation OK (Simple) (§3.14.6).
15941 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015942 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015943 baseType, set));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015944 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015945}
15946
15947/**
15948 * xmlSchemaCheckCOSDerivedOK:
15949 * @type: the derived simple type definition
15950 * @baseType: the base type definition
15951 *
15952 * Calls:
15953 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015954 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015955 * Checks wheter @type can be validly derived from @baseType.
15956 *
15957 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015958 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015959static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015960xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015961 xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015962 xmlSchemaTypePtr baseType,
15963 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015964{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015965 if (WXS_IS_SIMPLE(type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015966 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015967 else
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015968 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015969}
15970
William M. Brack2f2a6632004-08-20 23:09:47 +000015971/**
15972 * xmlSchemaCheckCOSCTExtends:
15973 * @ctxt: the schema parser context
15974 * @type: the complex type definition
15975 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015976 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015977 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015978 * Derivation Valid (Extension) (cos-ct-extends)
15979 *
15980 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015981 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015982 * (1.5)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015983 * (1.4.3.2.2.2) "Particle Valid (Extension)"
William M. Brack2f2a6632004-08-20 23:09:47 +000015984 *
15985 * Returns 0 if the constraints are satisfied, a positive
15986 * error code if not and -1 if an internal error occured.
15987 */
15988static int
15989xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
15990 xmlSchemaTypePtr type)
15991{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015992 xmlSchemaTypePtr base = type->baseType;
15993 /*
15994 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
15995 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000015996 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015997 /*
15998 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015999 * then all of the following must be true:"
16000 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016001 if (WXS_IS_COMPLEX(base)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000016002 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016003 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016004 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000016005 */
16006 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16007 xmlSchemaPCustomErr(ctxt,
16008 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016009 WXS_BASIC_CAST type, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000016010 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016011 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000016012 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16013 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016014
16015 /*
16016 * ATTENTION: The constrains (1.2) and (1.3) are not applied,
16017 * since they are automatically satisfied through the
16018 * inheriting mechanism.
16019 * Note that even if redefining components, the inheriting mechanism
16020 * is used.
16021 */
16022#if 0
William M. Brack2f2a6632004-08-20 23:09:47 +000016023 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016024 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016025 * uses}
16026 * of the complex type definition itself, that is, for every attribute
16027 * use in the {attribute uses} of the {base type definition}, there
16028 * must be an attribute use in the {attribute uses} of the complex
16029 * type definition itself whose {attribute declaration} has the same
16030 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016031 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000016032 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016033 if (base->attrUses != NULL) {
16034 int i, j, found;
16035 xmlSchemaAttributeUsePtr use, buse;
William M. Brack2f2a6632004-08-20 23:09:47 +000016036
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016037 for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16038 buse = (WXS_LIST_CAST base->attrUses)->items[i];
16039 found = 0;
16040 if (type->attrUses != NULL) {
16041 use = (WXS_LIST_CAST type->attrUses)->items[j];
16042 for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16043 {
16044 if ((WXS_ATTRUSE_DECL_NAME(use) ==
16045 WXS_ATTRUSE_DECL_NAME(buse)) &&
16046 (WXS_ATTRUSE_DECL_TNS(use) ==
16047 WXS_ATTRUSE_DECL_TNS(buse)) &&
16048 (WXS_ATTRUSE_TYPEDEF(use) ==
16049 WXS_ATTRUSE_TYPEDEF(buse))
16050 {
16051 found = 1;
16052 break;
16053 }
16054 }
16055 }
16056 if (! found) {
16057 xmlChar *str = NULL;
16058
16059 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16060 XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16061 NULL, WXS_BASIC_CAST type,
16062 /*
16063 * TODO: The report does not indicate that also the
16064 * type needs to be the same.
16065 */
16066 "This type is missing a matching correspondent "
16067 "for its {base type}'s %s in its {attribute uses}",
16068 xmlSchemaGetComponentDesignation(&str,
16069 buse->children),
16070 NULL);
16071 FREE_AND_NULL(str)
16072 }
16073 }
16074 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016075 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016076 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16077 * definition must also have one, and the base type definition's
16078 * {attribute wildcard}'s {namespace constraint} must be a subset
16079 * of the complex type definition's {attribute wildcard}'s {namespace
16080 * constraint}, as defined by Wildcard Subset (§3.10.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016081 */
16082
16083 /*
16084 * MAYBE TODO: Enable if ever needed. But this will be needed only
16085 * if created the type via a schema construction API.
16086 */
16087 if (base->attributeWildcard != NULL) {
16088 if (type->attributeWilcard == NULL) {
16089 xmlChar *str = NULL;
16090
16091 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16092 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16093 NULL, type,
16094 "The base %s has an attribute wildcard, "
16095 "but this type is missing an attribute wildcard",
16096 xmlSchemaGetComponentDesignation(&str, base));
16097 FREE_AND_NULL(str)
16098
16099 } else if (xmlSchemaCheckCOSNSSubset(
16100 base->attributeWildcard, type->attributeWildcard))
16101 {
16102 xmlChar *str = NULL;
16103
16104 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16105 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16106 NULL, type,
16107 "The attribute wildcard is not a valid "
16108 "superset of the one in the base %s",
16109 xmlSchemaGetComponentDesignation(&str, base));
16110 FREE_AND_NULL(str)
16111 }
16112 }
16113#endif
16114 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016115 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000016116 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016117 if ((type->contentTypeDef != NULL) &&
16118 (type->contentTypeDef == base->contentTypeDef)) {
16119 /*
16120 * SPEC (1.4.1) "The {content type} of the {base type definition}
16121 * and the {content type} of the complex type definition itself
16122 * must be the same simple type definition"
16123 * PASS
16124 */
16125 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16126 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16127 /*
16128 * SPEC (1.4.2) "The {content type} of both the {base type
16129 * definition} and the complex type definition itself must
16130 * be empty."
16131 * PASS
16132 */
16133 } else {
16134 /*
16135 * SPEC (1.4.3) "All of the following must be true:"
16136 */
16137 if (type->subtypes == NULL) {
16138 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016139 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016140 * definition itself must specify a particle.
16141 */
16142 xmlSchemaPCustomErr(ctxt,
16143 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016144 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016145 "The content type must specify a particle", NULL);
16146 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16147 }
16148 /*
16149 * SPEC (1.4.3.2) "One of the following must be true:"
16150 */
16151 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16152 /*
16153 * SPEC (1.4.3.2.1) "The {content type} of the {base type
16154 * definition} must be empty.
16155 * PASS
16156 */
16157 } else {
16158 /*
16159 * SPEC (1.4.3.2.2) "All of the following must be true:"
16160 */
16161 if ((type->contentType != base->contentType) ||
16162 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16163 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16164 /*
16165 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16166 * or both must be element-only."
16167 */
16168 xmlSchemaPCustomErr(ctxt,
16169 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016170 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016171 "The content type of both, the type and its base "
16172 "type, must either 'mixed' or 'element-only'", NULL);
16173 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016174 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016175 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016176 * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016177 * complex type definition must be a ·valid extension·
16178 * of the {base type definition}'s particle, as defined
16179 * in Particle Valid (Extension) (§3.9.6)."
16180 *
16181 * NOTE that we won't check "Particle Valid (Extension)",
16182 * since it is ensured by the derivation process in
16183 * xmlSchemaTypeFixup(). We need to implement this when heading
16184 * for a construction API
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016185 * TODO: !! This is needed to be checked if redefining a type !!
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016186 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016187 }
16188 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016189 * URGENT TODO (1.5)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016190 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016191 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016192 } else {
16193 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016194 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016195 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000016196 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016197 if (type->contentTypeDef != base) {
16198 /*
16199 * SPEC (2.1) "The {content type} must be the same simple type
16200 * definition."
16201 */
16202 xmlSchemaPCustomErr(ctxt,
16203 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016204 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016205 "The content type must be the simple base type", NULL);
16206 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16207 }
16208 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16209 /*
16210 * SPEC (2.2) "The {final} of the {base type definition} must not
16211 * contain extension"
16212 * NOTE that this is the same as (1.1).
16213 */
16214 xmlSchemaPCustomErr(ctxt,
16215 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016216 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016217 "The 'final' of the base type definition "
16218 "contains 'extension'", NULL);
16219 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016220 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016221 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016222 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016223}
16224
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016225/**
16226 * xmlSchemaCheckDerivationOKRestriction:
16227 * @ctxt: the schema parser context
16228 * @type: the complex type definition
16229 *
16230 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016231 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016232 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16233 *
16234 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016235 * missing:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016236 * (5.4.2) ???
16237 *
16238 * ATTENTION:
16239 * In XML Schema 1.1 this will be:
16240 * Validation Rule: Checking complex type subsumption
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016241 *
16242 * Returns 0 if the constraints are satisfied, a positive
16243 * error code if not and -1 if an internal error occured.
16244 */
16245static int
16246xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16247 xmlSchemaTypePtr type)
16248{
16249 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016250
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016251 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016252 * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016253 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016254 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016255 base = type->baseType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016256 if (! WXS_IS_COMPLEX(base)) {
16257 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16258 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16259 type->node, WXS_BASIC_CAST type,
16260 "The base type must be a complex type", NULL, NULL);
16261 return(ctxt->err);
16262 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016263 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16264 /*
16265 * SPEC (1) "The {base type definition} must be a complex type
16266 * definition whose {final} does not contain restriction."
16267 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016268 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16269 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16270 type->node, WXS_BASIC_CAST type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016271 "The 'final' of the base type definition "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016272 "contains 'restriction'", NULL, NULL);
16273 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016274 }
16275 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016276 * SPEC (2), (3) and (4)
16277 * Those are handled in a separate function, since the
16278 * same constraints are needed for redefinition of
16279 * attribute groups as well.
16280 */
16281 if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16282 XML_SCHEMA_ACTION_DERIVE,
16283 WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16284 type->attrUses, base->attrUses,
16285 type->attributeWildcard,
16286 base->attributeWildcard) == -1)
16287 {
16288 return(-1);
16289 }
16290 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016291 * SPEC (5) "One of the following must be true:"
16292 */
16293 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16294 /*
16295 * SPEC (5.1) "The {base type definition} must be the
16296 * ·ur-type definition·."
16297 * PASS
16298 */
16299 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16300 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16301 /*
16302 * SPEC (5.2.1) "The {content type} of the complex type definition
16303 * must be a simple type definition"
16304 *
16305 * SPEC (5.2.2) "One of the following must be true:"
16306 */
16307 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016308 (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16309 {
16310 int err;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016311 /*
16312 * SPEC (5.2.2.1) "The {content type} of the {base type
16313 * definition} must be a simple type definition from which
16314 * the {content type} is validly derived given the empty
16315 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016316 *
16317 * ATTENTION TODO: This seems not needed if the type implicitely
16318 * derived from the base type.
16319 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016320 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016321 err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16322 type->contentTypeDef, base->contentTypeDef, 0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016323 if (err != 0) {
16324 xmlChar *strA = NULL, *strB = NULL;
16325
16326 if (err == -1)
16327 return(-1);
16328 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16329 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16330 NULL, WXS_BASIC_CAST type,
16331 "The {content type} %s is not validly derived from the "
16332 "base type's {content type} %s",
16333 xmlSchemaGetComponentDesignation(&strA,
16334 type->contentTypeDef),
16335 xmlSchemaGetComponentDesignation(&strB,
16336 base->contentTypeDef));
16337 FREE_AND_NULL(strA);
16338 FREE_AND_NULL(strB);
16339 return(ctxt->err);
16340 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016341 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16342 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016343 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016344 /*
16345 * SPEC (5.2.2.2) "The {base type definition} must be mixed
16346 * and have a particle which is ·emptiable· as defined in
16347 * Particle Emptiable (§3.9.6)."
16348 * PASS
16349 */
16350 } else {
16351 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016352 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16353 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016354 "The content type of the base type must be either "
16355 "a simple type or 'mixed' and an emptiable particle", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016356 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016357 }
16358 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16359 /*
16360 * SPEC (5.3.1) "The {content type} of the complex type itself must
16361 * be empty"
16362 */
16363 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16364 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016365 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016366 * definition} must also be empty."
16367 * PASS
16368 */
16369 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16370 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16371 xmlSchemaIsParticleEmptiable(
16372 (xmlSchemaParticlePtr) base->subtypes)) {
16373 /*
16374 * SPEC (5.3.2.2) "The {content type} of the {base type
16375 * definition} must be elementOnly or mixed and have a particle
16376 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
16377 * PASS
16378 */
16379 } else {
16380 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016381 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16382 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016383 "The content type of the base type must be either "
16384 "empty or 'mixed' (or 'elements-only') and an emptiable "
16385 "particle", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016386 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016387 }
16388 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016389 WXS_HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016390 /*
16391 * SPEC (5.4.1.1) "The {content type} of the complex type definition
16392 * itself must be element-only"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016393 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016394 if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016395 /*
16396 * SPEC (5.4.1.2) "The {content type} of the complex type
16397 * definition itself and of the {base type definition} must be
16398 * mixed"
16399 */
16400 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016401 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16402 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016403 "If the content type is 'mixed', then the content type of the "
16404 "base type must also be 'mixed'", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016405 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016406 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016407 /*
16408 * SPEC (5.4.2) "The particle of the complex type definition itself
16409 * must be a ·valid restriction· of the particle of the {content
16410 * type} of the {base type definition} as defined in Particle Valid
16411 * (Restriction) (§3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016412 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016413 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016414 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016415 } else {
16416 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016417 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16418 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016419 "The type is not a valid restriction of its base type", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016420 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016421 }
16422 return (0);
16423}
16424
16425/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016426 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016427 * @ctxt: the schema parser context
16428 * @type: the complex type definition
16429 *
16430 * (3.4.6) Constraints on Complex Type Definition Schema Components
16431 *
16432 * Returns 0 if the constraints are satisfied, a positive
16433 * error code if not and -1 if an internal error occured.
16434 */
16435static int
16436xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16437 xmlSchemaTypePtr type)
16438{
16439 int ret;
16440 /*
16441 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016442 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016443 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16444 if (ret != 0)
16445 return (ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016446 if (WXS_IS_EXTENSION(type))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016447 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16448 else
16449 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16450 return (ret);
16451}
16452
16453/**
16454 * xmlSchemaCheckSRCCT:
16455 * @ctxt: the schema parser context
16456 * @type: the complex type definition
16457 *
16458 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016459 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016460 * Complex Type Definition Representation OK (src-ct)
16461 *
16462 * Returns 0 if the constraints are satisfied, a positive
16463 * error code if not and -1 if an internal error occured.
16464 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016465static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016466xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016467 xmlSchemaTypePtr type)
16468{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016469 xmlSchemaTypePtr base;
16470 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016471
16472 /*
16473 * TODO: Adjust the error codes here, as I used
16474 * XML_SCHEMAP_SRC_CT_1 only yet.
16475 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016476 base = type->baseType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016477 if (! WXS_HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016478 /*
16479 * 1 If the <complexContent> alternative is chosen, the type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016480 * ·resolved· to by the ·actual value· of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016481 * must be a complex type definition;
16482 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016483 if (! WXS_IS_COMPLEX(base)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016484 xmlChar *str = NULL;
16485 xmlSchemaPCustomErr(ctxt,
16486 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016487 WXS_BASIC_CAST type, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016488 "If using <complexContent>, the base type is expected to be "
16489 "a complex type. The base type '%s' is a simple type",
16490 xmlSchemaFormatQName(&str, base->targetNamespace,
16491 base->name));
16492 FREE_AND_NULL(str)
16493 return (XML_SCHEMAP_SRC_CT_1);
16494 }
16495 } else {
16496 /*
16497 * SPEC
16498 * 2 If the <simpleContent> alternative is chosen, all of the
16499 * following must be true:
16500 * 2.1 The type definition ·resolved· to by the ·actual value· of the
16501 * base [attribute] must be one of the following:
16502 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016503 if (WXS_IS_SIMPLE(base)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016504 if (WXS_IS_EXTENSION(type) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016505 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016506 /*
16507 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016508 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016509 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016510 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016511 xmlSchemaPCustomErr(ctxt,
16512 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016513 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016514 "If using <simpleContent> and <restriction>, the base "
16515 "type must be a complex type. The base type '%s' is "
16516 "a simple type",
16517 xmlSchemaFormatQName(&str, base->targetNamespace,
16518 base->name));
16519 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016520 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016521 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016522 } else {
16523 /* Base type is a complex type. */
16524 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16525 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16526 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016527 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016528 * simple type definition;
16529 * PASS
16530 */
16531 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016532 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016533 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016534 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016535 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016536 type->name);
16537 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016538 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016539 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016540 (WXS_IS_RESTRICTION(type))) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016541
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016542 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016543 * 2.1.2 only if the <restriction> alternative is also
16544 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016545 * is mixed and a particle emptiable.
16546 */
16547 if (! xmlSchemaIsParticleEmptiable(
16548 (xmlSchemaParticlePtr) base->subtypes)) {
16549 ret = XML_SCHEMAP_SRC_CT_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016550 } else
16551 /*
16552 * Attention: at this point the <simpleType> child is in
16553 * ->contentTypeDef (put there during parsing).
16554 */
16555 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016556 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016557 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016558 * 2.2 If clause 2.1.2 above is satisfied, then there
16559 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016560 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016561 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016562 /* TODO: Change error code to ..._SRC_CT_2_2. */
16563 xmlSchemaPCustomErr(ctxt,
16564 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016565 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016566 "A <simpleType> is expected among the children "
16567 "of <restriction>, if <simpleContent> is used and "
16568 "the base type '%s' is a complex type",
16569 xmlSchemaFormatQName(&str, base->targetNamespace,
16570 base->name));
16571 FREE_AND_NULL(str)
16572 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016573 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016574 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016575 ret = XML_SCHEMAP_SRC_CT_1;
16576 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016577 }
16578 if (ret > 0) {
16579 xmlChar *str = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016580 if (WXS_IS_RESTRICTION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016581 xmlSchemaPCustomErr(ctxt,
16582 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016583 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016584 "If <simpleContent> and <restriction> is used, the "
16585 "base type must be a simple type or a complex type with "
16586 "mixed content and particle emptiable. The base type "
16587 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016588 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016589 base->name));
16590 } else {
16591 xmlSchemaPCustomErr(ctxt,
16592 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016593 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016594 "If <simpleContent> and <extension> is used, the "
16595 "base type must be a simple type. The base type '%s' "
16596 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016597 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016598 base->name));
16599 }
16600 FREE_AND_NULL(str)
16601 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016602 }
16603 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016604 * SPEC (3) "The corresponding complex type definition component must
16605 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016606 * Definition Schema Components (§3.4.6);"
16607 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016608 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016609 /*
16610 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016611 * above for {attribute wildcard} is satisfied, the intensional
16612 * intersection must be expressible, as defined in Attribute Wildcard
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016613 * Intersection (§3.10.6).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016614 * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016615 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016616 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016617}
William M. Brack2f2a6632004-08-20 23:09:47 +000016618
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016619#ifdef ENABLE_PARTICLE_RESTRICTION
16620/**
16621 * xmlSchemaCheckParticleRangeOK:
16622 * @ctxt: the schema parser context
16623 * @type: the complex type definition
16624 *
16625 * (3.9.6) Constraints on Particle Schema Components
16626 * Schema Component Constraint:
16627 * Occurrence Range OK (range-ok)
16628 *
16629 * STATUS: complete
16630 *
16631 * Returns 0 if the constraints are satisfied, a positive
16632 * error code if not and -1 if an internal error occured.
16633 */
16634static int
16635xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16636 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016637{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016638 if (rmin < bmin)
16639 return (1);
16640 if ((bmax != UNBOUNDED) &&
16641 (rmax > bmax))
16642 return (1);
16643 return (0);
16644}
16645
16646/**
16647 * xmlSchemaCheckRCaseNameAndTypeOK:
16648 * @ctxt: the schema parser context
16649 * @r: the restricting element declaration particle
16650 * @b: the base element declaration particle
16651 *
16652 * (3.9.6) Constraints on Particle Schema Components
16653 * Schema Component Constraint:
16654 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16655 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016656 *
16657 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016658 * MISSING (3.2.3)
16659 * CLARIFY: (3.2.2)
16660 *
16661 * Returns 0 if the constraints are satisfied, a positive
16662 * error code if not and -1 if an internal error occured.
16663 */
16664static int
16665xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16666 xmlSchemaParticlePtr r,
16667 xmlSchemaParticlePtr b)
16668{
16669 xmlSchemaElementPtr elemR, elemB;
16670
16671 /* TODO: Error codes (rcase-NameAndTypeOK). */
16672 elemR = (xmlSchemaElementPtr) r->children;
16673 elemB = (xmlSchemaElementPtr) b->children;
16674 /*
16675 * SPEC (1) "The declarations' {name}s and {target namespace}s are
16676 * the same."
16677 */
16678 if ((elemR != elemB) &&
16679 ((! xmlStrEqual(elemR->name, elemB->name)) ||
16680 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16681 return (1);
16682 /*
16683 * SPEC (2) "R's occurrence range is a valid restriction of B's
16684 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16685 */
16686 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16687 b->minOccurs, b->maxOccurs) != 0)
16688 return (1);
16689 /*
16690 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16691 * {scope} are global."
16692 */
16693 if (elemR == elemB)
16694 return (0);
16695 /*
16696 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16697 */
16698 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16699 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16700 return (1);
16701 /*
16702 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16703 * or is not fixed, or R's declaration's {value constraint} is fixed
16704 * with the same value."
16705 */
16706 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16707 ((elemR->value == NULL) ||
16708 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16709 /* TODO: Equality of the initial value or normalized or canonical? */
16710 (! xmlStrEqual(elemR->value, elemB->value))))
16711 return (1);
16712 /*
16713 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16714 * definitions} is a subset of B's declaration's {identity-constraint
16715 * definitions}, if any."
16716 */
16717 if (elemB->idcs != NULL) {
16718 /* TODO */
16719 }
16720 /*
16721 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16722 * superset of B's declaration's {disallowed substitutions}."
16723 */
16724 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16725 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16726 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16727 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16728 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16729 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16730 return (1);
16731 /*
16732 * SPEC (3.2.5) "R's {type definition} is validly derived given
16733 * {extension, list, union} from B's {type definition}"
16734 *
16735 * BADSPEC TODO: What's the point of adding "list" and "union" to the
16736 * set, if the corresponding constraints handle "restriction" and
16737 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016738 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016739 */
16740 {
16741 int set = 0;
16742
16743 set |= SUBSET_EXTENSION;
16744 set |= SUBSET_LIST;
16745 set |= SUBSET_UNION;
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016746 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016747 elemB->subtypes, set) != 0)
16748 return (1);
16749 }
16750 return (0);
16751}
16752
16753/**
16754 * xmlSchemaCheckRCaseNSCompat:
16755 * @ctxt: the schema parser context
16756 * @r: the restricting element declaration particle
16757 * @b: the base wildcard particle
16758 *
16759 * (3.9.6) Constraints on Particle Schema Components
16760 * Schema Component Constraint:
16761 * Particle Derivation OK (Elt:Any -- NSCompat)
16762 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016763 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016764 * STATUS: complete
16765 *
16766 * Returns 0 if the constraints are satisfied, a positive
16767 * error code if not and -1 if an internal error occured.
16768 */
16769static int
16770xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16771 xmlSchemaParticlePtr r,
16772 xmlSchemaParticlePtr b)
16773{
16774 /* TODO:Error codes (rcase-NSCompat). */
16775 /*
16776 * SPEC "For an element declaration particle to be a ·valid restriction·
16777 * of a wildcard particle all of the following must be true:"
16778 *
16779 * SPEC (1) "The element declaration's {target namespace} is ·valid·
16780 * with respect to the wildcard's {namespace constraint} as defined by
16781 * Wildcard allows Namespace Name (§3.10.4)."
16782 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016783 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016784 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16785 return (1);
16786 /*
16787 * SPEC (2) "R's occurrence range is a valid restriction of B's
16788 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16789 */
16790 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16791 b->minOccurs, b->maxOccurs) != 0)
16792 return (1);
16793
16794 return (0);
16795}
16796
16797/**
16798 * xmlSchemaCheckRCaseRecurseAsIfGroup:
16799 * @ctxt: the schema parser context
16800 * @r: the restricting element declaration particle
16801 * @b: the base model group particle
16802 *
16803 * (3.9.6) Constraints on Particle Schema Components
16804 * Schema Component Constraint:
16805 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16806 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016807 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016808 * STATUS: TODO
16809 *
16810 * Returns 0 if the constraints are satisfied, a positive
16811 * error code if not and -1 if an internal error occured.
16812 */
16813static int
16814xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16815 xmlSchemaParticlePtr r,
16816 xmlSchemaParticlePtr b)
16817{
16818 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16819 TODO
16820 return (0);
16821}
16822
16823/**
16824 * xmlSchemaCheckRCaseNSSubset:
16825 * @ctxt: the schema parser context
16826 * @r: the restricting wildcard particle
16827 * @b: the base wildcard particle
16828 *
16829 * (3.9.6) Constraints on Particle Schema Components
16830 * Schema Component Constraint:
16831 * Particle Derivation OK (Any:Any -- NSSubset)
16832 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016833 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016834 * STATUS: complete
16835 *
16836 * Returns 0 if the constraints are satisfied, a positive
16837 * error code if not and -1 if an internal error occured.
16838 */
16839static int
16840xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16841 xmlSchemaParticlePtr r,
16842 xmlSchemaParticlePtr b,
16843 int isAnyTypeBase)
16844{
16845 /* TODO: Error codes (rcase-NSSubset). */
16846 /*
16847 * SPEC (1) "R's occurrence range is a valid restriction of B's
16848 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16849 */
16850 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16851 b->minOccurs, b->maxOccurs))
16852 return (1);
16853 /*
16854 * SPEC (2) "R's {namespace constraint} must be an intensional subset
16855 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
16856 */
16857 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
16858 (xmlSchemaWildcardPtr) b->children))
16859 return (1);
16860 /*
16861 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
16862 * definition·, R's {process contents} must be identical to or stronger
16863 * than B's {process contents}, where strict is stronger than lax is
16864 * stronger than skip."
16865 */
16866 if (! isAnyTypeBase) {
16867 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
16868 ((xmlSchemaWildcardPtr) b->children)->processContents)
16869 return (1);
16870 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016871
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016872 return (0);
16873}
16874
16875/**
16876 * xmlSchemaCheckCOSParticleRestrict:
16877 * @ctxt: the schema parser context
16878 * @type: the complex type definition
16879 *
16880 * (3.9.6) Constraints on Particle Schema Components
16881 * Schema Component Constraint:
16882 * Particle Valid (Restriction) (cos-particle-restrict)
16883 *
16884 * STATUS: TODO
16885 *
16886 * Returns 0 if the constraints are satisfied, a positive
16887 * error code if not and -1 if an internal error occured.
16888 */
16889static int
16890xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
16891 xmlSchemaParticlePtr r,
16892 xmlSchemaParticlePtr b)
16893{
16894 int ret = 0;
16895
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016896 /*part = WXS_TYPE_PARTICLE(type);
16897 basePart = WXS_TYPE_PARTICLE(base);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016898 */
16899
16900 TODO
16901
16902 /*
16903 * SPEC (1) "They are the same particle."
16904 */
16905 if (r == b)
16906 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016907
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016908
16909 return (0);
16910}
16911
16912/**
16913 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
16914 * @ctxt: the schema parser context
16915 * @r: the model group particle
16916 * @b: the base wildcard particle
16917 *
16918 * (3.9.6) Constraints on Particle Schema Components
16919 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016920 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016921 * NSRecurseCheckCardinality)
16922 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016923 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016924 * STATUS: TODO: subst-groups
16925 *
16926 * Returns 0 if the constraints are satisfied, a positive
16927 * error code if not and -1 if an internal error occured.
16928 */
16929static int
16930xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
16931 xmlSchemaParticlePtr r,
16932 xmlSchemaParticlePtr b)
16933{
16934 xmlSchemaParticlePtr part;
16935 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
16936 if ((r->children == NULL) || (r->children->children == NULL))
16937 return (-1);
16938 /*
16939 * SPEC "For a group particle to be a ·valid restriction· of a
16940 * wildcard particle..."
16941 *
16942 * SPEC (1) "Every member of the {particles} of the group is a ·valid
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016943 * restriction· of the wildcard as defined by
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016944 * Particle Valid (Restriction) (§3.9.6)."
16945 */
16946 part = (xmlSchemaParticlePtr) r->children->children;
16947 do {
16948 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
16949 return (1);
16950 part = (xmlSchemaParticlePtr) part->next;
16951 } while (part != NULL);
16952 /*
16953 * SPEC (2) "The effective total range of the group [...] is a
16954 * valid restriction of B's occurrence range as defined by
16955 * Occurrence Range OK (§3.9.6)."
16956 */
16957 if (xmlSchemaCheckParticleRangeOK(
16958 xmlSchemaGetParticleTotalRangeMin(r),
16959 xmlSchemaGetParticleTotalRangeMax(r),
16960 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016961 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016962 return (0);
16963}
16964
16965/**
16966 * xmlSchemaCheckRCaseRecurse:
16967 * @ctxt: the schema parser context
16968 * @r: the <all> or <sequence> model group particle
16969 * @b: the base <all> or <sequence> model group particle
16970 *
16971 * (3.9.6) Constraints on Particle Schema Components
16972 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016973 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016974 Recurse)
16975 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016976 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016977 * STATUS: ?
16978 * TODO: subst-groups
16979 *
16980 * Returns 0 if the constraints are satisfied, a positive
16981 * error code if not and -1 if an internal error occured.
16982 */
16983static int
16984xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
16985 xmlSchemaParticlePtr r,
16986 xmlSchemaParticlePtr b)
16987{
16988 /* xmlSchemaParticlePtr part; */
16989 /* TODO: Error codes (rcase-Recurse). */
16990 if ((r->children == NULL) || (b->children == NULL) ||
16991 (r->children->type != b->children->type))
16992 return (-1);
16993 /*
16994 * SPEC "For an all or sequence group particle to be a ·valid
16995 * restriction· of another group particle with the same {compositor}..."
16996 *
16997 * SPEC (1) "R's occurrence range is a valid restriction of B's
16998 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16999 */
17000 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17001 b->minOccurs, b->maxOccurs))
17002 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017003
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017004
17005 return (0);
17006}
17007
17008#endif
17009
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017010#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17011 xmlSchemaPCustomErrExt(pctxt, \
17012 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017013 WXS_BASIC_CAST fac1, fac1->node, \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017014 "It is an error for both '%s' and '%s' to be specified on the "\
17015 "same type definition", \
17016 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17017 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17018
17019#define FACET_RESTR_ERR(fac1, msg) \
17020 xmlSchemaPCustomErr(pctxt, \
17021 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017022 WXS_BASIC_CAST fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017023 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017024
17025#define FACET_RESTR_FIXED_ERR(fac) \
17026 xmlSchemaPCustomErr(pctxt, \
17027 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017028 WXS_BASIC_CAST fac, fac->node, \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017029 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017030 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017031
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017032static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017033xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17034 xmlSchemaFacetPtr facet1,
17035 xmlSchemaFacetPtr facet2,
17036 int lessGreater,
17037 int orEqual,
17038 int ofBase)
17039{
17040 xmlChar *msg = NULL;
17041
17042 msg = xmlStrdup(BAD_CAST "'");
17043 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17044 msg = xmlStrcat(msg, BAD_CAST "' has to be");
17045 if (lessGreater == 0)
17046 msg = xmlStrcat(msg, BAD_CAST " equal to");
17047 if (lessGreater == 1)
17048 msg = xmlStrcat(msg, BAD_CAST " greater than");
17049 else
17050 msg = xmlStrcat(msg, BAD_CAST " less than");
17051
17052 if (orEqual)
17053 msg = xmlStrcat(msg, BAD_CAST " or equal to");
17054 msg = xmlStrcat(msg, BAD_CAST " '");
17055 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17056 if (ofBase)
17057 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17058 else
17059 msg = xmlStrcat(msg, BAD_CAST "'");
17060
17061 xmlSchemaPCustomErr(pctxt,
17062 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017063 WXS_BASIC_CAST facet1, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017064 (const char *) msg, NULL);
17065
17066 if (msg != NULL)
17067 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017068}
17069
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017070/*
17071* xmlSchemaDeriveAndValidateFacets:
17072*
17073* Schema Component Constraint: Simple Type Restriction (Facets)
17074* (st-restrict-facets)
17075*/
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017076static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017077xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17078 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017079{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017080 xmlSchemaTypePtr base = type->baseType;
17081 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017082 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017083 flength = NULL, ftotdig = NULL, ffracdig = NULL,
17084 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17085 fmininc = NULL, fmaxinc = NULL,
17086 fminexc = NULL, fmaxexc = NULL,
17087 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17088 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17089 bfmininc = NULL, bfmaxinc = NULL,
17090 bfminexc = NULL, bfmaxexc = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000017091 int res; /* err = 0, fixedErr; */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017092
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017093 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017094 * SPEC st-restrict-facets 1:
17095 * "The {variety} of R is the same as that of B."
17096 */
17097 /*
17098 * SPEC st-restrict-facets 2:
17099 * "If {variety} is atomic, the {primitive type definition}
17100 * of R is the same as that of B."
17101 *
17102 * NOTE: we leave 1 & 2 out for now, since this will be
17103 * satisfied by the derivation process.
17104 * CONSTRUCTION TODO: Maybe needed if using a construction API.
17105 */
17106 /*
17107 * SPEC st-restrict-facets 3:
17108 * "The {facets} of R are the union of S and the {facets}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017109 * of B, eliminating duplicates. To eliminate duplicates,
17110 * when a facet of the same kind occurs in both S and the
17111 * {facets} of B, the one in the {facets} of B is not
17112 * included, with the exception of enumeration and pattern
17113 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017114 * are allowed."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017115 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017116
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017117 if ((type->facetSet == NULL) && (base->facetSet == NULL))
17118 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017119
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017120 last = type->facetSet;
17121 if (last != NULL)
17122 while (last->next != NULL)
17123 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017124
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017125 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17126 facet = cur->facet;
17127 switch (facet->type) {
17128 case XML_SCHEMA_FACET_LENGTH:
17129 flength = facet; break;
17130 case XML_SCHEMA_FACET_MINLENGTH:
17131 fminlen = facet; break;
17132 case XML_SCHEMA_FACET_MININCLUSIVE:
17133 fmininc = facet; break;
17134 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17135 fminexc = facet; break;
17136 case XML_SCHEMA_FACET_MAXLENGTH:
17137 fmaxlen = facet; break;
17138 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17139 fmaxinc = facet; break;
17140 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17141 fmaxexc = facet; break;
17142 case XML_SCHEMA_FACET_TOTALDIGITS:
17143 ftotdig = facet; break;
17144 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17145 ffracdig = facet; break;
17146 default:
17147 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017148 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017149 }
17150 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17151 facet = cur->facet;
17152 switch (facet->type) {
17153 case XML_SCHEMA_FACET_LENGTH:
17154 bflength = facet; break;
17155 case XML_SCHEMA_FACET_MINLENGTH:
17156 bfminlen = facet; break;
17157 case XML_SCHEMA_FACET_MININCLUSIVE:
17158 bfmininc = facet; break;
17159 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17160 bfminexc = facet; break;
17161 case XML_SCHEMA_FACET_MAXLENGTH:
17162 bfmaxlen = facet; break;
17163 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17164 bfmaxinc = facet; break;
17165 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17166 bfmaxexc = facet; break;
17167 case XML_SCHEMA_FACET_TOTALDIGITS:
17168 bftotdig = facet; break;
17169 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17170 bffracdig = facet; break;
17171 default:
17172 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017173 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017174 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017175 /*
17176 * length and minLength or maxLength (2.2) + (3.2)
17177 */
17178 if (flength && (fminlen || fmaxlen)) {
17179 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17180 "either of 'minLength' or 'maxLength' to be specified on "
17181 "the same type definition")
17182 }
17183 /*
17184 * Mutual exclusions in the same derivation step.
17185 */
17186 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017187 /*
17188 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017189 */
17190 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17191 }
17192 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017193 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017194 * SCC "minInclusive and minExclusive"
17195 */
17196 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017197 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017198
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017199 if (flength && bflength) {
17200 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017201 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017202 * The values have to be equal.
17203 */
17204 res = xmlSchemaCompareValues(flength->val, bflength->val);
17205 if (res == -2)
17206 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017207 if (res != 0)
17208 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17209 if ((res != 0) && (bflength->fixed)) {
17210 FACET_RESTR_FIXED_ERR(flength)
17211 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017212
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017213 }
17214 if (fminlen && bfminlen) {
17215 /*
17216 * SCC "minLength valid restriction"
17217 * minLength >= BASE minLength
17218 */
17219 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17220 if (res == -2)
17221 goto internal_error;
17222 if (res == -1)
17223 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17224 if ((res != 0) && (bfminlen->fixed)) {
17225 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017226 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017227 }
17228 if (fmaxlen && bfmaxlen) {
17229 /*
17230 * SCC "maxLength valid restriction"
17231 * maxLength <= BASE minLength
17232 */
17233 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17234 if (res == -2)
17235 goto internal_error;
17236 if (res == 1)
17237 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17238 if ((res != 0) && (bfmaxlen->fixed)) {
17239 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017240 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017241 }
17242 /*
17243 * SCC "length and minLength or maxLength"
17244 */
17245 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017246 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017247 if (flength) {
17248 if (! fminlen)
17249 flength = bflength;
17250 if (fminlen) {
17251 /* (1.1) length >= minLength */
17252 res = xmlSchemaCompareValues(flength->val, fminlen->val);
17253 if (res == -2)
17254 goto internal_error;
17255 if (res == -1)
17256 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17257 }
17258 if (! fmaxlen)
17259 fmaxlen = bfmaxlen;
17260 if (fmaxlen) {
17261 /* (2.1) length <= maxLength */
17262 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17263 if (res == -2)
17264 goto internal_error;
17265 if (res == 1)
17266 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17267 }
17268 }
17269 if (fmaxinc) {
17270 /*
17271 * "maxInclusive"
17272 */
17273 if (fmininc) {
17274 /* SCC "maxInclusive >= minInclusive" */
17275 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17276 if (res == -2)
17277 goto internal_error;
17278 if (res == -1) {
17279 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17280 }
17281 }
17282 /*
17283 * SCC "maxInclusive valid restriction"
17284 */
17285 if (bfmaxinc) {
17286 /* maxInclusive <= BASE maxInclusive */
17287 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17288 if (res == -2)
17289 goto internal_error;
17290 if (res == 1)
17291 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17292 if ((res != 0) && (bfmaxinc->fixed)) {
17293 FACET_RESTR_FIXED_ERR(fmaxinc)
17294 }
17295 }
17296 if (bfmaxexc) {
17297 /* maxInclusive < BASE maxExclusive */
17298 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17299 if (res == -2)
17300 goto internal_error;
17301 if (res != -1) {
17302 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17303 }
17304 }
17305 if (bfmininc) {
17306 /* maxInclusive >= BASE minInclusive */
17307 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17308 if (res == -2)
17309 goto internal_error;
17310 if (res == -1) {
17311 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17312 }
17313 }
17314 if (bfminexc) {
17315 /* maxInclusive > BASE minExclusive */
17316 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17317 if (res == -2)
17318 goto internal_error;
17319 if (res != 1) {
17320 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17321 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017322 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017323 }
17324 if (fmaxexc) {
17325 /*
17326 * "maxExclusive >= minExclusive"
17327 */
17328 if (fminexc) {
17329 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17330 if (res == -2)
17331 goto internal_error;
17332 if (res == -1) {
17333 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17334 }
17335 }
17336 /*
17337 * "maxExclusive valid restriction"
17338 */
17339 if (bfmaxexc) {
17340 /* maxExclusive <= BASE maxExclusive */
17341 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17342 if (res == -2)
17343 goto internal_error;
17344 if (res == 1) {
17345 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17346 }
17347 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017348 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017349 }
17350 }
17351 if (bfmaxinc) {
17352 /* maxExclusive <= BASE maxInclusive */
17353 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17354 if (res == -2)
17355 goto internal_error;
17356 if (res == 1) {
17357 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17358 }
17359 }
17360 if (bfmininc) {
17361 /* maxExclusive > BASE minInclusive */
17362 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17363 if (res == -2)
17364 goto internal_error;
17365 if (res != 1) {
17366 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17367 }
17368 }
17369 if (bfminexc) {
17370 /* maxExclusive > BASE minExclusive */
17371 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17372 if (res == -2)
17373 goto internal_error;
17374 if (res != 1) {
17375 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17376 }
17377 }
17378 }
17379 if (fminexc) {
17380 /*
17381 * "minExclusive < maxInclusive"
17382 */
17383 if (fmaxinc) {
17384 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17385 if (res == -2)
17386 goto internal_error;
17387 if (res != -1) {
17388 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17389 }
17390 }
17391 /*
17392 * "minExclusive valid restriction"
17393 */
17394 if (bfminexc) {
17395 /* minExclusive >= BASE minExclusive */
17396 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17397 if (res == -2)
17398 goto internal_error;
17399 if (res == -1) {
17400 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17401 }
17402 if ((res != 0) && (bfminexc->fixed)) {
17403 FACET_RESTR_FIXED_ERR(fminexc)
17404 }
17405 }
17406 if (bfmaxinc) {
17407 /* minExclusive <= BASE maxInclusive */
17408 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17409 if (res == -2)
17410 goto internal_error;
17411 if (res == 1) {
17412 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17413 }
17414 }
17415 if (bfmininc) {
17416 /* minExclusive >= BASE minInclusive */
17417 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17418 if (res == -2)
17419 goto internal_error;
17420 if (res == -1) {
17421 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17422 }
17423 }
17424 if (bfmaxexc) {
17425 /* minExclusive < BASE maxExclusive */
17426 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17427 if (res == -2)
17428 goto internal_error;
17429 if (res != -1) {
17430 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17431 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017432 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017433 }
17434 if (fmininc) {
17435 /*
17436 * "minInclusive < maxExclusive"
17437 */
17438 if (fmaxexc) {
17439 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17440 if (res == -2)
17441 goto internal_error;
17442 if (res != -1) {
17443 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17444 }
17445 }
17446 /*
17447 * "minExclusive valid restriction"
17448 */
17449 if (bfmininc) {
17450 /* minInclusive >= BASE minInclusive */
17451 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17452 if (res == -2)
17453 goto internal_error;
17454 if (res == -1) {
17455 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17456 }
17457 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017458 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017459 }
17460 }
17461 if (bfmaxinc) {
17462 /* minInclusive <= BASE maxInclusive */
17463 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17464 if (res == -2)
17465 goto internal_error;
Daniel Veillard0a119eb2005-07-20 13:46:00 +000017466 if (res == 1) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017467 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17468 }
17469 }
17470 if (bfminexc) {
17471 /* minInclusive > BASE minExclusive */
17472 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17473 if (res == -2)
17474 goto internal_error;
17475 if (res != 1)
17476 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17477 }
17478 if (bfmaxexc) {
17479 /* minInclusive < BASE maxExclusive */
17480 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17481 if (res == -2)
17482 goto internal_error;
17483 if (res != -1)
17484 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17485 }
17486 }
17487 if (ftotdig && bftotdig) {
17488 /*
17489 * SCC " totalDigits valid restriction"
17490 * totalDigits <= BASE totalDigits
17491 */
17492 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17493 if (res == -2)
17494 goto internal_error;
17495 if (res == 1)
17496 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17497 -1, 1, 1);
17498 if ((res != 0) && (bftotdig->fixed)) {
17499 FACET_RESTR_FIXED_ERR(ftotdig)
17500 }
17501 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017502 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017503 /*
17504 * SCC "fractionDigits valid restriction"
17505 * fractionDigits <= BASE fractionDigits
17506 */
17507 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17508 if (res == -2)
17509 goto internal_error;
17510 if (res == 1)
17511 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17512 -1, 1, 1);
17513 if ((res != 0) && (bffracdig->fixed)) {
17514 FACET_RESTR_FIXED_ERR(ffracdig)
17515 }
17516 }
17517 /*
17518 * SCC "fractionDigits less than or equal to totalDigits"
17519 */
17520 if (! ftotdig)
17521 ftotdig = bftotdig;
17522 if (! ffracdig)
17523 ffracdig = bffracdig;
17524 if (ftotdig && ffracdig) {
17525 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17526 if (res == -2)
17527 goto internal_error;
17528 if (res == 1)
17529 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17530 -1, 1, 0);
17531 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017532 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017533 * *Enumerations* won' be added here, since only the first set
17534 * of enumerations in the ancestor-or-self axis is used
17535 * for validation, plus we need to use the base type of those
17536 * enumerations for whitespace.
17537 *
17538 * *Patterns*: won't be add here, since they are ORed at
17539 * type level and ANDed at ancestor level. This will
17540 * happed during validation by walking the base axis
17541 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017542 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017543 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17544 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017545 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017546 * Special handling of enumerations and patterns.
17547 * TODO: hmm, they should not appear in the set, so remove this.
17548 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017549 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017550 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017551 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017552 /*
17553 * Search for a duplicate facet in the current type.
17554 */
17555 link = type->facetSet;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000017556 /* err = 0; */
17557 /* fixedErr = 0; */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017558 while (link != NULL) {
17559 facet = link->facet;
17560 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017561 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017562 case XML_SCHEMA_FACET_WHITESPACE:
17563 /*
17564 * The whitespace must be stronger.
17565 */
17566 if (facet->whitespace < bfacet->whitespace) {
17567 FACET_RESTR_ERR(flength,
17568 "The 'whitespace' value has to be equal to "
17569 "or stronger than the 'whitespace' value of "
17570 "the base type")
17571 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017572 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017573 (facet->whitespace != bfacet->whitespace)) {
17574 FACET_RESTR_FIXED_ERR(facet)
17575 }
17576 break;
17577 default:
17578 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017579 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017580 /* Duplicate found. */
17581 break;
17582 }
17583 link = link->next;
17584 }
17585 /*
17586 * If no duplicate was found: add the base types's facet
17587 * to the set.
17588 */
17589 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017590 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017591 xmlMalloc(sizeof(xmlSchemaFacetLink));
17592 if (link == NULL) {
17593 xmlSchemaPErrMemory(pctxt,
17594 "deriving facets, creating a facet link", NULL);
17595 return (-1);
17596 }
17597 link->facet = cur->facet;
17598 link->next = NULL;
17599 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017600 type->facetSet = link;
17601 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017602 last->next = link;
17603 last = link;
17604 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017605
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017606 }
17607
17608 return (0);
17609internal_error:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017610 PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17611 "an error occured");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017612 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017613}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017614
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017615static int
17616xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17617 xmlSchemaTypePtr type)
17618{
17619 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17620 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017621 * The actual value is then formed by replacing any union type
17622 * definition in the ·explicit members· with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017623 * {member type definitions}, in order.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017624 *
17625 * TODO: There's a bug entry at
17626 * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17627 * which indicates that we'll keep the union types the future.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017628 */
17629 link = type->memberTypes;
17630 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017631
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017632 if (WXS_IS_TYPE_NOT_FIXED(link->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000017633 xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017634
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017635 if (WXS_IS_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017636 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017637 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017638 link->type = subLink->type;
17639 if (subLink->next != NULL) {
17640 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017641 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017642 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017643 while (subLink != NULL) {
17644 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017645 xmlMalloc(sizeof(xmlSchemaTypeLink));
17646 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017647 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017648 NULL);
17649 return (-1);
17650 }
17651 newLink->type = subLink->type;
17652 prevLink->next = newLink;
17653 prevLink = newLink;
17654 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017655
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017656 subLink = subLink->next;
17657 }
17658 }
17659 }
17660 }
17661 link = link->next;
17662 }
17663 return (0);
17664}
17665
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017666static void
17667xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17668{
17669 int has = 0, needVal = 0, normVal = 0;
17670
17671 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17672 if (has) {
17673 needVal = (type->baseType->flags &
17674 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17675 normVal = (type->baseType->flags &
17676 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17677 }
17678 if (type->facets != NULL) {
17679 xmlSchemaFacetPtr fac;
17680
17681 for (fac = type->facets; fac != NULL; fac = fac->next) {
17682 switch (fac->type) {
17683 case XML_SCHEMA_FACET_WHITESPACE:
17684 break;
17685 case XML_SCHEMA_FACET_PATTERN:
17686 normVal = 1;
17687 has = 1;
17688 break;
17689 case XML_SCHEMA_FACET_ENUMERATION:
17690 needVal = 1;
17691 normVal = 1;
17692 has = 1;
17693 break;
17694 default:
17695 has = 1;
17696 break;
17697 }
17698 }
17699 }
17700 if (normVal)
17701 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17702 if (needVal)
17703 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17704 if (has)
17705 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17706
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017707 if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017708 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17709 /*
17710 * OPTIMIZE VAL TODO: Some facets need a computed value.
17711 */
17712 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17713 (prim->builtInType != XML_SCHEMAS_STRING)) {
17714 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17715 }
17716 }
17717}
17718
17719static int
17720xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17721{
17722
17723
17724 /*
17725 * Evaluate the whitespace-facet value.
17726 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017727 if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017728 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17729 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017730 } else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017731 return (0);
17732
17733 if (type->facetSet != NULL) {
17734 xmlSchemaFacetLinkPtr lin;
17735
17736 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17737 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17738 switch (lin->facet->whitespace) {
17739 case XML_SCHEMAS_FACET_PRESERVE:
17740 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17741 break;
17742 case XML_SCHEMAS_FACET_REPLACE:
17743 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17744 break;
17745 case XML_SCHEMAS_FACET_COLLAPSE:
17746 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17747 break;
17748 default:
17749 return (-1);
17750 }
17751 return (0);
17752 }
17753 }
17754 }
17755 /*
17756 * For all ·atomic· datatypes other than string (and types ·derived·
17757 * by ·restriction· from it) the value of whiteSpace is fixed to
17758 * collapse
17759 */
17760 {
17761 xmlSchemaTypePtr anc;
17762
17763 for (anc = type->baseType; anc != NULL &&
17764 anc->builtInType != XML_SCHEMAS_ANYTYPE;
17765 anc = anc->baseType) {
17766
17767 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17768 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17769 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17770
17771 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17772 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17773 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17774
17775 } else
17776 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17777 break;
17778 }
17779 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017780 }
17781 return (0);
17782}
17783
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017784static int
17785xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17786 xmlSchemaTypePtr type)
Daniel Veillard4255d502002-04-16 15:50:10 +000017787{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017788 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17789 return(0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017790 if (! WXS_IS_TYPE_NOT_FIXED_1(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017791 return(0);
17792 type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017793
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017794 if (WXS_IS_LIST(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017795 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017796 * Corresponds to <simpleType><list>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017797 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017798 if (type->subtypes == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017799 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017800 * This one is really needed, so get out.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017801 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017802 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017803 "list type has no item-type assigned");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017804 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017805 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017806 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017807 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017808 * Corresponds to <simpleType><union>...
17809 */
17810 if (type->memberTypes == NULL) {
17811 /*
17812 * This one is really needed, so get out.
17813 */
17814 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17815 "union type has no member-types assigned");
17816 return(-1);
17817 }
17818 } else {
17819 /*
17820 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017821 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017822 if (type->baseType == NULL) {
17823 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17824 "type has no base-type assigned");
17825 return(-1);
17826 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017827 if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017828 if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17829 return(-1);
17830 /*
17831 * Variety
17832 * If the <restriction> alternative is chosen, then the
17833 * {variety} of the {base type definition}.
17834 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017835 if (WXS_IS_ATOMIC(type->baseType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017836 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017837 else if (WXS_IS_LIST(type->baseType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017838 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017839 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017840 * Inherit the itemType.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017841 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017842 type->subtypes = type->baseType->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017843 } else if (WXS_IS_UNION(type->baseType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017844 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017845 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017846 * NOTE that we won't assign the memberTypes of the base,
17847 * since this will make trouble when freeing them; we will
17848 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017849 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017850 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017851 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017852 return(0);
17853}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017854
Daniel Veillard8651f532002-04-17 09:06:27 +000017855#ifdef DEBUG_TYPE
Daniel Veillard67952602006-01-05 15:29:44 +000017856static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017857xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
17858 xmlSchemaTypePtr type)
17859{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017860 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017861 xmlGenericError(xmlGenericErrorContext,
17862 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017863 type->node->doc->URL,
17864 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000017865 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017866 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000017867 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017868 if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017869 switch (type->contentType) {
17870 case XML_SCHEMA_CONTENT_SIMPLE:
17871 xmlGenericError(xmlGenericErrorContext, "simple\n");
17872 break;
17873 case XML_SCHEMA_CONTENT_ELEMENTS:
17874 xmlGenericError(xmlGenericErrorContext, "elements\n");
17875 break;
17876 case XML_SCHEMA_CONTENT_UNKNOWN:
17877 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
17878 break;
17879 case XML_SCHEMA_CONTENT_EMPTY:
17880 xmlGenericError(xmlGenericErrorContext, "empty\n");
17881 break;
17882 case XML_SCHEMA_CONTENT_MIXED:
17883 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017884 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017885 xmlGenericError(xmlGenericErrorContext,
17886 "mixed as emptiable particle\n");
17887 else
17888 xmlGenericError(xmlGenericErrorContext, "mixed\n");
17889 break;
17890 /* Removed, since not used. */
17891 /*
17892 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
17893 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
17894 break;
17895 */
17896 case XML_SCHEMA_CONTENT_BASIC:
17897 xmlGenericError(xmlGenericErrorContext, "basic\n");
17898 break;
17899 default:
17900 xmlGenericError(xmlGenericErrorContext,
17901 "not registered !!!\n");
17902 break;
17903 }
Daniel Veillard8651f532002-04-17 09:06:27 +000017904 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017905}
Daniel Veillard8651f532002-04-17 09:06:27 +000017906#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017907
17908/*
17909* 3.14.6 Constraints on Simple Type Definition Schema Components
17910*/
17911static int
17912xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
17913 xmlSchemaTypePtr type)
17914{
17915 int res, olderrs = pctxt->nberrors;
17916
17917 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17918 return(-1);
17919
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017920 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017921 return(0);
17922
17923 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
17924 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
17925
17926 if (type->baseType == NULL) {
17927 PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
17928 "missing baseType");
17929 goto exit_failure;
17930 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017931 if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000017932 xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017933 /*
17934 * If a member type of a union is a union itself, we need to substitute
17935 * that member type for its member types.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017936 * NOTE that this might change in WXS 1.1; i.e. we will keep the union
17937 * types in WXS 1.1.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017938 */
17939 if ((type->memberTypes != NULL) &&
17940 (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
17941 return(-1);
17942 /*
17943 * SPEC src-simple-type 1
17944 * "The corresponding simple type definition, if any, must satisfy
17945 * the conditions set out in Constraints on Simple Type Definition
17946 * Schema Components (§3.14.6)."
17947 */
17948 /*
17949 * Schema Component Constraint: Simple Type Definition Properties Correct
17950 * (st-props-correct)
17951 */
17952 res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
17953 HFAILURE HERROR
17954 /*
17955 * Schema Component Constraint: Derivation Valid (Restriction, Simple)
17956 * (cos-st-restricts)
17957 */
17958 res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
17959 HFAILURE HERROR
17960 /*
17961 * TODO: Removed the error report, since it got annoying to get an
17962 * extra error report, if anything failed until now.
17963 * Enable this if needed.
17964 *
17965 * xmlSchemaPErr(ctxt, type->node,
17966 * XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
17967 * "Simple type '%s' does not satisfy the constraints "
17968 * "on simple type definitions.\n",
17969 * type->name, NULL);
17970 */
17971 /*
17972 * Schema Component Constraint: Simple Type Restriction (Facets)
17973 * (st-restrict-facets)
17974 */
17975 res = xmlSchemaCheckFacetValues(type, pctxt);
17976 HFAILURE HERROR
17977 if ((type->facetSet != NULL) ||
17978 (type->baseType->facetSet != NULL)) {
17979 res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
17980 HFAILURE HERROR
17981 }
17982 /*
17983 * Whitespace value.
17984 */
17985 res = xmlSchemaTypeFixupWhitespace(type);
17986 HFAILURE HERROR
17987 xmlSchemaTypeFixupOptimFacets(type);
17988
17989exit_error:
17990#ifdef DEBUG_TYPE
17991 xmlSchemaDebugFixedType(pctxt, type);
17992#endif
17993 if (olderrs != pctxt->nberrors)
17994 return(pctxt->err);
17995 return(0);
17996
17997exit_failure:
17998#ifdef DEBUG_TYPE
17999 xmlSchemaDebugFixedType(pctxt, type);
18000#endif
18001 return(-1);
18002}
18003
18004static int
18005xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18006 xmlSchemaTypePtr type)
18007{
18008 int res = 0, olderrs = pctxt->nberrors;
18009 xmlSchemaTypePtr baseType = type->baseType;
18010
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018011 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018012 return(0);
18013 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18014 if (baseType == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018015 PERROR_INT("xmlSchemaFixupComplexType",
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018016 "missing baseType");
18017 goto exit_failure;
18018 }
18019 /*
18020 * Fixup the base type.
18021 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018022 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018023 xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018024 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18025 /*
18026 * Skip fixup if the base type is invalid.
18027 * TODO: Generate a warning!
18028 */
18029 return(0);
18030 }
18031 /*
18032 * This basically checks if the base type can be derived.
18033 */
18034 res = xmlSchemaCheckSRCCT(pctxt, type);
18035 HFAILURE HERROR
18036 /*
18037 * Fixup the content type.
18038 */
18039 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18040 /*
18041 * Corresponds to <complexType><simpleContent>...
18042 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018043 if ((WXS_IS_COMPLEX(baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018044 (baseType->contentTypeDef != NULL) &&
18045 (WXS_IS_RESTRICTION(type))) {
18046 xmlSchemaTypePtr contentBase, content;
18047#ifdef ENABLE_NAMED_LOCALS
18048 char buf[30];
18049 const xmlChar *tmpname;
18050#endif
18051 /*
18052 * SPEC (1) If <restriction> + base type is <complexType>,
18053 * "whose own {content type} is a simple type..."
18054 */
18055 if (type->contentTypeDef != NULL) {
18056 /*
18057 * SPEC (1.1) "the simple type definition corresponding to the
18058 * <simpleType> among the [children] of <restriction> if there
18059 * is one;"
18060 * Note that this "<simpleType> among the [children]" was put
18061 * into ->contentTypeDef during parsing.
18062 */
18063 contentBase = type->contentTypeDef;
18064 type->contentTypeDef = NULL;
18065 } else {
18066 /*
18067 * (1.2) "...otherwise (<restriction> has no <simpleType>
18068 * among its [children]), the simple type definition which
18069 * is the {content type} of the ... base type."
18070 */
18071 contentBase = baseType->contentTypeDef;
18072 }
18073 /*
18074 * SPEC
18075 * "... a simple type definition which restricts the simple
18076 * type definition identified in clause 1.1 or clause 1.2
18077 * with a set of facet components"
18078 *
18079 * Create the anonymous simple type, which will be the content
18080 * type of the complex type.
18081 */
18082#ifdef ENABLE_NAMED_LOCALS
18083 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18084 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018085 content = xmlSchemaAddType(pctxt, pctxt->schema,
18086 XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018087 type->node, 0);
18088#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018089 content = xmlSchemaAddType(pctxt, pctxt->schema,
18090 XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018091 type->node, 0);
18092#endif
18093 if (content == NULL)
18094 goto exit_failure;
18095 /*
18096 * We will use the same node as for the <complexType>
18097 * to have it somehow anchored in the schema doc.
18098 */
18099 content->type = XML_SCHEMA_TYPE_SIMPLE;
18100 content->baseType = contentBase;
18101 /*
18102 * Move the facets, previously anchored on the
18103 * complexType during parsing.
18104 */
18105 content->facets = type->facets;
18106 type->facets = NULL;
18107 content->facetSet = type->facetSet;
18108 type->facetSet = NULL;
18109
18110 type->contentTypeDef = content;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018111 if (WXS_IS_TYPE_NOT_FIXED(contentBase))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018112 xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018113 /*
18114 * Fixup the newly created type. We don't need to check
18115 * for circularity here.
18116 */
18117 res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18118 HFAILURE HERROR
18119 res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18120 HFAILURE HERROR
18121
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018122 } else if ((WXS_IS_COMPLEX(baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018123 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18124 (WXS_IS_RESTRICTION(type))) {
18125 /*
18126 * SPEC (2) If <restriction> + base is a mixed <complexType> with
18127 * an emptiable particle, then a simple type definition which
18128 * restricts the <restriction>'s <simpleType> child.
18129 */
18130 if ((type->contentTypeDef == NULL) ||
18131 (type->contentTypeDef->baseType == NULL)) {
18132 /*
18133 * TODO: Check if this ever happens.
18134 */
18135 xmlSchemaPCustomErr(pctxt,
18136 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018137 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018138 "Internal error: xmlSchemaTypeFixup, "
18139 "complex type '%s': the <simpleContent><restriction> "
18140 "is missing a <simpleType> child, but was not catched "
18141 "by xmlSchemaCheckSRCCT()", type->name);
18142 goto exit_failure;
18143 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018144 } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018145 /*
18146 * SPEC (3) If <extension> + base is <complexType> with
18147 * <simpleType> content, "...then the {content type} of that
18148 * complex type definition"
18149 */
18150 if (baseType->contentTypeDef == NULL) {
18151 /*
18152 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18153 * should have catched this already.
18154 */
18155 xmlSchemaPCustomErr(pctxt,
18156 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018157 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018158 "Internal error: xmlSchemaTypeFixup, "
18159 "complex type '%s': the <extension>ed base type is "
18160 "a complex type with no simple content type",
18161 type->name);
18162 goto exit_failure;
18163 }
18164 type->contentTypeDef = baseType->contentTypeDef;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018165 } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018166 /*
18167 * SPEC (4) <extension> + base is <simpleType>
18168 * "... then that simple type definition"
18169 */
18170 type->contentTypeDef = baseType;
18171 } else {
18172 /*
18173 * TODO: Check if this ever happens.
18174 */
18175 xmlSchemaPCustomErr(pctxt,
18176 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018177 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018178 "Internal error: xmlSchemaTypeFixup, "
18179 "complex type '%s' with <simpleContent>: unhandled "
18180 "derivation case", type->name);
18181 goto exit_failure;
18182 }
18183 } else {
18184 int dummySequence = 0;
18185 xmlSchemaParticlePtr particle =
18186 (xmlSchemaParticlePtr) type->subtypes;
18187 /*
18188 * Corresponds to <complexType><complexContent>...
18189 *
18190 * NOTE that the effective mixed was already set during parsing of
18191 * <complexType> and <complexContent>; its flag value is
18192 * XML_SCHEMAS_TYPE_MIXED.
18193 *
18194 * Compute the "effective content":
18195 * (2.1.1) + (2.1.2) + (2.1.3)
18196 */
18197 if ((particle == NULL) ||
18198 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18199 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18200 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18201 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18202 (particle->minOccurs == 0))) &&
18203 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18204 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18205 /*
18206 * SPEC (2.1.4) "If the ·effective mixed· is true, then
18207 * a particle whose properties are as follows:..."
18208 *
18209 * Empty sequence model group with
18210 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18211 * NOTE that we sill assign it the <complexType> node to
18212 * somehow anchor it in the doc.
18213 */
18214 if ((particle == NULL) ||
18215 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18216 /*
18217 * Create the particle.
18218 */
18219 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
18220 type->node, 1, 1);
18221 if (particle == NULL)
18222 goto exit_failure;
18223 /*
18224 * Create the model group.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018225 */ /* URGENT TODO: avoid adding to pending items. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018226 particle->children = (xmlSchemaTreeItemPtr)
18227 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18228 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18229 if (particle->children == NULL)
18230 goto exit_failure;
18231
18232 type->subtypes = (xmlSchemaTypePtr) particle;
18233 }
18234 dummySequence = 1;
18235 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18236 } else {
18237 /*
18238 * SPEC (2.1.5) "otherwise empty"
18239 */
18240 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18241 }
18242 } else {
18243 /*
18244 * SPEC (2.2) "otherwise the particle corresponding to the
18245 * <all>, <choice>, <group> or <sequence> among the
18246 * [children]."
18247 */
18248 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18249 }
18250 /*
18251 * Compute the "content type".
18252 */
18253 if (WXS_IS_RESTRICTION(type)) {
18254 /*
18255 * SPEC (3.1) "If <restriction>..."
18256 * (3.1.1) + (3.1.2) */
18257 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18258 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18259 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18260 }
18261 } else {
18262 /*
18263 * SPEC (3.2) "If <extension>..."
18264 */
18265 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18266 /*
18267 * SPEC (3.2.1)
18268 */
18269 type->contentType = baseType->contentType;
18270 type->subtypes = baseType->subtypes;
18271 /*
18272 * NOTE that the effective mixed is ignored here.
18273 */
18274 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18275 /*
18276 * SPEC (3.2.2)
18277 */
18278 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18279 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18280 } else {
18281 /*
18282 * SPEC (3.2.3)
18283 */
18284 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18285 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18286 /*
18287 * "A model group whose {compositor} is sequence and whose
18288 * {particles} are..."
18289 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018290 if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18291 (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18292 ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18293 XML_SCHEMA_TYPE_ALL))
18294 {
18295 /*
18296 * SPEC cos-all-limited (1)
18297 */
18298 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18299 /* TODO: error code */
18300 XML_SCHEMAP_COS_ALL_LIMITED,
18301 WXS_ITEM_NODE(type), NULL,
18302 "The type has an 'all' model group in its "
18303 "{content type} and thus cannot be derived from "
18304 "a non-empty type, since this would produce a "
18305 "'sequence' model group containing the 'all' "
18306 "model group; 'all' model groups are not "
18307 "allowed to appear inside other model groups",
18308 NULL, NULL);
18309
18310 } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18311 (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18312 ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18313 XML_SCHEMA_TYPE_ALL))
18314 {
18315 /*
18316 * SPEC cos-all-limited (1)
18317 */
18318 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18319 /* TODO: error code */
18320 XML_SCHEMAP_COS_ALL_LIMITED,
18321 WXS_ITEM_NODE(type), NULL,
18322 "A type cannot be derived by extension from a type "
18323 "which has an 'all' model group in its "
18324 "{content type}, since this would produce a "
18325 "'sequence' model group containing the 'all' "
18326 "model group; 'all' model groups are not "
18327 "allowed to appear inside other model groups",
18328 NULL, NULL);
18329
18330 } else if (! dummySequence) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018331 xmlSchemaTreeItemPtr effectiveContent =
18332 (xmlSchemaTreeItemPtr) type->subtypes;
18333 /*
18334 * Create the particle.
18335 */
18336 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
18337 type->node, 1, 1);
18338 if (particle == NULL)
18339 goto exit_failure;
18340 /*
18341 * Create the "sequence" model group.
18342 */
18343 particle->children = (xmlSchemaTreeItemPtr)
18344 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18345 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18346 if (particle->children == NULL)
18347 goto exit_failure;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018348 WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018349 /*
18350 * SPEC "the particle of the {content type} of
18351 * the ... base ..."
18352 * Create a duplicate of the base type's particle
18353 * and assign its "term" to it.
18354 */
18355 particle->children->children =
18356 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18357 pctxt->schema, type->node,
18358 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
18359 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
18360 if (particle->children->children == NULL)
18361 goto exit_failure;
18362 particle = (xmlSchemaParticlePtr)
18363 particle->children->children;
18364 particle->children =
18365 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
18366 /*
18367 * SPEC "followed by the ·effective content·."
18368 */
18369 particle->next = effectiveContent;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018370 /*
18371 * This all will result in:
18372 * new-particle
18373 * --> new-sequence(
18374 * new-particle
18375 * --> base-model,
18376 * this-particle
18377 * --> this-model
18378 * )
18379 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018380 } else {
18381 /*
18382 * This is the case when there is already an empty
18383 * <sequence> with minOccurs==maxOccurs==1.
18384 * Just add the base types's content type.
18385 * NOTE that, although we miss to add an intermediate
18386 * <sequence>, this should produce no difference to
18387 * neither the regex compilation of the content model,
18388 * nor to the complex type contraints.
18389 */
18390 particle->children->children =
18391 (xmlSchemaTreeItemPtr) baseType->subtypes;
18392 }
18393 }
18394 }
18395 }
18396 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018397 * Now fixup attribute uses:
18398 * - expand attr. group references
18399 * - intersect attribute wildcards
18400 * - inherit attribute uses of the base type
18401 * - inherit or union attr. wildcards if extending
18402 * - apply attr. use prohibitions if restricting
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018403 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018404 res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018405 HFAILURE HERROR
18406 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018407 * Apply the complex type component constraints; this will not
18408 * check attributes, since this is done in
18409 * xmlSchemaFixupTypeAttributeUses().
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018410 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018411 res = xmlSchemaCheckCTComponent(pctxt, type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018412 HFAILURE HERROR
18413
18414#ifdef DEBUG_TYPE
18415 xmlSchemaDebugFixedType(pctxt, type);
18416#endif
18417 if (olderrs != pctxt->nberrors)
18418 return(pctxt->err);
18419 else
18420 return(0);
18421
18422exit_error:
18423 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18424#ifdef DEBUG_TYPE
18425 xmlSchemaDebugFixedType(pctxt, type);
18426#endif
18427 return(pctxt->err);
18428
18429exit_failure:
18430 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18431#ifdef DEBUG_TYPE
18432 xmlSchemaDebugFixedType(pctxt, type);
18433#endif
18434 return(-1);
18435}
18436
18437
18438/**
18439 * xmlSchemaTypeFixup:
18440 * @typeDecl: the schema type definition
18441 * @ctxt: the schema parser context
18442 *
18443 * Fixes the content model of the type.
18444 * URGENT TODO: We need an int result!
18445 */
18446static int
18447xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018448 xmlSchemaAbstractCtxtPtr actxt)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018449{
18450 if (type == NULL)
18451 return(0);
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018452 if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18453 AERROR_INT("xmlSchemaTypeFixup",
18454 "this function needs a parser context");
18455 return(-1);
18456 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018457 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018458 return(0);
18459 if (type->type == XML_SCHEMA_TYPE_COMPLEX)
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018460 return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018461 else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018462 return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018463 return(0);
Daniel Veillard4255d502002-04-16 15:50:10 +000018464}
18465
18466/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018467 * xmlSchemaCheckFacet:
18468 * @facet: the facet
18469 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000018470 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018471 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018472 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018473 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018474 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018475 * Returns 0 if valid, a positive error code if not valid and
18476 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018477 */
18478int
18479xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018480 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018481 xmlSchemaParserCtxtPtr pctxt,
18482 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018483{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018484 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018485
Daniel Veillardce682bc2004-11-05 17:22:25 +000018486 if ((facet == NULL) || (typeDecl == NULL))
18487 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018488 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018489 * TODO: will the parser context be given if used from
18490 * the relaxNG module?
18491 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018492 if (pctxt == NULL)
18493 ctxtGiven = 0;
18494 else
18495 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018496
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018497 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018498 case XML_SCHEMA_FACET_MININCLUSIVE:
18499 case XML_SCHEMA_FACET_MINEXCLUSIVE:
18500 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018501 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18502 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018503 /*
18504 * Okay we need to validate the value
18505 * at that point.
18506 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018507 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018508
18509 /* 4.3.5.5 Constraints on enumeration Schema Components
18510 * Schema Component Constraint: enumeration valid restriction
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018511 * It is an ·error· if any member of {value} is not in the
18512 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018513 *
18514 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018515 * The value ·must· be in the
18516 * ·value space· of the ·base type·.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018517 */
18518 /*
18519 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018520 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018521 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018522 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018523 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018524 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018525 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018526 */
18527 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18528 base = typeDecl->baseType;
18529 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018530 PERROR_INT("xmlSchemaCheckFacet",
18531 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018532 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018533 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018534 } else
18535 base = typeDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018536
18537 if (! ctxtGiven) {
18538 /*
18539 * A context is needed if called from RelaxNG.
18540 */
18541 pctxt = xmlSchemaNewParserCtxt("*");
18542 if (pctxt == NULL)
18543 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018544 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018545 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018546 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018547 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018548 * facet->node is just the node holding the facet
18549 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018550 * of the facet.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018551 */
18552 ret = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018553 ACTXT_CAST pctxt, facet->node, base,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018554 facet->value, &(facet->val), 1, 1, 0);
18555 if (ret != 0) {
18556 if (ret < 0) {
18557 /* No error message for RelaxNG. */
18558 if (ctxtGiven) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018559 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018560 XML_SCHEMAP_INTERNAL, facet->node, NULL,
18561 "Internal error: xmlSchemaCheckFacet, "
18562 "failed to validate the value '%s' of the "
18563 "facet '%s' against the base type",
18564 facet->value, xmlSchemaFacetTypeToString(facet->type));
18565 }
18566 goto internal_error;
18567 }
18568 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18569 /* No error message for RelaxNG. */
18570 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018571 xmlChar *str = NULL;
18572
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018573 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018574 ret, facet->node, WXS_BASIC_CAST facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018575 "The value '%s' of the facet does not validate "
18576 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018577 facet->value,
18578 xmlSchemaFormatQName(&str,
18579 base->targetNamespace, base->name));
18580 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018581 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018582 goto exit;
18583 } else if (facet->val == NULL) {
18584 if (ctxtGiven) {
18585 PERROR_INT("xmlSchemaCheckFacet",
18586 "value was not computed");
18587 }
18588 TODO
18589 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018590 break;
18591 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018592 case XML_SCHEMA_FACET_PATTERN:
18593 facet->regexp = xmlRegexpCompile(facet->value);
18594 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018595 ret = XML_SCHEMAP_REGEXP_INVALID;
18596 /* No error message for RelaxNG. */
18597 if (ctxtGiven) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018598 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018599 ret, facet->node, WXS_BASIC_CAST typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018600 "The value '%s' of the facet 'pattern' is not a "
18601 "valid regular expression",
18602 facet->value, NULL);
18603 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018604 }
18605 break;
18606 case XML_SCHEMA_FACET_TOTALDIGITS:
18607 case XML_SCHEMA_FACET_FRACTIONDIGITS:
18608 case XML_SCHEMA_FACET_LENGTH:
18609 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018610 case XML_SCHEMA_FACET_MINLENGTH:
18611
18612 if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18613 ret = xmlSchemaValidatePredefinedType(
18614 xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18615 facet->value, &(facet->val));
18616 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018617 ret = xmlSchemaValidatePredefinedType(
18618 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18619 facet->value, &(facet->val));
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018620 }
18621 if (ret != 0) {
18622 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018623 /* No error message for RelaxNG. */
18624 if (ctxtGiven) {
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018625 PERROR_INT("xmlSchemaCheckFacet",
18626 "validating facet value");
18627 }
18628 goto internal_error;
18629 }
18630 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18631 /* No error message for RelaxNG. */
18632 if (ctxtGiven) {
18633 /* error code */
18634 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18635 ret, facet->node, WXS_BASIC_CAST typeDecl,
18636 "The value '%s' of the facet '%s' is not a valid '%s'",
18637 facet->value,
18638 xmlSchemaFacetTypeToString(facet->type),
18639 (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18640 BAD_CAST "nonNegativeInteger" :
18641 BAD_CAST "positiveInteger",
18642 NULL);
18643 }
18644 }
18645 break;
18646
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018647 case XML_SCHEMA_FACET_WHITESPACE:{
18648 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18649 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18650 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18651 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18652 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18653 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18654 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018655 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18656 /* No error message for RelaxNG. */
18657 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018658 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018659 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018660 ret, facet->node, WXS_BASIC_CAST typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018661 "The value '%s' of the facet 'whitespace' is not "
18662 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018663 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018664 }
18665 }
18666 default:
18667 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018668 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018669exit:
18670 if ((! ctxtGiven) && (pctxt != NULL))
18671 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018672 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018673internal_error:
18674 if ((! ctxtGiven) && (pctxt != NULL))
18675 xmlSchemaFreeParserCtxt(pctxt);
18676 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018677}
18678
18679/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018680 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000018681 * @typeDecl: the schema type definition
18682 * @ctxt: the schema parser context
18683 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018684 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000018685 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018686static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018687xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018688 xmlSchemaParserCtxtPtr pctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000018689{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018690 int res, olderrs = pctxt->nberrors;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018691 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018692 /*
18693 * NOTE: It is intended to use the facets list, instead
18694 * of facetSet.
18695 */
18696 if (typeDecl->facets != NULL) {
18697 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018698
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018699 /*
18700 * Temporarily assign the "schema" to the validation context
18701 * of the parser context. This is needed for NOTATION validation.
18702 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018703 if (pctxt->vctxt == NULL) {
18704 if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18705 return(-1);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018706 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018707 pctxt->vctxt->schema = pctxt->schema;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018708 while (facet != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018709 res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18710 HFAILURE
Daniel Veillard01fa6152004-06-29 17:04:39 +000018711 facet = facet->next;
18712 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018713 pctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018714 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018715 if (olderrs != pctxt->nberrors)
18716 return(pctxt->err);
18717 return(0);
18718exit_failure:
18719 return(-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018720}
18721
18722/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018723 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018724 * @ctxtMGroup: the searched model group
18725 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018726 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018727 *
18728 * This one is intended to be used by
18729 * xmlSchemaCheckGroupDefCircular only.
18730 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018731 * Returns the particle with the circular model group definition reference,
18732 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018733 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018734static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018735xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018736 xmlSchemaTreeItemPtr particle)
18737{
18738 xmlSchemaTreeItemPtr circ = NULL;
18739 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018740 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018741
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018742 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018743 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018744 if (term == NULL)
18745 continue;
18746 switch (term->type) {
18747 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018748 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018749 if (gdef == groupDef)
18750 return (particle);
18751 /*
18752 * Mark this model group definition to avoid infinite
18753 * recursion on circular references not yet examined.
18754 */
18755 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18756 continue;
18757 if (gdef->children != NULL) {
18758 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18759 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18760 gdef->children->children);
18761 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18762 if (circ != NULL)
18763 return (circ);
18764 }
18765 break;
18766 case XML_SCHEMA_TYPE_SEQUENCE:
18767 case XML_SCHEMA_TYPE_CHOICE:
18768 case XML_SCHEMA_TYPE_ALL:
18769 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18770 if (circ != NULL)
18771 return (circ);
18772 break;
18773 default:
18774 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018775 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018776 }
18777 return (NULL);
18778}
18779
18780/**
18781 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018782 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018783 * @ctxt: the parser context
18784 * @name: the name
18785 *
18786 * Checks for circular references to model group definitions.
18787 */
18788static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018789xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018790 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018791{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018792 /*
18793 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018794 * 2 Circular groups are disallowed. That is, within the {particles}
18795 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018796 * is the group itself.
18797 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018798 if ((item == NULL) ||
18799 (item->type != XML_SCHEMA_TYPE_GROUP) ||
18800 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018801 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018802 {
18803 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018804
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018805 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018806 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018807 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018808 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018809 * TODO: The error report is not adequate: this constraint
18810 * is defined for model groups but not definitions, but since
18811 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018812 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018813 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018814 */
18815 xmlSchemaPCustomErr(ctxt,
18816 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018817 NULL, WXS_ITEM_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018818 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018819 "defined", xmlSchemaFormatQName(&str,
18820 item->targetNamespace, item->name));
18821 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018822 /*
18823 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018824 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018825 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018826 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018827 }
18828 }
18829}
18830
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018831/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018832 * xmlSchemaModelGroupToModelGroupDefFixup:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018833 * @ctxt: the parser context
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018834 * @mg: the model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018835 *
18836 * Assigns the model group of model group definitions to the "term"
18837 * of the referencing particle.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018838 * In xmlSchemaResolveModelGroupParticleReferences the model group
18839 * definitions were assigned to the "term", since needed for the
18840 * circularity check.
18841 *
18842 * Schema Component Constraint:
18843 * All Group Limited (cos-all-limited) (1.2)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018844 */
18845static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018846xmlSchemaModelGroupToModelGroupDefFixup(
18847 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18848 xmlSchemaModelGroupPtr mg)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018849{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018850 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
18851
18852 while (particle != NULL) {
18853 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
18854 ((WXS_PARTICLE_TERM(particle))->type !=
18855 XML_SCHEMA_TYPE_GROUP))
18856 {
18857 particle = WXS_PTC_CAST particle->next;
18858 continue;
18859 }
18860 if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
18861 /*
18862 * TODO: Remove the particle.
18863 */
18864 WXS_PARTICLE_TERM(particle) = NULL;
18865 particle = WXS_PTC_CAST particle->next;
18866 continue;
18867 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018868 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018869 * Assign the model group to the {term} of the particle.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018870 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018871 WXS_PARTICLE_TERM(particle) =
18872 WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
18873
18874 particle = WXS_PTC_CAST particle->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018875 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018876}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018877
18878/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018879 * xmlSchemaCheckAttrGroupCircularRecur:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018880 * @ctxtGr: the searched attribute group
18881 * @attr: the current attribute list to be processed
18882 *
18883 * This one is intended to be used by
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018884 * xmlSchemaCheckAttrGroupCircular only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018885 *
18886 * Returns the circular attribute grou reference, otherwise NULL.
18887 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018888static xmlSchemaQNameRefPtr
18889xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
18890 xmlSchemaItemListPtr list)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018891{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018892 xmlSchemaAttributeGroupPtr gr;
18893 xmlSchemaQNameRefPtr ref, circ;
18894 int i;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018895 /*
18896 * We will search for an attribute group reference which
18897 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018898 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018899 for (i = 0; i < list->nbItems; i++) {
18900 ref = list->items[i];
18901 if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
18902 (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
18903 (ref->item != NULL))
18904 {
18905 gr = WXS_ATTR_GROUP_CAST ref->item;
18906 if (gr == ctxtGr)
18907 return(ref);
18908 if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
18909 continue;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018910 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018911 * Mark as visited to avoid infinite recursion on
18912 * circular references not yet examined.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018913 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018914 if ((gr->attrUses) &&
18915 (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
18916 {
18917 gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
18918 circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
18919 (xmlSchemaItemListPtr) gr->attrUses);
18920 gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
18921 if (circ != NULL)
18922 return (circ);
18923 }
18924
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018925 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018926 }
18927 return (NULL);
18928}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018929
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018930/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018931 * xmlSchemaCheckAttrGroupCircular:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018932 * attrGr: the attribute group definition
18933 * @ctxt: the parser context
18934 * @name: the name
18935 *
18936 * Checks for circular references of attribute groups.
18937 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018938static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018939xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018940 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018941{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018942 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018943 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018944 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018945 * 3 Circular group reference is disallowed outside <redefine>.
18946 * That is, unless this element information item's parent is
18947 * <redefine>, then among the [children], if any, there must
18948 * not be an <attributeGroup> with ref [attribute] which resolves
18949 * to the component corresponding to this <attributeGroup>. Indirect
18950 * circularity is also ruled out. That is, when QName resolution
18951 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
18952 * any <attributeGroup>s with a ref [attribute] among the [children],
18953 * it must not be the case that a ·QName· is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018954 * which resolves to the component corresponding to this <attributeGroup>.
18955 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018956 if (attrGr->attrUses == NULL)
18957 return(0);
18958 else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
18959 return(0);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018960 else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018961 xmlSchemaQNameRefPtr circ;
18962
18963 circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
18964 (xmlSchemaItemListPtr) attrGr->attrUses);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018965 if (circ != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018966 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018967 /*
18968 * TODO: Report the referenced attr group as QName.
18969 */
18970 xmlSchemaPCustomErr(ctxt,
18971 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018972 NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018973 "Circular reference to the attribute group '%s' "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018974 "defined", xmlSchemaGetComponentQName(&str, attrGr));
18975 FREE_AND_NULL(str);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018976 /*
18977 * NOTE: We will cut the reference to avoid further
18978 * confusion of the processor.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018979 * BADSPEC TODO: The spec should define how to process in this case.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018980 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018981 circ->item = NULL;
18982 return(ctxt->err);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018983 }
18984 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018985 return(0);
18986}
18987
18988static int
18989xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
18990 xmlSchemaAttributeGroupPtr attrGr);
18991
18992/**
18993 * xmlSchemaExpandAttributeGroupRefs:
18994 * @pctxt: the parser context
18995 * @node: the node of the component holding the attribute uses
18996 * @completeWild: the intersected wildcard to be returned
18997 * @list: the attribute uses
18998 *
18999 * Substitutes contained attribute group references
19000 * for their attribute uses. Wilcards are intersected.
19001 * Attribute use prohibitions are removed from the list
19002 * and returned via the @prohibs list.
19003 * Pointlessness of attr. prohibs, if a matching attr. decl
19004 * is existent a well, are checked.
19005 */
19006static int
19007xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19008 xmlSchemaBasicItemPtr item,
19009 xmlSchemaWildcardPtr *completeWild,
19010 xmlSchemaItemListPtr list,
19011 xmlSchemaItemListPtr prohibs)
19012{
19013 xmlSchemaAttributeGroupPtr gr;
19014 xmlSchemaAttributeUsePtr use;
19015 xmlSchemaItemListPtr sublist;
19016 int i, j;
19017 int created = (*completeWild == NULL) ? 0 : 1;
19018
19019 if (prohibs)
19020 prohibs->nbItems = 0;
19021
19022 for (i = 0; i < list->nbItems; i++) {
19023 use = list->items[i];
19024
19025 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19026 if (prohibs == NULL) {
19027 PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19028 "unexpected attr prohibition found");
19029 return(-1);
19030 }
19031 /*
19032 * Remove from attribute uses.
19033 */
19034 if (xmlSchemaItemListRemove(list, i) == -1)
19035 return(-1);
19036 i--;
19037 /*
19038 * Note that duplicate prohibitions were already
19039 * handled at parsing time.
19040 */
19041 /*
19042 * Add to list of prohibitions.
19043 */
19044 xmlSchemaItemListAddSize(prohibs, 2, use);
19045 continue;
19046 }
19047 if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19048 ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19049 {
19050 if ((WXS_QNAME_CAST use)->item == NULL)
19051 return(-1);
19052 gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19053 /*
19054 * Expand the referenced attr. group.
19055 * TODO: remove this, this is done in a previous step, so
19056 * already done here.
19057 */
19058 if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19059 if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19060 return(-1);
19061 }
19062 /*
19063 * Build the 'complete' wildcard; i.e. intersect multiple
19064 * wildcards.
19065 */
19066 if (gr->attributeWildcard != NULL) {
19067 if (*completeWild == NULL) {
19068 *completeWild = gr->attributeWildcard;
19069 } else {
19070 if (! created) {
19071 xmlSchemaWildcardPtr tmpWild;
19072
19073 /*
19074 * Copy the first encountered wildcard as context,
19075 * except for the annotation.
19076 *
19077 * Although the complete wildcard might not correspond
19078 * to any node in the schema, we will anchor it on
19079 * the node of the owner component.
19080 */
19081 tmpWild = xmlSchemaAddWildcard(pctxt, pctxt->schema,
19082 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19083 WXS_ITEM_NODE(item));
19084 if (tmpWild == NULL)
19085 return(-1);
19086 if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19087 tmpWild, *completeWild) == -1)
19088 return (-1);
19089 tmpWild->processContents = (*completeWild)->processContents;
19090 *completeWild = tmpWild;
19091 created = 1;
19092 }
19093
19094 if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19095 gr->attributeWildcard) == -1)
19096 return(-1);
19097 }
19098 }
19099 /*
19100 * Just remove the reference if the referenced group does not
19101 * contain any attribute uses.
19102 */
19103 if (gr->attrUses == NULL) {
19104 if (xmlSchemaItemListRemove(list, i) == -1)
19105 return(-1);
19106 i--;
19107 continue;
19108 }
19109 /*
19110 * Add the attribute uses.
19111 */
19112 sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19113 if (sublist->nbItems != 0) {
19114 list->items[i] = sublist->items[0];
19115 if (sublist->nbItems != 1) {
19116 for (j = 1; j < sublist->nbItems; j++) {
19117 i++;
19118 if (xmlSchemaItemListInsert(list,
19119 sublist->items[j], i) == -1)
19120 return(-1);
19121 }
19122 }
19123 }
19124 }
19125
19126 }
19127 /*
19128 * Handle pointless prohibitions of declared attributes.
19129 */
19130 if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19131 xmlSchemaAttributeUseProhibPtr prohib;
19132
19133 for (i = prohibs->nbItems -1; i >= 0; i--) {
19134 prohib = prohibs->items[i];
19135 for (j = 0; j < list->nbItems; j++) {
19136 use = list->items[j];
19137
19138 if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19139 (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19140 {
19141 xmlChar *str = NULL;
19142
19143 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19144 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19145 prohib->node, NULL,
19146 "Skipping pointless attribute use prohibition "
19147 "'%s', since a corresponding attribute use "
19148 "exists already in the type definition",
19149 xmlSchemaFormatQName(&str,
19150 prohib->targetNamespace, prohib->name),
19151 NULL, NULL);
19152 FREE_AND_NULL(str);
19153 /*
19154 * Remove the prohibition.
19155 */
19156 if (xmlSchemaItemListRemove(prohibs, i) == -1)
19157 return(-1);
19158 break;
19159 }
19160 }
19161 }
19162 }
19163 return(0);
19164}
19165
19166/**
19167 * xmlSchemaAttributeGroupExpandRefs:
19168 * @pctxt: the parser context
19169 * @attrGr: the attribute group definition
19170 *
19171 * Computation of:
19172 * {attribute uses} property
19173 * {attribute wildcard} property
19174 *
19175 * Substitutes contained attribute group references
19176 * for their attribute uses. Wilcards are intersected.
19177 */
19178static int
19179xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19180 xmlSchemaAttributeGroupPtr attrGr)
19181{
19182 if ((attrGr->attrUses == NULL) ||
19183 (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19184 return(0);
19185
19186 attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19187 if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19188 &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19189 return(-1);
19190 return(0);
19191}
19192
19193/**
19194 * xmlSchemaAttributeGroupExpandRefs:
19195 * @pctxt: the parser context
19196 * @attrGr: the attribute group definition
19197 *
19198 * Substitutes contained attribute group references
19199 * for their attribute uses. Wilcards are intersected.
19200 *
19201 * Schema Component Constraint:
19202 * Attribute Group Definition Properties Correct (ag-props-correct)
19203 */
19204static int
19205xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19206 xmlSchemaAttributeGroupPtr attrGr)
19207{
19208 /*
19209 * SPEC ag-props-correct
19210 * (1) "The values of the properties of an attribute group definition
19211 * must be as described in the property tableau in The Attribute
19212 * Group Definition Schema Component (§3.6.1), modulo the impact of
19213 * Missing Sub-components (§5.3);"
19214 */
19215
19216 if ((attrGr->attrUses != NULL) &&
19217 (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19218 {
19219 xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19220 xmlSchemaAttributeUsePtr use, tmp;
19221 int i, j, hasId = 0;
19222
19223 for (i = uses->nbItems -1; i >= 0; i--) {
19224 use = uses->items[i];
19225 /*
19226 * SPEC ag-props-correct
19227 * (2) "Two distinct members of the {attribute uses} must not have
19228 * {attribute declaration}s both of whose {name}s match and whose
19229 * {target namespace}s are identical."
19230 */
19231 if (i > 0) {
19232 for (j = i -1; j >= 0; j--) {
19233 tmp = uses->items[j];
19234 if ((WXS_ATTRUSE_DECL_NAME(use) ==
19235 WXS_ATTRUSE_DECL_NAME(tmp)) &&
19236 (WXS_ATTRUSE_DECL_TNS(use) ==
19237 WXS_ATTRUSE_DECL_TNS(tmp)))
19238 {
19239 xmlChar *str = NULL;
19240
19241 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19242 XML_SCHEMAP_AG_PROPS_CORRECT,
19243 attrGr->node, WXS_BASIC_CAST attrGr,
19244 "Duplicate %s",
19245 xmlSchemaGetComponentDesignation(&str, use),
19246 NULL);
19247 FREE_AND_NULL(str);
19248 /*
19249 * Remove the duplicate.
19250 */
19251 if (xmlSchemaItemListRemove(uses, i) == -1)
19252 return(-1);
19253 goto next_use;
19254 }
19255 }
19256 }
19257 /*
19258 * SPEC ag-props-correct
19259 * (3) "Two distinct members of the {attribute uses} must not have
19260 * {attribute declaration}s both of whose {type definition}s are or
19261 * are derived from ID."
19262 * TODO: Does 'derived' include member-types of unions?
19263 */
19264 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19265 if (xmlSchemaIsDerivedFromBuiltInType(
19266 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19267 {
19268 if (hasId) {
19269 xmlChar *str = NULL;
19270
19271 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19272 XML_SCHEMAP_AG_PROPS_CORRECT,
19273 attrGr->node, WXS_BASIC_CAST attrGr,
19274 "There must not exist more than one attribute "
19275 "declaration of type 'xs:ID' "
19276 "(or derived from 'xs:ID'). The %s violates this "
19277 "constraint",
19278 xmlSchemaGetComponentDesignation(&str, use),
19279 NULL);
19280 FREE_AND_NULL(str);
19281 if (xmlSchemaItemListRemove(uses, i) == -1)
19282 return(-1);
19283 }
19284 hasId = 1;
19285 }
19286 }
19287next_use: {}
19288 }
19289 }
19290 return(0);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019291}
19292
19293/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019294 * xmlSchemaResolveAttrGroupReferences:
Daniel Veillard13e04c62002-04-23 17:51:29 +000019295 * @attrgrpDecl: the schema attribute definition
19296 * @ctxt: the schema parser context
19297 * @name: the attribute name
19298 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019299 * Resolves references to attribute group definitions.
Daniel Veillard13e04c62002-04-23 17:51:29 +000019300 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019301static int
19302xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19303 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard13e04c62002-04-23 17:51:29 +000019304{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019305 xmlSchemaAttributeGroupPtr group;
Daniel Veillard13e04c62002-04-23 17:51:29 +000019306
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019307 if (ref->item != NULL)
19308 return(0);
19309 group = xmlSchemaGetAttributeGroup(ctxt->schema,
19310 ref->name,
19311 ref->targetNamespace);
19312 if (group == NULL) {
19313 xmlSchemaPResCompAttrErr(ctxt,
19314 XML_SCHEMAP_SRC_RESOLVE,
19315 NULL, ref->node,
19316 "ref", ref->name, ref->targetNamespace,
19317 ref->itemType, NULL);
19318 return(ctxt->err);
Daniel Veillard3646d642004-06-02 19:19:14 +000019319 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019320 ref->item = WXS_BASIC_CAST group;
19321 return(0);
Daniel Veillard13e04c62002-04-23 17:51:29 +000019322}
19323
19324/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019325 * xmlSchemaCheckAttrPropsCorrect:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019326 * @item: an schema attribute declaration/use
19327 * @ctxt: a schema parser context
19328 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019329 *
19330 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019331 * Schema Component Constraint:
19332 * Attribute Declaration Properties Correct (a-props-correct)
Daniel Veillard4255d502002-04-16 15:50:10 +000019333 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019334 * Validates the value constraints of an attribute declaration/use.
19335 * NOTE that this needs the simle type definitions to be already
19336 * builded and checked.
Daniel Veillard4255d502002-04-16 15:50:10 +000019337 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019338static int
19339xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19340 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019341{
19342
19343 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019344 * SPEC a-props-correct (1)
19345 * "The values of the properties of an attribute declaration must
19346 * be as described in the property tableau in The Attribute
19347 * Declaration Schema Component (§3.2.1), modulo the impact of
19348 * Missing Sub-components (§5.3)."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019349 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019350
19351 if (WXS_ATTR_TYPEDEF(attr) == NULL)
19352 return(0);
19353
19354 if (attr->defValue != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019355 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019356
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019357 /*
19358 * SPEC a-props-correct (3)
19359 * "If the {type definition} is or is derived from ID then there
19360 * must not be a {value constraint}."
19361 */
19362 if (xmlSchemaIsDerivedFromBuiltInType(
19363 WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19364 {
19365 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19366 XML_SCHEMAP_A_PROPS_CORRECT_3,
19367 NULL, WXS_BASIC_CAST attr,
19368 "Value constraints are not allowed if the type definition "
19369 "is or is derived from xs:ID",
19370 NULL, NULL);
19371 return(pctxt->err);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019372 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019373 /*
19374 * SPEC a-props-correct (2)
19375 * "if there is a {value constraint}, the canonical lexical
19376 * representation of its value must be ·valid· with respect
19377 * to the {type definition} as defined in String Valid (§3.14.4)."
19378 * TODO: Don't care about the *cononical* stuff here, this requirement
19379 * will be removed in WXS 1.1 anyway.
19380 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019381 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019382 attr->node, WXS_ATTR_TYPEDEF(attr),
19383 attr->defValue, &(attr->defVal),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019384 1, 1, 0);
19385 if (ret != 0) {
19386 if (ret < 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019387 PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019388 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019389 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019390 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019391 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019392 XML_SCHEMAP_A_PROPS_CORRECT_2,
19393 NULL, WXS_BASIC_CAST attr,
19394 "The value of the value constraint is not valid",
19395 NULL, NULL);
19396 return(pctxt->err);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019397 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019398 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019399
19400 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019401}
19402
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019403static xmlSchemaElementPtr
19404xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19405 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019406{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019407 xmlSchemaElementPtr ret;
19408
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019409 if (WXS_SUBST_HEAD(ancestor) == NULL)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019410 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019411 if (WXS_SUBST_HEAD(ancestor) == elemDecl)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019412 return (ancestor);
19413
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019414 if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019415 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019416 WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019417 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019418 WXS_SUBST_HEAD(ancestor));
19419 WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019420
19421 return (ret);
19422}
19423
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019424/**
19425 * xmlSchemaCheckElemPropsCorrect:
19426 * @ctxt: a schema parser context
19427 * @decl: the element declaration
19428 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019429 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019430 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019431 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019432 *
19433 * STATUS:
19434 * missing: (6)
19435 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019436static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019437xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19438 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019439{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019440 int ret = 0;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019441 xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019442 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019443 * SPEC (1) "The values of the properties of an element declaration
19444 * must be as described in the property tableau in The Element
19445 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
19446 * Sub-components (§5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019447 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019448 if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19449 xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019450
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019451 xmlSchemaCheckElementDeclComponent(head, pctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019452 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019453 * SPEC (3) "If there is a non-·absent· {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019454 * affiliation}, then {scope} must be global."
19455 */
19456 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19457 xmlSchemaPCustomErr(pctxt,
19458 XML_SCHEMAP_E_PROPS_CORRECT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019459 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019460 "Only global element declarations can have a "
19461 "substitution group affiliation", NULL);
19462 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019463 }
19464 /*
19465 * TODO: SPEC (6) "Circular substitution groups are disallowed.
19466 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019467 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019468 * property."
19469 */
19470 if (head == elemDecl)
19471 circ = head;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019472 else if (WXS_SUBST_HEAD(head) != NULL)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019473 circ = xmlSchemaCheckSubstGroupCircular(head, head);
19474 else
19475 circ = NULL;
19476 if (circ != NULL) {
19477 xmlChar *strA = NULL, *strB = NULL;
19478
19479 xmlSchemaPCustomErrExt(pctxt,
19480 XML_SCHEMAP_E_PROPS_CORRECT_6,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019481 WXS_BASIC_CAST circ, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019482 "The element declaration '%s' defines a circular "
19483 "substitution group to element declaration '%s'",
19484 xmlSchemaGetComponentQName(&strA, circ),
19485 xmlSchemaGetComponentQName(&strB, head),
19486 NULL);
19487 FREE_AND_NULL(strA)
19488 FREE_AND_NULL(strB)
19489 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19490 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019491 /*
19492 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019493 * the {type definition}
19494 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019495 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019496 * of the {substitution group exclusions} of the {substitution group
19497 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
19498 * (if the {type definition} is complex) or as defined in
19499 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019500 * simple)."
19501 *
19502 * NOTE: {substitution group exclusions} means the values of the
19503 * attribute "final".
19504 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019505
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019506 if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019507 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019508
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019509 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19510 set |= SUBSET_EXTENSION;
19511 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19512 set |= SUBSET_RESTRICTION;
19513
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000019514 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019515 WXS_ELEM_TYPEDEF(head), set) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019516 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19517
19518 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019519 xmlSchemaPCustomErrExt(pctxt,
19520 XML_SCHEMAP_E_PROPS_CORRECT_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019521 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019522 "The type definition '%s' was "
19523 "either rejected by the substitution group "
19524 "affiliation '%s', or not validly derived from its type "
19525 "definition '%s'",
19526 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019527 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019528 xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019529 FREE_AND_NULL(strA)
19530 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019531 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019532 }
19533 }
19534 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019535 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019536 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019537 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019538 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019539 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019540 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019541 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019542 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019543 ((WXS_IS_SIMPLE(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019544 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019545 (WXS_IS_COMPLEX(typeDef) &&
19546 WXS_HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019547 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19548 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019549
19550 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19551 xmlSchemaPCustomErr(pctxt,
19552 XML_SCHEMAP_E_PROPS_CORRECT_5,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019553 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019554 "The type definition (or type definition's content type) is or "
19555 "is derived from ID; value constraints are not allowed in "
19556 "conjunction with such a type definition", NULL);
19557 } else if (elemDecl->value != NULL) {
19558 int vcret;
19559 xmlNodePtr node = NULL;
19560
19561 /*
19562 * SPEC (2) "If there is a {value constraint}, the canonical lexical
19563 * representation of its value must be ·valid· with respect to the
19564 * {type definition} as defined in Element Default Valid (Immediate)
19565 * (§3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019566 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019567 if (typeDef == NULL) {
19568 xmlSchemaPErr(pctxt, elemDecl->node,
19569 XML_SCHEMAP_INTERNAL,
19570 "Internal error: xmlSchemaCheckElemPropsCorrect, "
19571 "type is missing... skipping validation of "
19572 "the value constraint", NULL, NULL);
19573 return (-1);
19574 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019575 if (elemDecl->node != NULL) {
19576 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19577 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19578 BAD_CAST "fixed");
19579 else
19580 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19581 BAD_CAST "default");
19582 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019583 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19584 typeDef, elemDecl->value, &(elemDecl->defVal));
19585 if (vcret != 0) {
19586 if (vcret < 0) {
19587 PERROR_INT("xmlSchemaElemCheckValConstr",
19588 "failed to validate the value constraint of an "
19589 "element declaration");
19590 return (-1);
19591 }
19592 return (vcret);
19593 }
19594 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019595
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019596 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019597}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019598
19599/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019600 * xmlSchemaCheckElemSubstGroup:
19601 * @ctxt: a schema parser context
19602 * @decl: the element declaration
19603 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019604 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019605 * Schema Component Constraint:
19606 * Substitution Group (cos-equiv-class)
19607 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019608 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019609 * a list will be built for each subst. group head, holding all direct
19610 * referents to this head.
19611 * NOTE that this function needs:
19612 * 1. circular subst. groups to be checked beforehand
19613 * 2. the declaration's type to be derived from the head's type
19614 *
19615 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019616 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019617 */
19618static void
19619xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19620 xmlSchemaElementPtr elemDecl)
19621{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019622 if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019623 /* SPEC (1) "Its {abstract} is false." */
19624 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19625 return;
19626 {
19627 xmlSchemaElementPtr head;
19628 xmlSchemaTypePtr headType, type;
19629 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019630 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019631 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19632 * {disallowed substitutions} as the blocking constraint, as defined in
19633 * Substitution Group OK (Transitive) (§3.3.6)."
19634 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019635 for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19636 head = WXS_SUBST_HEAD(head)) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019637 set = 0;
19638 methSet = 0;
19639 /*
19640 * The blocking constraints.
19641 */
19642 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19643 continue;
19644 headType = head->subtypes;
19645 type = elemDecl->subtypes;
19646 if (headType == type)
19647 goto add_member;
19648 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19649 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19650 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19651 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19652 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019653 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019654 * "The set of all {derivation method}s involved in the
19655 * derivation of D's {type definition} from C's {type definition}
19656 * does not intersect with the union of the blocking constraint,
19657 * C's {prohibited substitutions} (if C is complex, otherwise the
19658 * empty set) and the {prohibited substitutions} (respectively the
19659 * empty set) of any intermediate {type definition}s in the
19660 * derivation of D's {type definition} from C's {type definition}."
19661 */
19662 /*
19663 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19664 * subst.head axis, the methSet does not need to be computed for
19665 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019666 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019667 /*
19668 * The set of all {derivation method}s involved in the derivation
19669 */
19670 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019671 if ((WXS_IS_EXTENSION(type)) &&
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019672 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19673 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019674
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019675 if (WXS_IS_RESTRICTION(type) &&
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019676 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19677 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19678
19679 type = type->baseType;
19680 }
19681 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019682 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019683 * the head's type.
19684 */
19685 type = elemDecl->subtypes->baseType;
19686 while (type != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019687 if (WXS_IS_COMPLEX(type)) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019688 if ((type->flags &
19689 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19690 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19691 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19692 if ((type->flags &
19693 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19694 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19695 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19696 } else
19697 break;
19698 if (type == headType)
19699 break;
19700 type = type->baseType;
19701 }
19702 if ((set != 0) &&
19703 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19704 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19705 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19706 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19707 continue;
19708 }
19709add_member:
19710 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19711 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19712 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19713 }
19714 }
19715}
19716
19717/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019718 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019719 * @item: an schema element declaration/particle
19720 * @ctxt: a schema parser context
19721 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019722 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019723 * Validates the value constraints of an element declaration.
19724 *
19725 * Fixes finish doing the computations on the element declarations.
19726 */
19727static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019728xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019729 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019730{
19731 if (elemDecl == NULL)
19732 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019733 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19734 return;
19735 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019736 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
19737 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019738}
19739
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019740/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019741 * xmlSchemaResolveModelGroupParticleReferences:
19742 * @particle: a particle component
19743 * @ctxt: a parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019744 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019745 * Resolves references of a model group's {particles} to
19746 * model group definitions and to element declarations.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019747 */
19748static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019749xmlSchemaResolveModelGroupParticleReferences(
19750 xmlSchemaParserCtxtPtr ctxt,
19751 xmlSchemaModelGroupPtr mg)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019752{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019753 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19754 xmlSchemaQNameRefPtr ref;
19755 xmlSchemaBasicItemPtr refItem;
19756
19757 /*
19758 * URGENT TODO: Test this.
19759 */
19760 while (particle != NULL) {
19761 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19762 ((WXS_PARTICLE_TERM(particle))->type !=
19763 XML_SCHEMA_EXTRA_QNAMEREF))
19764 {
19765 goto next_particle;
19766 }
19767 ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019768 /*
19769 * Resolve the reference.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019770 * NULL the {term} by default.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019771 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019772 particle->children = NULL;
19773
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019774 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
19775 ref->itemType, ref->name, ref->targetNamespace);
19776 if (refItem == NULL) {
19777 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019778 NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019779 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019780 /* TODO: remove the particle. */
19781 goto next_particle;
19782 }
19783 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
19784 if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
19785 /* TODO: remove the particle. */
19786 goto next_particle;
19787 /*
19788 * NOTE that we will assign the model group definition
19789 * itself to the "term" of the particle. This will ease
19790 * the check for circular model group definitions. After
19791 * that the "term" will be assigned the model group of the
19792 * model group definition.
19793 */
19794 if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
19795 XML_SCHEMA_TYPE_ALL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019796 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019797 * SPEC cos-all-limited (1)
19798 * SPEC cos-all-limited (1.2)
19799 * "It appears only as the value of one or both of the
19800 * following properties:"
19801 * (1.1) "the {model group} property of a model group
19802 * definition."
19803 * (1.2) "the {term} property of a particle [... of] the "
19804 * {content type} of a complex type definition."
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019805 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019806 xmlSchemaCustomErr(ACTXT_CAST ctxt,
19807 /* TODO: error code */
19808 XML_SCHEMAP_COS_ALL_LIMITED,
19809 WXS_ITEM_NODE(particle), NULL,
19810 "A model group definition is referenced, but "
19811 "it contains an 'all' model group, which "
19812 "cannot be contained by model groups",
19813 NULL, NULL);
19814 /* TODO: remove the particle. */
19815 goto next_particle;
19816 }
19817 particle->children = (xmlSchemaTreeItemPtr) refItem;
19818 } else {
19819 /*
19820 * TODO: Are referenced element declarations the only
19821 * other components we expect here?
19822 */
19823 particle->children = (xmlSchemaTreeItemPtr) refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019824 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019825next_particle:
19826 particle = WXS_PTC_CAST particle->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019827 }
19828}
19829
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019830static int
19831xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
19832 xmlSchemaValPtr y)
19833{
19834 xmlSchemaTypePtr tx, ty, ptx, pty;
19835 int ret;
19836
19837 while (x != NULL) {
19838 /* Same types. */
19839 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
19840 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
19841 ptx = xmlSchemaGetPrimitiveType(tx);
19842 pty = xmlSchemaGetPrimitiveType(ty);
19843 /*
19844 * (1) if a datatype T' is ·derived· by ·restriction· from an
19845 * atomic datatype T then the ·value space· of T' is a subset of
19846 * the ·value space· of T. */
19847 /*
19848 * (2) if datatypes T' and T'' are ·derived· by ·restriction·
19849 * from a common atomic ancestor T then the ·value space·s of T'
19850 * and T'' may overlap.
19851 */
19852 if (ptx != pty)
19853 return(0);
19854 /*
19855 * We assume computed values to be normalized, so do a fast
19856 * string comparison for string based types.
19857 */
19858 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019859 WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019860 if (! xmlStrEqual(
19861 xmlSchemaValueGetAsString(x),
19862 xmlSchemaValueGetAsString(y)))
19863 return (0);
19864 } else {
19865 ret = xmlSchemaCompareValuesWhtsp(
19866 x, XML_SCHEMA_WHITESPACE_PRESERVE,
19867 y, XML_SCHEMA_WHITESPACE_PRESERVE);
19868 if (ret == -2)
19869 return(-1);
19870 if (ret != 0)
19871 return(0);
19872 }
19873 /*
19874 * Lists.
19875 */
19876 x = xmlSchemaValueGetNext(x);
19877 if (x != NULL) {
19878 y = xmlSchemaValueGetNext(y);
19879 if (y == NULL)
19880 return (0);
19881 } else if (xmlSchemaValueGetNext(y) != NULL)
19882 return (0);
19883 else
19884 return (1);
19885 }
19886 return (0);
19887}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019888
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019889/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019890 * xmlSchemaResolveAttrUseReferences:
19891 * @item: an attribute use
19892 * @ctxt: a parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019893 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019894 * Resolves the referenced attribute declaration.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019895 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019896static int
19897xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
19898 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000019899{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019900 if ((ctxt == NULL) || (ause == NULL))
19901 return(-1);
19902 if ((ause->attrDecl == NULL) ||
19903 (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
19904 return(0);
19905
19906 {
19907 xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
19908
19909 /*
19910 * TODO: Evaluate, what errors could occur if the declaration is not
19911 * found.
19912 */
19913 ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
19914 ref->name, ref->targetNamespace);
19915 if (ause->attrDecl == NULL) {
19916 xmlSchemaPResCompAttrErr(ctxt,
19917 XML_SCHEMAP_SRC_RESOLVE,
19918 WXS_BASIC_CAST ause, ause->node,
19919 "ref", ref->name, ref->targetNamespace,
19920 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
19921 return(ctxt->err);;
19922 }
19923 }
19924 return(0);
19925}
19926
19927/**
19928 * xmlSchemaCheckAttrUsePropsCorrect:
19929 * @ctxt: a parser context
19930 * @use: an attribute use
19931 *
19932 * Schema Component Constraint:
19933 * Attribute Use Correct (au-props-correct)
19934 *
19935 */
19936static int
19937xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
19938 xmlSchemaAttributeUsePtr use)
19939{
19940 if ((ctxt == NULL) || (use == NULL))
19941 return(-1);
19942 if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
19943 ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
19944 return(0);
19945
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019946 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019947 * SPEC au-props-correct (1)
19948 * "The values of the properties of an attribute use must be as
19949 * described in the property tableau in The Attribute Use Schema
19950 * Component (§3.5.1), modulo the impact of Missing
19951 * Sub-components (§5.3)."
Daniel Veillardc0826a72004-08-10 14:17:33 +000019952 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019953
19954 if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
19955 ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
19956 ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
19957 {
19958 xmlSchemaPCustomErr(ctxt,
19959 XML_SCHEMAP_AU_PROPS_CORRECT_2,
19960 WXS_BASIC_CAST use, NULL,
19961 "The attribute declaration has a 'fixed' value constraint "
19962 ", thus the attribute use must also have a 'fixed' value "
19963 "constraint",
19964 NULL);
19965 return(ctxt->err);
19966 }
19967 /*
19968 * Compute and check the value constraint's value.
19969 */
19970 if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
19971 int ret;
19972 /*
19973 * TODO: The spec seems to be missing a check of the
19974 * value constraint of the attribute use. We will do it here.
19975 */
19976 /*
19977 * SPEC a-props-correct (3)
19978 */
19979 if (xmlSchemaIsDerivedFromBuiltInType(
19980 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19981 {
19982 xmlSchemaCustomErr(ACTXT_CAST ctxt,
19983 XML_SCHEMAP_AU_PROPS_CORRECT,
19984 NULL, WXS_BASIC_CAST use,
19985 "Value constraints are not allowed if the type definition "
19986 "is or is derived from xs:ID",
19987 NULL, NULL);
19988 return(ctxt->err);
19989 }
19990
19991 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
19992 use->node, WXS_ATTRUSE_TYPEDEF(use),
19993 use->defValue, &(use->defVal),
19994 1, 1, 0);
19995 if (ret != 0) {
19996 if (ret < 0) {
19997 PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
19998 "calling xmlSchemaVCheckCVCSimpleType()");
19999 return(-1);
20000 }
20001 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20002 XML_SCHEMAP_AU_PROPS_CORRECT,
20003 NULL, WXS_BASIC_CAST use,
20004 "The value of the value constraint is not valid",
20005 NULL, NULL);
20006 return(ctxt->err);
20007 }
20008 }
20009 /*
20010 * SPEC au-props-correct (2)
20011 * "If the {attribute declaration} has a fixed
20012 * {value constraint}, then if the attribute use itself has a
20013 * {value constraint}, it must also be fixed and its value must match
20014 * that of the {attribute declaration}'s {value constraint}."
20015 */
20016 if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20017 (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20018 {
20019 if (! xmlSchemaAreValuesEqual(use->defVal,
20020 (WXS_ATTRUSE_DECL(use))->defVal))
20021 {
20022 xmlSchemaPCustomErr(ctxt,
20023 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20024 WXS_BASIC_CAST use, NULL,
20025 "The 'fixed' value constraint of the attribute use "
20026 "must match the attribute declaration's value "
20027 "constraint '%s'",
20028 (WXS_ATTRUSE_DECL(use))->defValue);
20029 }
20030 return(ctxt->err);
20031 }
20032 return(0);
20033}
20034
20035
20036
20037
20038/**
20039 * xmlSchemaResolveAttrTypeReferences:
20040 * @item: an attribute declaration
20041 * @ctxt: a parser context
20042 *
20043 * Resolves the referenced type definition component.
20044 */
20045static int
20046xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20047 xmlSchemaParserCtxtPtr ctxt)
20048{
Daniel Veillard01fa6152004-06-29 17:04:39 +000020049 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020050 * The simple type definition corresponding to the <simpleType> element
20051 * information item in the [children], if present, otherwise the simple
20052 * type definition ·resolved· to by the ·actual value· of the type
Daniel Veillard01fa6152004-06-29 17:04:39 +000020053 * [attribute], if present, otherwise the ·simple ur-type definition·.
20054 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020055 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020056 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020057 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20058 if (item->subtypes != NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020059 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020060 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020061 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000020062
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020063 type = xmlSchemaGetType(ctxt->schema, item->typeName,
20064 item->typeNs);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020065 if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000020066 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000020067 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020068 WXS_BASIC_CAST item, item->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020069 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020070 XML_SCHEMA_TYPE_SIMPLE, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020071 return(ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020072 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020073 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020074
Daniel Veillard3646d642004-06-02 19:19:14 +000020075 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020076 /*
20077 * The type defaults to the xs:anySimpleType.
20078 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020079 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20080 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020081 return(0);
Daniel Veillard4255d502002-04-16 15:50:10 +000020082}
20083
20084/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020085 * xmlSchemaResolveIDCKeyReferences:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020086 * @idc: the identity-constraint definition
20087 * @ctxt: the schema parser context
20088 * @name: the attribute name
20089 *
20090 * Resolve keyRef references to key/unique IDCs.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020091 * Schema Component Constraint:
20092 * Identity-constraint Definition Properties Correct (c-props-correct)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020093 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020094static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020095xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020096 xmlSchemaParserCtxtPtr pctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020097{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020098 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020099 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020100 if (idc->ref->name != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020101 idc->ref->item = (xmlSchemaBasicItemPtr)
20102 xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20103 idc->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020104 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020105 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020106 * TODO: It is actually not an error to fail to resolve
20107 * at this stage. BUT we need to be that strict!
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020108 */
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020109 xmlSchemaPResCompAttrErr(pctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020110 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020111 WXS_BASIC_CAST idc, idc->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020112 "refer", idc->ref->name,
20113 idc->ref->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020114 XML_SCHEMA_TYPE_IDC_KEY, NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020115 return(pctxt->err);
20116 } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20117 /*
20118 * SPEC c-props-correct (1)
20119 */
20120 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20121 XML_SCHEMAP_C_PROPS_CORRECT,
20122 NULL, WXS_BASIC_CAST idc,
20123 "The keyref references a keyref",
20124 NULL, NULL);
20125 idc->ref->item = NULL;
20126 return(pctxt->err);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020127 } else {
20128 if (idc->nbFields !=
20129 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20130 xmlChar *str = NULL;
20131 xmlSchemaIDCPtr refer;
20132
20133 refer = (xmlSchemaIDCPtr) idc->ref->item;
20134 /*
20135 * SPEC c-props-correct(2)
20136 * "If the {identity-constraint category} is keyref,
20137 * the cardinality of the {fields} must equal that of
20138 * the {fields} of the {referenced key}.
20139 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020140 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020141 XML_SCHEMAP_C_PROPS_CORRECT,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020142 NULL, WXS_BASIC_CAST idc,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020143 "The cardinality of the keyref differs from the "
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020144 "cardinality of the referenced key/unique '%s'",
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020145 xmlSchemaFormatQName(&str, refer->targetNamespace,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020146 refer->name),
20147 NULL);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020148 FREE_AND_NULL(str)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020149 return(pctxt->err);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020150 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020151 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020152 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020153 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020154}
20155
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020156static int
20157xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20158 xmlSchemaParserCtxtPtr pctxt)
20159{
20160 if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20161 prohib->targetNamespace) == NULL) {
20162
20163 xmlSchemaPResCompAttrErr(pctxt,
20164 XML_SCHEMAP_SRC_RESOLVE,
20165 NULL, prohib->node,
20166 "ref", prohib->name, prohib->targetNamespace,
20167 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20168 return(XML_SCHEMAP_SRC_RESOLVE);
20169 }
20170 return(0);
20171}
20172
20173#define WXS_REDEFINED_TYPE(c) \
20174(((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20175
20176#define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20177(((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20178
20179#define WXS_REDEFINED_ATTR_GROUP(c) \
20180(((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20181
20182static int
20183xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20184{
20185 int err = 0;
20186 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20187 xmlSchemaBasicItemPtr prev, item;
20188 int wasRedefined;
20189
20190 if (redef == NULL)
20191 return(0);
20192
20193 do {
20194 item = redef->item;
20195 /*
20196 * First try to locate the redefined component in the
20197 * schema graph starting with the redefined schema.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020198 * NOTE: According to this schema bug entry:
20199 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20200 * it's not clear if the referenced component needs to originate
20201 * from the <redefine>d schema _document_ or the schema; the latter
20202 * would include all imported and included sub-schemas of the
20203 * <redefine>d schema. Currenlty we latter approach is used.
20204 * SUPPLEMENT: It seems that the WG moves towards the latter
20205 * approach, so we are doing it right.
20206 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020207 */
20208 prev = xmlSchemaFindRedefCompInGraph(
20209 redef->targetBucket, item->type,
20210 redef->refName, redef->refTargetNs);
20211 if (prev == NULL) {
20212 xmlChar *str = NULL;
20213 xmlNodePtr node;
20214
20215 /*
20216 * SPEC src-redefine:
20217 * (6.2.1) "The ·actual value· of its own name attribute plus
20218 * target namespace must successfully ·resolve· to a model
20219 * group definition in I."
20220 * (7.2.1) "The ·actual value· of its own name attribute plus
20221 * target namespace must successfully ·resolve· to an attribute
20222 * group definition in I."
20223
20224 *
20225 * Note that, if we are redefining with the use of references
20226 * to components, the spec assumes the src-resolve to be used;
20227 * but this won't assure that we search only *inside* the
20228 * redefined schema.
20229 */
20230 if (redef->reference)
20231 node = WXS_ITEM_NODE(redef->reference);
20232 else
20233 node = WXS_ITEM_NODE(item);
20234 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20235 /*
20236 * TODO: error code.
20237 * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20238 * reference kind.
20239 */
20240 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
Kasimier T. Buchcik5d2998b2005-11-22 17:36:01 +000020241 "The %s '%s' to be redefined could not be found in "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020242 "the redefined schema",
20243 WXS_ITEM_TYPE_NAME(item),
20244 xmlSchemaFormatQName(&str, redef->refTargetNs,
20245 redef->refName));
20246 FREE_AND_NULL(str);
20247 err = pctxt->err;
20248 redef = redef->next;
20249 continue;
20250 }
20251 /*
20252 * TODO: Obtaining and setting the redefinition state is really
20253 * clumsy.
20254 */
20255 wasRedefined = 0;
20256 switch (item->type) {
20257 case XML_SCHEMA_TYPE_COMPLEX:
20258 case XML_SCHEMA_TYPE_SIMPLE:
20259 if ((WXS_TYPE_CAST prev)->flags &
20260 XML_SCHEMAS_TYPE_REDEFINED)
20261 {
20262 wasRedefined = 1;
20263 break;
20264 }
20265 /* Mark it as redefined. */
20266 (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20267 /*
20268 * Assign the redefined type to the
20269 * base type of the redefining type.
20270 * TODO: How
20271 */
20272 ((xmlSchemaTypePtr) item)->baseType =
20273 (xmlSchemaTypePtr) prev;
20274 break;
20275 case XML_SCHEMA_TYPE_GROUP:
20276 if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20277 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20278 {
20279 wasRedefined = 1;
20280 break;
20281 }
20282 /* Mark it as redefined. */
20283 (WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20284 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20285 if (redef->reference != NULL) {
20286 /*
20287 * Overwrite the QName-reference with the
20288 * referenced model group def.
20289 */
20290 (WXS_PTC_CAST redef->reference)->children =
20291 WXS_TREE_CAST prev;
20292 }
20293 redef->target = prev;
20294 break;
20295 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20296 if ((WXS_ATTR_GROUP_CAST prev)->flags &
20297 XML_SCHEMAS_ATTRGROUP_REDEFINED)
20298 {
20299 wasRedefined = 1;
20300 break;
20301 }
20302 (WXS_ATTR_GROUP_CAST prev)->flags |=
20303 XML_SCHEMAS_ATTRGROUP_REDEFINED;
20304 if (redef->reference != NULL) {
20305 /*
20306 * Assign the redefined attribute group to the
20307 * QName-reference component.
20308 * This is the easy case, since we will just
20309 * expand the redefined group.
20310 */
20311 (WXS_QNAME_CAST redef->reference)->item = prev;
20312 redef->target = NULL;
20313 } else {
20314 /*
20315 * This is the complicated case: we need
20316 * to apply src-redefine (7.2.2) at a later
20317 * stage, i.e. when attribute group references
20318 * have beed expanded and simple types have
20319 * beed fixed.
20320 */
20321 redef->target = prev;
20322 }
20323 break;
20324 default:
20325 PERROR_INT("xmlSchemaResolveRedefReferences",
20326 "Unexpected redefined component type");
20327 return(-1);
20328 }
20329 if (wasRedefined) {
20330 xmlChar *str = NULL;
20331 xmlNodePtr node;
20332
20333 if (redef->reference)
20334 node = WXS_ITEM_NODE(redef->reference);
20335 else
20336 node = WXS_ITEM_NODE(redef->item);
20337
20338 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20339 /* TODO: error code. */
20340 XML_SCHEMAP_SRC_REDEFINE,
20341 node, NULL,
20342 "The referenced %s was already redefined. Multiple "
20343 "redefinition of the same component is not supported",
20344 xmlSchemaGetComponentDesignation(&str, prev),
20345 NULL);
20346 FREE_AND_NULL(str)
20347 err = pctxt->err;
20348 redef = redef->next;
20349 continue;
20350 }
20351 redef = redef->next;
20352 } while (redef != NULL);
20353
20354 return(err);
20355}
20356
20357static int
20358xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20359{
20360 int err = 0;
20361 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20362 xmlSchemaBasicItemPtr item;
20363
20364 if (redef == NULL)
20365 return(0);
20366
20367 do {
20368 if (redef->target == NULL) {
20369 redef = redef->next;
20370 continue;
20371 }
20372 item = redef->item;
20373
20374 switch (item->type) {
20375 case XML_SCHEMA_TYPE_SIMPLE:
20376 case XML_SCHEMA_TYPE_COMPLEX:
20377 /*
20378 * Since the spec wants the {name} of the redefined
20379 * type to be 'absent', we'll NULL it.
20380 */
20381 (WXS_TYPE_CAST redef->target)->name = NULL;
20382
20383 /*
20384 * TODO: Seems like there's nothing more to do. The normal
20385 * inheritance mechanism is used. But not 100% sure.
20386 */
20387 break;
20388 case XML_SCHEMA_TYPE_GROUP:
20389 /*
20390 * URGENT TODO:
20391 * SPEC src-redefine:
20392 * (6.2.2) "The {model group} of the model group definition
20393 * which corresponds to it per XML Representation of Model
20394 * Group Definition Schema Components (§3.7.2) must be a
20395 * ·valid restriction· of the {model group} of that model
20396 * group definition in I, as defined in Particle Valid
20397 * (Restriction) (§3.9.6)."
20398 */
20399 break;
20400 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20401 /*
20402 * SPEC src-redefine:
20403 * (7.2.2) "The {attribute uses} and {attribute wildcard} of
20404 * the attribute group definition which corresponds to it
20405 * per XML Representation of Attribute Group Definition Schema
20406 * Components (§3.6.2) must be ·valid restrictions· of the
20407 * {attribute uses} and {attribute wildcard} of that attribute
20408 * group definition in I, as defined in clause 2, clause 3 and
20409 * clause 4 of Derivation Valid (Restriction, Complex)
20410 * (§3.4.6) (where references to the base type definition are
20411 * understood as references to the attribute group definition
20412 * in I)."
20413 */
20414 err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20415 XML_SCHEMA_ACTION_REDEFINE,
20416 item, redef->target,
20417 (WXS_ATTR_GROUP_CAST item)->attrUses,
20418 (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20419 (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20420 (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20421 if (err == -1)
20422 return(-1);
20423 break;
20424 default:
20425 break;
20426 }
20427 redef = redef->next;
20428 } while (redef != NULL);
20429 return(0);
20430}
20431
20432
20433static int
20434xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20435 xmlSchemaBucketPtr bucket)
20436{
20437 xmlSchemaBasicItemPtr item;
20438 int err;
20439 xmlHashTablePtr *table;
20440 const xmlChar *name;
20441 int i;
20442
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020443#define WXS_GET_GLOBAL_HASH(c, slot) { \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020444 if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20445 table = &(WXS_IMPBUCKET((c))->schema->slot); \
20446 else \
20447 table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20448
20449 /*
20450 * Add global components to the schema's hash tables.
20451 * This is the place where duplicate components will be
20452 * detected.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020453 * TODO: I think normally we should support imports of the
20454 * same namespace from multiple locations. We don't do currently,
20455 * but if we do then according to:
20456 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20457 * we would need, if imported directly, to import redefined
20458 * components as well to be able to catch clashing components.
20459 * (I hope I'll still know what this means after some months :-()
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020460 */
20461 if (bucket == NULL)
20462 return(-1);
20463 if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20464 return(0);
20465 bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20466
20467 for (i = 0; i < bucket->globals->nbItems; i++) {
20468 item = bucket->globals->items[i];
20469 table = NULL;
20470 switch (item->type) {
20471 case XML_SCHEMA_TYPE_COMPLEX:
20472 case XML_SCHEMA_TYPE_SIMPLE:
20473 if (WXS_REDEFINED_TYPE(item))
20474 continue;
20475 name = (WXS_TYPE_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020476 WXS_GET_GLOBAL_HASH(bucket, typeDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020477 break;
20478 case XML_SCHEMA_TYPE_ELEMENT:
20479 name = (WXS_ELEM_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020480 WXS_GET_GLOBAL_HASH(bucket, elemDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020481 break;
20482 case XML_SCHEMA_TYPE_ATTRIBUTE:
20483 name = (WXS_ATTR_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020484 WXS_GET_GLOBAL_HASH(bucket, attrDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020485 break;
20486 case XML_SCHEMA_TYPE_GROUP:
20487 if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20488 continue;
20489 name = (WXS_MODEL_GROUPDEF_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020490 WXS_GET_GLOBAL_HASH(bucket, groupDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020491 break;
20492 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20493 if (WXS_REDEFINED_ATTR_GROUP(item))
20494 continue;
20495 name = (WXS_ATTR_GROUP_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020496 WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020497 break;
20498 case XML_SCHEMA_TYPE_IDC_KEY:
20499 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20500 case XML_SCHEMA_TYPE_IDC_KEYREF:
20501 name = (WXS_IDC_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020502 WXS_GET_GLOBAL_HASH(bucket, idcDef)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020503 break;
20504 case XML_SCHEMA_TYPE_NOTATION:
20505 name = ((xmlSchemaNotationPtr) item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020506 WXS_GET_GLOBAL_HASH(bucket, notaDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020507 break;
20508 default:
20509 PERROR_INT("xmlSchemaAddComponents",
20510 "Unexpected global component type");
20511 continue;
20512 }
20513 if (*table == NULL) {
20514 *table = xmlHashCreateDict(10, pctxt->dict);
20515 if (*table == NULL) {
20516 PERROR_INT("xmlSchemaAddComponents",
20517 "failed to create a component hash table");
20518 return(-1);
20519 }
20520 }
20521 err = xmlHashAddEntry(*table, name, item);
20522 if (err != 0) {
20523 xmlChar *str = NULL;
20524
20525 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20526 XML_SCHEMAP_REDEFINED_TYPE,
20527 WXS_ITEM_NODE(item),
20528 WXS_BASIC_CAST item,
20529 "A global %s '%s' does already exist",
20530 WXS_ITEM_TYPE_NAME(item),
20531 xmlSchemaGetComponentQName(&str, item));
20532 FREE_AND_NULL(str);
20533 }
20534 }
20535 /*
20536 * Process imported/included schemas.
20537 */
20538 if (bucket->relations != NULL) {
20539 xmlSchemaSchemaRelationPtr rel = bucket->relations;
20540 do {
20541 if ((rel->bucket != NULL) &&
20542 ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20543 if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20544 return(-1);
20545 }
20546 rel = rel->next;
20547 } while (rel != NULL);
20548 }
20549 return(0);
20550}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020551
20552static int
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020553xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20554 xmlSchemaBucketPtr rootBucket)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020555{
20556 xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20557 xmlSchemaTreeItemPtr item, *items;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020558 int nbItems, i, ret = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020559
20560#define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20561
20562 if ((con->pending == NULL) ||
20563 (con->pending->nbItems == 0))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020564 return(0);
20565
20566 /* TODO:
20567 * SPEC (src-redefine):
20568 * (6.2) "If it has no such self-reference, then all of the
20569 * following must be true:"
20570
20571 * (6.2.2) The {model group} of the model group definition which
20572 * corresponds to it per XML Representation of Model Group
20573 * Definition Schema Components (§3.7.2) must be a ·valid
20574 * restriction· of the {model group} of that model group definition
20575 * in I, as defined in Particle Valid (Restriction) (§3.9.6)."
20576 */
20577 xmlSchemaCheckSRCRedefineFirst(pctxt);
20578
20579 /*
20580 * Add global components to the schemata's hash tables.
20581 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020582 xmlSchemaAddComponents(pctxt, rootBucket);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020583
20584 pctxt->ctxtType = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020585 items = (xmlSchemaTreeItemPtr *) con->pending->items;
20586 nbItems = con->pending->nbItems;
20587 /*
20588 * Now that we have parsed *all* the schema document(s) and converted
20589 * them to schema components, we can resolve references, apply component
20590 * constraints, create the FSA from the content model, etc.
20591 */
20592 /*
20593 * Resolve references of..
20594 *
20595 * 1. element declarations:
20596 * - the type definition
20597 * - the substitution group affiliation
20598 * 2. simple/complex types:
20599 * - the base type definition
20600 * - the memberTypes of union types
20601 * - the itemType of list types
20602 * 3. attributes declarations and attribute uses:
20603 * - the type definition
20604 * - if an attribute use, then the attribute declaration
20605 * 4. attribute group references:
20606 * - the attribute group definition
20607 * 5. particles:
20608 * - the term of the particle (e.g. a model group)
20609 * 6. IDC key-references:
20610 * - the referenced IDC 'key' or 'unique' definition
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020611 * 7. Attribute prohibitions which had a "ref" attribute.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020612 */
20613 for (i = 0; i < nbItems; i++) {
20614 item = items[i];
20615 switch (item->type) {
20616 case XML_SCHEMA_TYPE_ELEMENT:
20617 xmlSchemaResolveElementReferences(
20618 (xmlSchemaElementPtr) item, pctxt);
20619 FIXHFAILURE;
20620 break;
20621 case XML_SCHEMA_TYPE_COMPLEX:
20622 case XML_SCHEMA_TYPE_SIMPLE:
20623 xmlSchemaResolveTypeReferences(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020624 (xmlSchemaTypePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020625 FIXHFAILURE;
20626 break;
20627 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020628 xmlSchemaResolveAttrTypeReferences(
20629 (xmlSchemaAttributePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020630 FIXHFAILURE;
20631 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020632 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20633 xmlSchemaResolveAttrUseReferences(
20634 (xmlSchemaAttributeUsePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020635 FIXHFAILURE;
20636 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020637 case XML_SCHEMA_EXTRA_QNAMEREF:
20638 if ((WXS_QNAME_CAST item)->itemType ==
20639 XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20640 {
20641 xmlSchemaResolveAttrGroupReferences(
20642 WXS_QNAME_CAST item, pctxt);
20643 }
20644 FIXHFAILURE;
20645 break;
20646 case XML_SCHEMA_TYPE_SEQUENCE:
20647 case XML_SCHEMA_TYPE_CHOICE:
20648 case XML_SCHEMA_TYPE_ALL:
20649 xmlSchemaResolveModelGroupParticleReferences(pctxt,
20650 WXS_MODEL_GROUP_CAST item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020651 FIXHFAILURE;
20652 break;
20653 case XML_SCHEMA_TYPE_IDC_KEY:
20654 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20655 case XML_SCHEMA_TYPE_IDC_KEYREF:
20656 xmlSchemaResolveIDCKeyReferences(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020657 (xmlSchemaIDCPtr) item, pctxt);
20658 FIXHFAILURE;
20659 break;
20660 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20661 /*
20662 * Handle attribue prohibition which had a
20663 * "ref" attribute.
20664 */
20665 xmlSchemaResolveAttrUseProhibReferences(
20666 WXS_ATTR_PROHIB_CAST item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020667 FIXHFAILURE;
20668 break;
20669 default:
20670 break;
20671 }
20672 }
20673 if (pctxt->nberrors != 0)
20674 goto exit_error;
20675
20676 /*
20677 * Now that all references are resolved we
20678 * can check for circularity of...
20679 * 1. the base axis of type definitions
20680 * 2. nested model group definitions
20681 * 3. nested attribute group definitions
20682 * TODO: check for circual substitution groups.
20683 */
20684 for (i = 0; i < nbItems; i++) {
20685 item = items[i];
20686 /*
20687 * Let's better stop on the first error here.
20688 */
20689 switch (item->type) {
20690 case XML_SCHEMA_TYPE_COMPLEX:
20691 case XML_SCHEMA_TYPE_SIMPLE:
20692 xmlSchemaCheckTypeDefCircular(
20693 (xmlSchemaTypePtr) item, pctxt);
20694 FIXHFAILURE;
20695 if (pctxt->nberrors != 0)
20696 goto exit_error;
20697 break;
20698 case XML_SCHEMA_TYPE_GROUP:
20699 xmlSchemaCheckGroupDefCircular(
20700 (xmlSchemaModelGroupDefPtr) item, pctxt);
20701 FIXHFAILURE;
20702 if (pctxt->nberrors != 0)
20703 goto exit_error;
20704 break;
20705 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20706 xmlSchemaCheckAttrGroupCircular(
20707 (xmlSchemaAttributeGroupPtr) item, pctxt);
20708 FIXHFAILURE;
20709 if (pctxt->nberrors != 0)
20710 goto exit_error;
20711 break;
20712 default:
20713 break;
20714 }
20715 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020716 if (pctxt->nberrors != 0)
20717 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020718 /*
20719 * Model group definition references:
20720 * Such a reference is reflected by a particle at the component
20721 * level. Until now the 'term' of such particles pointed
20722 * to the model group definition; this was done, in order to
20723 * ease circularity checks. Now we need to set the 'term' of
20724 * such particles to the model group of the model group definition.
20725 */
20726 for (i = 0; i < nbItems; i++) {
20727 item = items[i];
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020728 switch (item->type) {
20729 case XML_SCHEMA_TYPE_SEQUENCE:
20730 case XML_SCHEMA_TYPE_CHOICE:
20731 xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
20732 WXS_MODEL_GROUP_CAST item);
20733 break;
20734 default:
20735 break;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020736 }
20737 }
20738 if (pctxt->nberrors != 0)
20739 goto exit_error;
20740 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020741 * Expand attribute group references of attribute group definitions.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020742 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020743 for (i = 0; i < nbItems; i++) {
20744 item = items[i];
20745 switch (item->type) {
20746 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20747 if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
20748 WXS_ATTR_GROUP_HAS_REFS(item))
20749 {
20750 xmlSchemaAttributeGroupExpandRefs(pctxt,
20751 WXS_ATTR_GROUP_CAST item);
20752 FIXHFAILURE;
20753 }
20754 break;
20755 default:
20756 break;
20757 }
20758 }
20759 if (pctxt->nberrors != 0)
20760 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020761 /*
20762 * First compute the variety of simple types. This is needed as
20763 * a seperate step, since otherwise we won't be able to detect
20764 * circular union types in all cases.
20765 */
20766 for (i = 0; i < nbItems; i++) {
20767 item = items[i];
20768 switch (item->type) {
20769 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020770 if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020771 xmlSchemaFixupSimpleTypeStageOne(pctxt,
20772 (xmlSchemaTypePtr) item);
20773 FIXHFAILURE;
20774 }
20775 break;
20776 default:
20777 break;
20778 }
20779 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020780 if (pctxt->nberrors != 0)
20781 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020782 /*
20783 * Detect circular union types. Note that this needs the variety to
20784 * be already computed.
20785 */
20786 for (i = 0; i < nbItems; i++) {
20787 item = items[i];
20788 switch (item->type) {
20789 case XML_SCHEMA_TYPE_SIMPLE:
20790 if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
20791 xmlSchemaCheckUnionTypeDefCircular(pctxt,
20792 (xmlSchemaTypePtr) item);
20793 FIXHFAILURE;
20794 }
20795 break;
20796 default:
20797 break;
20798 }
20799 }
20800 if (pctxt->nberrors != 0)
20801 goto exit_error;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020802
20803 /*
20804 * Do the complete type fixup for simple types.
20805 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020806 for (i = 0; i < nbItems; i++) {
20807 item = items[i];
20808 switch (item->type) {
20809 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020810 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
20811 xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
20812 FIXHFAILURE;
20813 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020814 break;
20815 default:
20816 break;
20817 }
20818 }
20819 if (pctxt->nberrors != 0)
20820 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020821 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020822 * At this point we need all simple types to be builded and checked.
20823 */
20824 /*
20825 * Apply contraints for attribute declarations.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020826 */
20827 for (i = 0; i < nbItems; i++) {
20828 item = items[i];
20829 switch (item->type) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020830 case XML_SCHEMA_TYPE_ATTRIBUTE:
20831 xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
20832 FIXHFAILURE;
20833 break;
20834 default:
20835 break;
20836 }
20837 }
20838 if (pctxt->nberrors != 0)
20839 goto exit_error;
20840 /*
20841 * Apply constraints for attribute uses.
20842 */
20843 for (i = 0; i < nbItems; i++) {
20844 item = items[i];
20845 switch (item->type) {
20846 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20847 if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
20848 xmlSchemaCheckAttrUsePropsCorrect(pctxt,
20849 WXS_ATTR_USE_CAST item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020850 FIXHFAILURE;
20851 }
20852 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020853 default:
20854 break;
20855 }
20856 }
20857 if (pctxt->nberrors != 0)
20858 goto exit_error;
20859
20860 /*
20861 * Apply constraints for attribute group definitions.
20862 */
20863 for (i = 0; i < nbItems; i++) {
20864 item = items[i];
20865 switch (item->type) {
20866 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20867 if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
20868 ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
20869 {
20870 xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
20871 FIXHFAILURE;
20872 }
20873 break;
20874 default:
20875 break;
20876 }
20877 }
20878 if (pctxt->nberrors != 0)
20879 goto exit_error;
20880
20881 /*
20882 * Apply constraints for redefinitions.
20883 */
20884 if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
20885 xmlSchemaCheckSRCRedefineSecond(pctxt);
20886 if (pctxt->nberrors != 0)
20887 goto exit_error;
20888
20889 /*
20890 * Fixup complex types.
20891 */
20892 for (i = 0; i < nbItems; i++) {
20893 item = con->pending->items[i];
20894 switch (item->type) {
20895 case XML_SCHEMA_TYPE_COMPLEX:
20896 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
20897 xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
20898 FIXHFAILURE;
20899 }
20900 break;
20901 default:
20902 break;
20903 }
20904 }
20905 if (pctxt->nberrors != 0)
20906 goto exit_error;
20907
20908 /*
20909 * The list could have changed, since xmlSchemaFixupComplexType()
20910 * will create particles and model groups in some cases.
20911 */
20912 items = (xmlSchemaTreeItemPtr *) con->pending->items;
20913 nbItems = con->pending->nbItems;
20914
20915 /*
20916 * At this point all complex types need to be builded and checked.
20917 */
20918 /*
20919 * Apply some constraints for element declarations.
20920 */
20921 for (i = 0; i < nbItems; i++) {
20922 item = items[i];
20923 switch (item->type) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020924 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020925
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020926 if ((((xmlSchemaElementPtr) item)->flags &
20927 XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0) {
20928 xmlSchemaCheckElementDeclComponent(
20929 (xmlSchemaElementPtr) item, pctxt);
20930 FIXHFAILURE;
20931 }
20932 break;
20933 default:
20934 break;
20935 }
20936 }
20937 if (pctxt->nberrors != 0)
20938 goto exit_error;
20939 /*
20940 * Finally we can build the automaton from the content model of
20941 * complex types.
20942 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020943
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020944 for (i = 0; i < nbItems; i++) {
20945 item = items[i];
20946 switch (item->type) {
20947 case XML_SCHEMA_TYPE_COMPLEX:
20948 xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020949 /* FIXHFAILURE; */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020950 break;
20951 default:
20952 break;
20953 }
20954 }
20955 if (pctxt->nberrors != 0)
20956 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020957 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020958 * URGENT TODO: cos-element-consistent
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020959 */
20960 goto exit;
20961
20962exit_error:
20963 ret = pctxt->err;
20964
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020965exit_failure:
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020966 ret = -1;
20967
20968exit:
20969 /*
20970 * Reset the constructor. This is needed for XSI acquisition, since
20971 * those items will be processed over and over again for every XSI
20972 * if not cleared here.
20973 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020974 con->pending->nbItems = 0;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020975 if (con->substGroups != NULL) {
20976 xmlHashFree(con->substGroups,
20977 (xmlHashDeallocator) xmlSchemaSubstGroupFree);
20978 con->substGroups = NULL;
20979 }
20980 if (con->redefs != NULL) {
20981 xmlSchemaRedefListFree(con->redefs);
20982 con->redefs = NULL;
20983 }
20984 return(ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020985}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020986/**
Daniel Veillard4255d502002-04-16 15:50:10 +000020987 * xmlSchemaParse:
20988 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000020989 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000020990 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000020991 * XML Shema struture which can be used to validate instances.
Daniel Veillard4255d502002-04-16 15:50:10 +000020992 *
20993 * Returns the internal XML Schema structure built from the resource or
20994 * NULL in case of error
20995 */
20996xmlSchemaPtr
20997xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
20998{
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020999 xmlSchemaPtr mainSchema = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021000 xmlSchemaBucketPtr bucket = NULL;
21001 int res;
Daniel Veillard4255d502002-04-16 15:50:10 +000021002
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021003 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021004 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021005 * the API; i.e. not automatically by the validated instance document.
21006 */
21007
Daniel Veillard4255d502002-04-16 15:50:10 +000021008 xmlSchemaInitTypes();
21009
Daniel Veillard6045c902002-10-09 21:13:59 +000021010 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000021011 return (NULL);
21012
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021013 /* TODO: Init the context. Is this all we need?*/
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000021014 ctxt->nberrors = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021015 ctxt->err = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000021016 ctxt->counter = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000021017
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021018 /* Create the *main* schema. */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021019 mainSchema = xmlSchemaNewSchema(ctxt);
21020 if (mainSchema == NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021021 goto exit_failure;
Daniel Veillard4255d502002-04-16 15:50:10 +000021022 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021023 * Create the schema constructor.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021024 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021025 if (ctxt->constructor == NULL) {
21026 ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21027 if (ctxt->constructor == NULL)
21028 return(NULL);
21029 /* Take ownership of the constructor to be able to free it. */
21030 ctxt->ownsConstructor = 1;
21031 }
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021032 ctxt->constructor->mainSchema = mainSchema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021033 /*
21034 * Locate and add the schema document.
21035 */
21036 res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21037 ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21038 NULL, NULL, &bucket);
21039 if (res == -1)
21040 goto exit_failure;
21041 if (res != 0)
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000021042 goto exit;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021043
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021044 if (bucket == NULL) {
21045 /* TODO: Error code, actually we failed to *locate* the schema. */
21046 if (ctxt->URL)
21047 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21048 NULL, NULL,
21049 "Failed to locate the main schema resource at '%s'",
21050 ctxt->URL, NULL);
21051 else
21052 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21053 NULL, NULL,
21054 "Failed to locate the main schema resource",
21055 NULL, NULL);
21056 goto exit;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021057 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021058 /* Then do the parsing for good. */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021059 if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021060 goto exit_failure;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021061 if (ctxt->nberrors != 0)
21062 goto exit;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021063
21064 mainSchema->doc = bucket->doc;
21065 mainSchema->preserve = ctxt->preserve;
21066
21067 ctxt->schema = mainSchema;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021068
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021069 if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021070 goto exit_failure;
21071
21072 /*
21073 * TODO: This is not nice, since we cannot distinguish from the
21074 * result if there was an internal error or not.
21075 */
21076exit:
21077 if (ctxt->nberrors != 0) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021078 if (mainSchema) {
21079 xmlSchemaFree(mainSchema);
21080 mainSchema = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021081 }
21082 if (ctxt->constructor) {
21083 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21084 ctxt->constructor = NULL;
21085 ctxt->ownsConstructor = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021086 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021087 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021088 ctxt->schema = NULL;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021089 return(mainSchema);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021090exit_failure:
21091 /*
21092 * Quite verbose, but should catch internal errors, which were
21093 * not communitated.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021094 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021095 if (mainSchema) {
21096 xmlSchemaFree(mainSchema);
21097 mainSchema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021098 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021099 if (ctxt->constructor) {
21100 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21101 ctxt->constructor = NULL;
21102 ctxt->ownsConstructor = 0;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000021103 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021104 PERROR_INT2("xmlSchemaParse",
21105 "An internal error occured");
21106 ctxt->schema = NULL;
21107 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000021108}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021109
Daniel Veillard4255d502002-04-16 15:50:10 +000021110/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000021111 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000021112 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000021113 * @err: the error callback
21114 * @warn: the warning callback
21115 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000021116 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000021117 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000021118 */
21119void
21120xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021121 xmlSchemaValidityErrorFunc err,
21122 xmlSchemaValidityWarningFunc warn, void *ctx)
21123{
Daniel Veillard4255d502002-04-16 15:50:10 +000021124 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021125 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000021126 ctxt->error = err;
21127 ctxt->warning = warn;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021128 ctxt->errCtxt = ctx;
21129 if (ctxt->vctxt != NULL)
21130 xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21131}
21132
21133/**
21134 * xmlSchemaSetParserStructuredErrors:
21135 * @ctxt: a schema parser context
21136 * @serror: the structured error function
21137 * @ctx: the functions context
21138 *
21139 * Set the structured error callback
21140 */
21141void
21142xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21143 xmlStructuredErrorFunc serror,
21144 void *ctx)
21145{
21146 if (ctxt == NULL)
21147 return;
21148 ctxt->serror = serror;
21149 ctxt->errCtxt = ctx;
21150 if (ctxt->vctxt != NULL)
21151 xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000021152}
21153
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021154/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000021155 * xmlSchemaGetParserErrors:
21156 * @ctxt: a XMl-Schema parser context
21157 * @err: the error callback result
21158 * @warn: the warning callback result
21159 * @ctx: contextual data for the callbacks result
21160 *
21161 * Get the callback information used to handle errors for a parser context
21162 *
21163 * Returns -1 in case of failure, 0 otherwise
21164 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021165int
Daniel Veillard259f0df2004-08-18 09:13:18 +000021166xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021167 xmlSchemaValidityErrorFunc * err,
21168 xmlSchemaValidityWarningFunc * warn, void **ctx)
Daniel Veillard259f0df2004-08-18 09:13:18 +000021169{
21170 if (ctxt == NULL)
21171 return(-1);
21172 if (err != NULL)
21173 *err = ctxt->error;
21174 if (warn != NULL)
21175 *warn = ctxt->warning;
21176 if (ctx != NULL)
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021177 *ctx = ctxt->errCtxt;
Daniel Veillard259f0df2004-08-18 09:13:18 +000021178 return(0);
21179}
21180
21181/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021182 * xmlSchemaFacetTypeToString:
21183 * @type: the facet type
21184 *
21185 * Convert the xmlSchemaTypeType to a char string.
21186 *
21187 * Returns the char string representation of the facet type if the
21188 * type is a facet and an "Internal Error" string otherwise.
21189 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021190static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021191xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21192{
21193 switch (type) {
21194 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021195 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021196 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021197 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021198 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021199 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021200 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021201 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021202 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021203 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021204 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021205 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021206 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021207 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021208 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021209 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021210 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021211 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021212 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021213 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021214 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021215 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021216 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021217 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021218 default:
21219 break;
21220 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021221 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021222}
21223
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021224static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000021225xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21226{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021227 /*
21228 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000021229 * from xsd:string.
21230 */
21231 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021232 /*
21233 * Note that we assume a whitespace of preserve for anySimpleType.
21234 */
21235 if ((type->builtInType == XML_SCHEMAS_STRING) ||
21236 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21237 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000021238 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021239 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021240 else {
21241 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021242 * For all ·atomic· datatypes other than string (and types ·derived·
21243 * by ·restriction· from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000021244 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021245 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000021246 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021247 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021248 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021249 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021250 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021251 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021252 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021253 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021254 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021255 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021256 } else if (WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021257 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21258 return (XML_SCHEMA_WHITESPACE_PRESERVE);
21259 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21260 return (XML_SCHEMA_WHITESPACE_REPLACE);
21261 else
21262 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021263 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021264 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021265}
21266
Daniel Veillard4255d502002-04-16 15:50:10 +000021267/************************************************************************
21268 * *
21269 * Simple type validation *
21270 * *
21271 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000021272
Daniel Veillard4255d502002-04-16 15:50:10 +000021273
21274/************************************************************************
21275 * *
21276 * DOM Validation code *
21277 * *
21278 ************************************************************************/
21279
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021280/**
21281 * xmlSchemaAssembleByLocation:
21282 * @pctxt: a schema parser context
21283 * @vctxt: a schema validation context
21284 * @schema: the existing schema
21285 * @node: the node that fired the assembling
21286 * @nsName: the namespace name of the new schema
21287 * @location: the location of the schema
21288 *
21289 * Expands an existing schema by an additional schema.
21290 *
21291 * Returns 0 if the new schema is correct, a positive error code
21292 * number otherwise and -1 in case of an internal or API error.
21293 */
21294static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021295xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021296 xmlSchemaPtr schema,
21297 xmlNodePtr node,
21298 const xmlChar *nsName,
21299 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021300{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021301 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021302 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021303 xmlSchemaBucketPtr bucket = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021304
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021305 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021306 return (-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021307
21308 if (vctxt->pctxt == NULL) {
21309 VERROR_INT("xmlSchemaAssembleByLocation",
21310 "no parser context available");
21311 return(-1);
21312 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021313 pctxt = vctxt->pctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021314 if (pctxt->constructor == NULL) {
21315 PERROR_INT("xmlSchemaAssembleByLocation",
21316 "no constructor");
21317 return(-1);
21318 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021319 /*
21320 * Acquire the schema document.
21321 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021322 location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21323 location, node);
21324 /*
21325 * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21326 * the process will automatically change this to
21327 * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21328 */
21329 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21330 location, NULL, NULL, 0, node, NULL, nsName,
21331 &bucket);
21332 if (ret != 0)
21333 return(ret);
21334 if (bucket == NULL) {
21335 PERROR_INT("xmlSchemaAssembleByLocation",
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021336 "no schema bucket acquired");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021337 return(-1);
21338 }
21339 /*
21340 * The first located schema will be handled as if all other
21341 * schemas imported by XSI were imported by this first schema.
21342 */
21343 if ((bucket != NULL) &&
21344 (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21345 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21346 /*
21347 * TODO: Is this handled like an import? I.e. is it not an error
21348 * if the schema cannot be located?
21349 */
21350 if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21351 return(0);
21352 /*
21353 * We will reuse the parser context for every schema imported
21354 * directly via XSI. So reset the context.
21355 */
21356 pctxt->nberrors = 0;
21357 pctxt->err = 0;
21358 pctxt->doc = bucket->doc;
21359
21360 ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21361 if (ret == -1) {
21362 pctxt->doc = NULL;
21363 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021364 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021365 /* Paranoid error channelling. */
21366 if ((ret == 0) && (pctxt->nberrors != 0))
21367 ret = pctxt->err;
21368 if (pctxt->nberrors == 0) {
21369 /*
21370 * Only bother to fixup pending components, if there was
21371 * no error yet.
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021372 * For every XSI acquired schema (and its sub-schemata) we will
21373 * fixup the components.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021374 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021375 xmlSchemaFixupComponents(pctxt, bucket);
Kasimier T. Buchcik215406f2005-12-07 12:14:09 +000021376 ret = pctxt->err;
21377 /*
21378 * Not nice, but we need somehow to channel the schema parser
21379 * error to the validation context.
21380 */
21381 if ((ret != 0) && (vctxt->err == 0))
21382 vctxt->err = ret;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021383 vctxt->nberrors += pctxt->nberrors;
21384 } else {
21385 /* Add to validation error sum. */
21386 vctxt->nberrors += pctxt->nberrors;
21387 }
21388 pctxt->doc = NULL;
21389 return(ret);
21390exit_failure:
21391 pctxt->doc = NULL;
21392 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021393}
21394
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021395static xmlSchemaAttrInfoPtr
21396xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21397 int metaType)
21398{
21399 if (vctxt->nbAttrInfos == 0)
21400 return (NULL);
21401 {
21402 int i;
21403 xmlSchemaAttrInfoPtr iattr;
21404
21405 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21406 iattr = vctxt->attrInfos[i];
21407 if (iattr->metaType == metaType)
21408 return (iattr);
21409 }
21410
21411 }
21412 return (NULL);
21413}
21414
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021415/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021416 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021417 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021418 *
21419 * Expands an existing schema by an additional schema using
21420 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21421 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21422 * must be set to 1.
21423 *
21424 * Returns 0 if the new schema is correct, a positive error code
21425 * number otherwise and -1 in case of an internal or API error.
21426 */
21427static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021428xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021429{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021430 const xmlChar *cur, *end;
21431 const xmlChar *nsname = NULL, *location;
21432 int count = 0;
21433 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021434 xmlSchemaAttrInfoPtr iattr;
21435
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021436 /*
21437 * Parse the value; we will assume an even number of values
21438 * to be given (this is how Xerces and XSV work).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021439 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021440 * URGENT TODO: !! This needs to work for both
21441 * @noNamespaceSchemaLocation AND @schemaLocation on the same
21442 * element !!
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021443 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021444 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21445 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21446 if (iattr == NULL)
Kasimier T. Buchcik81755ea2005-11-23 16:39:27 +000021447 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021448 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21449 if (iattr == NULL)
21450 return (0);
21451 cur = iattr->value;
21452 do {
21453 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021454 /*
21455 * Get the namespace name.
21456 */
21457 while (IS_BLANK_CH(*cur))
21458 cur++;
21459 end = cur;
21460 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21461 end++;
21462 if (end == cur)
21463 break;
21464 count++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021465 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021466 cur = end;
21467 }
21468 /*
21469 * Get the URI.
21470 */
21471 while (IS_BLANK_CH(*cur))
21472 cur++;
21473 end = cur;
21474 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21475 end++;
21476 if (end == cur)
21477 break;
21478 count++;
21479 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021480 cur = end;
21481 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21482 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021483 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021484 VERROR_INT("xmlSchemaAssembleByXSI",
21485 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021486 return (-1);
21487 }
21488 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021489 return (ret);
21490}
21491
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021492static const xmlChar *
21493xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21494 const xmlChar *prefix)
21495{
21496 if (vctxt->sax != NULL) {
21497 int i, j;
21498 xmlSchemaNodeInfoPtr inode;
21499
21500 for (i = vctxt->depth; i >= 0; i--) {
21501 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21502 inode = vctxt->elemInfos[i];
21503 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21504 if (((prefix == NULL) &&
21505 (inode->nsBindings[j] == NULL)) ||
21506 ((prefix != NULL) && xmlStrEqual(prefix,
21507 inode->nsBindings[j]))) {
21508
21509 /*
21510 * Note that the namespace bindings are already
21511 * in a string dict.
21512 */
21513 return (inode->nsBindings[j+1]);
21514 }
21515 }
21516 }
21517 }
21518 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000021519#ifdef LIBXML_WRITER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021520 } else if (vctxt->reader != NULL) {
21521 xmlChar *nsName;
21522
21523 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21524 if (nsName != NULL) {
21525 const xmlChar *ret;
21526
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021527 ret = xmlDictLookup(vctxt->dict, nsName, -1);
21528 xmlFree(nsName);
21529 return (ret);
21530 } else
21531 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000021532#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021533 } else {
21534 xmlNsPtr ns;
21535
21536 if ((vctxt->inode->node == NULL) ||
21537 (vctxt->inode->node->doc == NULL)) {
21538 VERROR_INT("xmlSchemaLookupNamespace",
21539 "no node or node's doc avaliable");
21540 return (NULL);
21541 }
21542 ns = xmlSearchNs(vctxt->inode->node->doc,
21543 vctxt->inode->node, prefix);
21544 if (ns != NULL)
21545 return (ns->href);
21546 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021547 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021548}
21549
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021550/*
21551* This one works on the schema of the validation context.
21552*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021553static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021554xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21555 xmlSchemaPtr schema,
21556 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021557 const xmlChar *value,
21558 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021559 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021560{
21561 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021562
21563 if (vctxt && (vctxt->schema == NULL)) {
21564 VERROR_INT("xmlSchemaValidateNotation",
21565 "a schema is needed on the validation context");
21566 return (-1);
21567 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021568 ret = xmlValidateQName(value, 1);
21569 if (ret != 0)
21570 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021571 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021572 xmlChar *localName = NULL;
21573 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021574
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021575 localName = xmlSplitQName2(value, &prefix);
21576 if (prefix != NULL) {
21577 const xmlChar *nsName = NULL;
21578
21579 if (vctxt != NULL)
21580 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21581 else if (node != NULL) {
21582 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21583 if (ns != NULL)
21584 nsName = ns->href;
21585 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021586 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021587 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021588 return (1);
21589 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021590 if (nsName == NULL) {
21591 xmlFree(prefix);
21592 xmlFree(localName);
21593 return (1);
21594 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021595 if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021596 if (valNeeded && (val != NULL)) {
21597 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
21598 BAD_CAST xmlStrdup(nsName));
21599 if (*val == NULL)
21600 ret = -1;
21601 }
21602 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021603 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021604 xmlFree(prefix);
21605 xmlFree(localName);
21606 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021607 if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021608 if (valNeeded && (val != NULL)) {
21609 (*val) = xmlSchemaNewNOTATIONValue(
21610 BAD_CAST xmlStrdup(value), NULL);
21611 if (*val == NULL)
21612 ret = -1;
21613 }
21614 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021615 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021616 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021617 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021618 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021619}
21620
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000021621static int
21622xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21623 const xmlChar* lname,
21624 const xmlChar* nsname)
21625{
21626 int i;
21627
21628 lname = xmlDictLookup(vctxt->dict, lname, -1);
21629 if (lname == NULL)
21630 return(-1);
21631 if (nsname != NULL) {
21632 nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21633 if (nsname == NULL)
21634 return(-1);
21635 }
21636 for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21637 if ((vctxt->nodeQNames->items [i] == lname) &&
21638 (vctxt->nodeQNames->items[i +1] == nsname))
21639 /* Already there */
21640 return(i);
21641 }
21642 /* Add new entry. */
21643 i = vctxt->nodeQNames->nbItems;
21644 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21645 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21646 return(i);
21647}
21648
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021649/************************************************************************
21650 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021651 * Validation of identity-constraints (IDC) *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021652 * *
21653 ************************************************************************/
21654
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021655/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021656 * xmlSchemaAugmentIDC:
21657 * @idcDef: the IDC definition
21658 *
21659 * Creates an augmented IDC definition item.
21660 *
21661 * Returns the item, or NULL on internal errors.
21662 */
21663static void
21664xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
21665 xmlSchemaValidCtxtPtr vctxt)
21666{
21667 xmlSchemaIDCAugPtr aidc;
21668
21669 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21670 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021671 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021672 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21673 NULL);
21674 return;
21675 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021676 aidc->keyrefDepth = -1;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021677 aidc->def = idcDef;
21678 aidc->next = NULL;
21679 if (vctxt->aidcs == NULL)
21680 vctxt->aidcs = aidc;
21681 else {
21682 aidc->next = vctxt->aidcs;
21683 vctxt->aidcs = aidc;
21684 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021685 /*
21686 * Save if we have keyrefs at all.
21687 */
21688 if ((vctxt->hasKeyrefs == 0) &&
21689 (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
21690 vctxt->hasKeyrefs = 1;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021691}
21692
21693/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021694 * xmlSchemaIDCNewBinding:
21695 * @idcDef: the IDC definition of this binding
21696 *
21697 * Creates a new IDC binding.
21698 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021699 * Returns the new IDC binding, NULL on internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021700 */
21701static xmlSchemaPSVIIDCBindingPtr
21702xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
21703{
21704 xmlSchemaPSVIIDCBindingPtr ret;
21705
21706 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
21707 sizeof(xmlSchemaPSVIIDCBinding));
21708 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021709 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021710 "allocating a PSVI IDC binding item", NULL);
21711 return (NULL);
21712 }
21713 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
21714 ret->definition = idcDef;
21715 return (ret);
21716}
21717
21718/**
21719 * xmlSchemaIDCStoreNodeTableItem:
21720 * @vctxt: the WXS validation context
21721 * @item: the IDC node table item
21722 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021723 * The validation context is used to store IDC node table items.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021724 * They are stored to avoid copying them if IDC node-tables are merged
21725 * with corresponding parent IDC node-tables (bubbling).
21726 *
21727 * Returns 0 if succeeded, -1 on internal errors.
21728 */
21729static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021730xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021731 xmlSchemaPSVIIDCNodePtr item)
21732{
21733 /*
21734 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021735 */
21736 if (vctxt->idcNodes == NULL) {
21737 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021738 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
21739 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021740 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021741 "allocating the IDC node table item list", NULL);
21742 return (-1);
21743 }
21744 vctxt->sizeIdcNodes = 20;
21745 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
21746 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021747 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
21748 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021749 sizeof(xmlSchemaPSVIIDCNodePtr));
21750 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021751 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021752 "re-allocating the IDC node table item list", NULL);
21753 return (-1);
21754 }
21755 }
21756 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021757
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021758 return (0);
21759}
21760
21761/**
21762 * xmlSchemaIDCStoreKey:
21763 * @vctxt: the WXS validation context
21764 * @item: the IDC key
21765 *
21766 * The validation context is used to store an IDC key.
21767 *
21768 * Returns 0 if succeeded, -1 on internal errors.
21769 */
21770static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021771xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021772 xmlSchemaPSVIIDCKeyPtr key)
21773{
21774 /*
21775 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021776 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021777 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021778 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021779 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
21780 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021781 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021782 "allocating the IDC key storage list", NULL);
21783 return (-1);
21784 }
21785 vctxt->sizeIdcKeys = 40;
21786 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
21787 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021788 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
21789 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021790 sizeof(xmlSchemaPSVIIDCKeyPtr));
21791 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021792 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021793 "re-allocating the IDC key storage list", NULL);
21794 return (-1);
21795 }
21796 }
21797 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021798
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021799 return (0);
21800}
21801
21802/**
21803 * xmlSchemaIDCAppendNodeTableItem:
21804 * @bind: the IDC binding
21805 * @ntItem: the node-table item
21806 *
21807 * Appends the IDC node-table item to the binding.
21808 *
21809 * Returns 0 on success and -1 on internal errors.
21810 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021811static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021812xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
21813 xmlSchemaPSVIIDCNodePtr ntItem)
21814{
21815 if (bind->nodeTable == NULL) {
21816 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021817 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021818 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
21819 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021820 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021821 "allocating an array of IDC node-table items", NULL);
21822 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021823 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021824 } else if (bind->sizeNodes <= bind->nbNodes) {
21825 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021826 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
21827 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021828 sizeof(xmlSchemaPSVIIDCNodePtr));
21829 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021830 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021831 "re-allocating an array of IDC node-table items", NULL);
21832 return(-1);
21833 }
21834 }
21835 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021836 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021837}
21838
21839/**
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021840 * xmlSchemaIDCAcquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021841 * @vctxt: the WXS validation context
21842 * @matcher: the IDC matcher
21843 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021844 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021845 * of the given matcher. If none found, a new one is created
21846 * and added to the IDC table.
21847 *
21848 * Returns an IDC binding or NULL on internal errors.
21849 */
21850static xmlSchemaPSVIIDCBindingPtr
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021851xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021852 xmlSchemaIDCMatcherPtr matcher)
21853{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021854 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021855
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021856 ielem = vctxt->elemInfos[matcher->depth];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021857
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021858 if (ielem->idcTable == NULL) {
21859 ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
21860 if (ielem->idcTable == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021861 return (NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021862 return(ielem->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021863 } else {
21864 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021865
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021866 bind = ielem->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021867 do {
21868 if (bind->definition == matcher->aidc->def)
21869 return(bind);
21870 if (bind->next == NULL) {
21871 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
21872 if (bind->next == NULL)
21873 return (NULL);
21874 return(bind->next);
21875 }
21876 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021877 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021878 }
21879 return (NULL);
21880}
21881
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021882static xmlSchemaItemListPtr
21883xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
21884 xmlSchemaIDCMatcherPtr matcher)
21885{
21886 if (matcher->targets == NULL)
21887 matcher->targets = xmlSchemaItemListCreate();
21888 return(matcher->targets);
21889}
21890
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021891/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021892 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021893 * @key: the IDC key
21894 *
21895 * Frees an IDC key together with its compiled value.
21896 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021897static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021898xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
21899{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021900 if (key->val != NULL)
21901 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021902 xmlFree(key);
21903}
21904
21905/**
21906 * xmlSchemaIDCFreeBinding:
21907 *
21908 * Frees an IDC binding. Note that the node table-items
21909 * are not freed.
21910 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021911static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021912xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
21913{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021914 if (bind->nodeTable != NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021915 xmlFree(bind->nodeTable);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021916 if (bind->dupls != NULL)
21917 xmlSchemaItemListFree(bind->dupls);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021918 xmlFree(bind);
21919}
21920
21921/**
21922 * xmlSchemaIDCFreeIDCTable:
21923 * @bind: the first IDC binding in the list
21924 *
21925 * Frees an IDC table, i.e. all the IDC bindings in the list.
21926 */
21927static void
21928xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
21929{
21930 xmlSchemaPSVIIDCBindingPtr prev;
21931
21932 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021933 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021934 bind = bind->next;
21935 xmlSchemaIDCFreeBinding(prev);
21936 }
21937}
21938
21939/**
21940 * xmlSchemaIDCFreeMatcherList:
21941 * @matcher: the first IDC matcher in the list
21942 *
21943 * Frees a list of IDC matchers.
21944 */
21945static void
21946xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
21947{
21948 xmlSchemaIDCMatcherPtr next;
21949
21950 while (matcher != NULL) {
21951 next = matcher->next;
21952 if (matcher->keySeqs != NULL) {
21953 int i;
21954 for (i = 0; i < matcher->sizeKeySeqs; i++)
21955 if (matcher->keySeqs[i] != NULL)
21956 xmlFree(matcher->keySeqs[i]);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021957 xmlFree(matcher->keySeqs);
21958 }
21959 if (matcher->targets != NULL) {
21960 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
21961 int i;
21962 xmlSchemaPSVIIDCNodePtr idcNode;
21963 /*
21964 * Node-table items for keyrefs are not stored globally
21965 * to the validation context, since they are not bubbled.
21966 * We need to free them here.
21967 */
21968 for (i = 0; i < matcher->targets->nbItems; i++) {
21969 idcNode =
21970 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
21971 xmlFree(idcNode->keys);
21972 xmlFree(idcNode);
21973 }
21974 }
21975 xmlSchemaItemListFree(matcher->targets);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021976 }
21977 xmlFree(matcher);
21978 matcher = next;
21979 }
21980}
21981
21982/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021983 * xmlSchemaIDCAddStateObject:
21984 * @vctxt: the WXS validation context
21985 * @matcher: the IDC matcher
21986 * @sel: the XPath information
21987 * @parent: the parent "selector" state object if any
21988 * @type: "selector" or "field"
21989 *
21990 * Creates/reuses and activates state objects for the given
21991 * XPath information; if the XPath expression consists of unions,
21992 * multiple state objects are created for every unioned expression.
21993 *
21994 * Returns 0 on success and -1 on internal errors.
21995 */
21996static int
21997xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
21998 xmlSchemaIDCMatcherPtr matcher,
21999 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022000 int type)
22001{
22002 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022003
22004 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022005 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022006 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022007 if (vctxt->xpathStatePool != NULL) {
22008 sto = vctxt->xpathStatePool;
22009 vctxt->xpathStatePool = sto->next;
22010 sto->next = NULL;
22011 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022012 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022013 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022014 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022015 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22016 if (sto == NULL) {
22017 xmlSchemaVErrMemory(NULL,
22018 "allocating an IDC state object", NULL);
22019 return (-1);
22020 }
22021 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22022 }
22023 /*
22024 * Add to global list.
22025 */
22026 if (vctxt->xpathStates != NULL)
22027 sto->next = vctxt->xpathStates;
22028 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022029
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022030 /*
22031 * Free the old xpath validation context.
22032 */
22033 if (sto->xpathCtxt != NULL)
22034 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22035
22036 /*
22037 * Create a new XPath (pattern) validation context.
22038 */
22039 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22040 (xmlPatternPtr) sel->xpathComp);
22041 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022042 VERROR_INT("xmlSchemaIDCAddStateObject",
22043 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022044 return (-1);
22045 }
22046 sto->type = type;
22047 sto->depth = vctxt->depth;
22048 sto->matcher = matcher;
22049 sto->sel = sel;
22050 sto->nbHistory = 0;
22051
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022052#ifdef DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022053 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
22054 sto->sel->xpath);
22055#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022056 return (0);
22057}
22058
22059/**
22060 * xmlSchemaXPathEvaluate:
22061 * @vctxt: the WXS validation context
22062 * @nodeType: the nodeType of the current node
22063 *
22064 * Evaluates all active XPath state objects.
22065 *
22066 * Returns the number of IC "field" state objects which resolved to
22067 * this node, 0 if none resolved and -1 on internal errors.
22068 */
22069static int
22070xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022071 xmlElementType nodeType)
22072{
22073 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022074 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022075
22076 if (vctxt->xpathStates == NULL)
22077 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022078
22079 if (nodeType == XML_ATTRIBUTE_NODE)
22080 depth++;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022081#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022082 {
22083 xmlChar *str = NULL;
22084 xmlGenericError(xmlGenericErrorContext,
22085 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022086 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22087 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022088 FREE_AND_NULL(str)
22089 }
22090#endif
22091 /*
22092 * Process all active XPath state objects.
22093 */
22094 first = vctxt->xpathStates;
22095 sto = first;
22096 while (sto != head) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022097#ifdef DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022098 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022099 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
22100 sto->matcher->aidc->def->name, sto->sel->xpath);
22101 else
22102 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
22103 sto->matcher->aidc->def->name, sto->sel->xpath);
22104#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022105 if (nodeType == XML_ELEMENT_NODE)
22106 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022107 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022108 else
22109 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022110 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022111
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022112 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022113 VERROR_INT("xmlSchemaXPathEvaluate",
22114 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022115 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022116 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022117 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022118 goto next_sto;
22119 /*
22120 * Full match.
22121 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022122#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022123 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022124 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022125#endif
22126 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022127 * Register a match in the state object history.
22128 */
22129 if (sto->history == NULL) {
22130 sto->history = (int *) xmlMalloc(5 * sizeof(int));
22131 if (sto->history == NULL) {
22132 xmlSchemaVErrMemory(NULL,
22133 "allocating the state object history", NULL);
22134 return(-1);
22135 }
22136 sto->sizeHistory = 10;
22137 } else if (sto->sizeHistory <= sto->nbHistory) {
22138 sto->sizeHistory *= 2;
22139 sto->history = (int *) xmlRealloc(sto->history,
22140 sto->sizeHistory * sizeof(int));
22141 if (sto->history == NULL) {
22142 xmlSchemaVErrMemory(NULL,
22143 "re-allocating the state object history", NULL);
22144 return(-1);
22145 }
22146 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022147 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022148
22149#ifdef DEBUG_IDC
22150 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
22151 vctxt->depth);
22152#endif
22153
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022154 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22155 xmlSchemaIDCSelectPtr sel;
22156 /*
22157 * Activate state objects for the IDC fields of
22158 * the IDC selector.
22159 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022160#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022161 xmlGenericError(xmlGenericErrorContext, "IDC: "
22162 "activating field states\n");
22163#endif
22164 sel = sto->matcher->aidc->def->fields;
22165 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022166 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22167 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22168 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022169 sel = sel->next;
22170 }
22171 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22172 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022173 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022174 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022175#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022176 xmlGenericError(xmlGenericErrorContext,
22177 "IDC: key found\n");
22178#endif
22179 /*
22180 * Notify that the character value of this node is
22181 * needed.
22182 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022183 if (resolved == 0) {
22184 if ((vctxt->inode->flags &
22185 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22186 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22187 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022188 resolved++;
22189 }
22190next_sto:
22191 if (sto->next == NULL) {
22192 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022193 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022194 */
22195 head = first;
22196 sto = vctxt->xpathStates;
22197 } else
22198 sto = sto->next;
22199 }
22200 return (resolved);
22201}
22202
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022203static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022204xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022205 xmlChar **buf,
22206 xmlSchemaPSVIIDCKeyPtr *seq,
22207 int count)
22208{
22209 int i, res;
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022210 xmlChar *value = NULL;
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022211
22212 *buf = xmlStrdup(BAD_CAST "[");
22213 for (i = 0; i < count; i++) {
22214 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022215 res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22216 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22217 &value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022218 if (res == 0)
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022219 *buf = xmlStrcat(*buf, BAD_CAST value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022220 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022221 VERROR_INT("xmlSchemaFormatIDCKeySequence",
22222 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022223 *buf = xmlStrcat(*buf, BAD_CAST "???");
22224 }
22225 if (i < count -1)
22226 *buf = xmlStrcat(*buf, BAD_CAST "', ");
22227 else
22228 *buf = xmlStrcat(*buf, BAD_CAST "'");
22229 if (value != NULL) {
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022230 xmlFree(value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022231 value = NULL;
22232 }
22233 }
22234 *buf = xmlStrcat(*buf, BAD_CAST "]");
22235
22236 return (BAD_CAST *buf);
22237}
22238
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022239/**
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000022240 * xmlSchemaXPathPop:
22241 * @vctxt: the WXS validation context
22242 *
22243 * Pops all XPath states.
22244 *
22245 * Returns 0 on success and -1 on internal errors.
22246 */
22247static int
22248xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22249{
22250 xmlSchemaIDCStateObjPtr sto;
22251 int res;
22252
22253 if (vctxt->xpathStates == NULL)
22254 return(0);
22255 sto = vctxt->xpathStates;
22256 do {
22257 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22258 if (res == -1)
22259 return (-1);
22260 sto = sto->next;
22261 } while (sto != NULL);
22262 return(0);
22263}
22264
22265/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022266 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022267 * @vctxt: the WXS validation context
22268 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022269 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022270 *
22271 * Processes and pops the history items of the IDC state objects.
22272 * IDC key-sequences are validated/created on IDC bindings.
22273 *
22274 * Returns 0 on success and -1 on internal errors.
22275 */
22276static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022277xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022278 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022279{
22280 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022281 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022282 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022283 xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022284
22285 if (vctxt->xpathStates == NULL)
22286 return (0);
22287 sto = vctxt->xpathStates;
22288
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022289#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022290 {
22291 xmlChar *str = NULL;
22292 xmlGenericError(xmlGenericErrorContext,
22293 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022294 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22295 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022296 FREE_AND_NULL(str)
22297 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022298#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022299 /*
22300 * Evaluate the state objects.
22301 */
22302 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000022303 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22304 if (res == -1) {
22305 VERROR_INT("xmlSchemaXPathProcessHistory",
22306 "calling xmlStreamPop()");
22307 return (-1);
22308 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022309#ifdef DEBUG_IDC
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022310 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
22311 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022312#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022313 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022314 goto deregister_check;
22315
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022316 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022317
22318 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022319 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022320 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022321 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022322 sto = sto->next;
22323 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022324 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022325 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022326 /*
22327 * NOTE: According to
22328 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22329 * ... the simple-content of complex types is also allowed.
22330 */
22331
22332 if (WXS_IS_COMPLEX(type)) {
22333 if (WXS_HAS_SIMPLE_CONTENT(type)) {
22334 /*
22335 * Sanity check for complex types with simple content.
22336 */
22337 simpleType = type->contentTypeDef;
22338 if (simpleType == NULL) {
22339 VERROR_INT("xmlSchemaXPathProcessHistory",
22340 "field resolves to a CT with simple content "
22341 "but the CT is missing the ST definition");
22342 return (-1);
22343 }
22344 } else
22345 simpleType = NULL;
22346 } else
22347 simpleType = type;
22348 if (simpleType == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022349 xmlChar *str = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022350
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022351 /*
22352 * Not qualified if the field resolves to a node of non
22353 * simple type.
22354 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022355 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022356 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022357 WXS_BASIC_CAST sto->matcher->aidc->def,
22358 "The XPath '%s' of a field of %s does evaluate to a node of "
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022359 "non-simple type",
22360 sto->sel->xpath,
22361 xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22362 FREE_AND_NULL(str);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022363 sto->nbHistory--;
22364 goto deregister_check;
22365 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022366
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022367 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022368 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022369 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022370 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022371 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022372 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022373 WXS_BASIC_CAST sto->matcher->aidc->def,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000022374 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022375 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022376 sto->nbHistory--;
22377 goto deregister_check;
22378 } else {
22379 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22380 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022381 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022382
22383 /*
22384 * The key will be anchored on the matcher's list of
22385 * key-sequences. The position in this list is determined
22386 * by the target node's depth relative to the matcher's
22387 * depth of creation (i.e. the depth of the scope element).
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022388 *
22389 * Element Depth Pos List-entries
22390 * <scope> 0 NULL
22391 * <bar> 1 NULL
22392 * <target/> 2 2 target
22393 * <bar>
22394 * </scope>
22395 *
22396 * The size of the list is only dependant on the depth of
22397 * the tree.
22398 * An entry will be NULLed in selector_leave, i.e. when
22399 * we hit the target's
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022400 */
22401 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022402 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022403
22404 /*
22405 * Create/grow the array of key-sequences.
22406 */
22407 if (matcher->keySeqs == NULL) {
22408 if (pos > 9)
22409 matcher->sizeKeySeqs = pos * 2;
22410 else
22411 matcher->sizeKeySeqs = 10;
22412 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22413 xmlMalloc(matcher->sizeKeySeqs *
22414 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22415 if (matcher->keySeqs == NULL) {
22416 xmlSchemaVErrMemory(NULL,
22417 "allocating an array of key-sequences",
22418 NULL);
22419 return(-1);
22420 }
22421 memset(matcher->keySeqs, 0,
22422 matcher->sizeKeySeqs *
22423 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22424 } else if (pos >= matcher->sizeKeySeqs) {
22425 int i = matcher->sizeKeySeqs;
22426
22427 matcher->sizeKeySeqs *= 2;
22428 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22429 xmlRealloc(matcher->keySeqs,
22430 matcher->sizeKeySeqs *
22431 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022432 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022433 xmlSchemaVErrMemory(NULL,
22434 "reallocating an array of key-sequences",
22435 NULL);
22436 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022437 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022438 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022439 * The array needs to be NULLed.
22440 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022441 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022442 for (; i < matcher->sizeKeySeqs; i++)
22443 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022444 }
22445
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022446 /*
22447 * Get/create the key-sequence.
22448 */
22449 keySeq = matcher->keySeqs[pos];
22450 if (keySeq == NULL) {
22451 goto create_sequence;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022452 } else if (keySeq[idx] != NULL) {
22453 xmlChar *str = NULL;
22454 /*
22455 * cvc-identity-constraint:
22456 * 3 For each node in the ·target node set· all
22457 * of the {fields}, with that node as the context
22458 * node, evaluate to either an empty node-set or
22459 * a node-set with exactly one member, which must
22460 * have a simple type.
22461 *
22462 * The key was already set; report an error.
22463 */
22464 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22465 XML_SCHEMAV_CVC_IDC, NULL,
22466 WXS_BASIC_CAST matcher->aidc->def,
22467 "The XPath '%s' of a field of %s evaluates to a "
22468 "node-set with more than one member",
22469 sto->sel->xpath,
22470 xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22471 FREE_AND_NULL(str);
22472 sto->nbHistory--;
22473 goto deregister_check;
22474 } else
22475 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022476
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022477create_sequence:
22478 /*
22479 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022480 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022481 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22482 matcher->aidc->def->nbFields *
22483 sizeof(xmlSchemaPSVIIDCKeyPtr));
22484 if (keySeq == NULL) {
22485 xmlSchemaVErrMemory(NULL,
22486 "allocating an IDC key-sequence", NULL);
22487 return(-1);
22488 }
22489 memset(keySeq, 0, matcher->aidc->def->nbFields *
22490 sizeof(xmlSchemaPSVIIDCKeyPtr));
22491 matcher->keySeqs[pos] = keySeq;
22492create_key:
22493 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022494 * Create a key once per node only.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022495 */
22496 if (key == NULL) {
22497 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22498 sizeof(xmlSchemaPSVIIDCKey));
22499 if (key == NULL) {
22500 xmlSchemaVErrMemory(NULL,
22501 "allocating a IDC key", NULL);
22502 xmlFree(keySeq);
22503 matcher->keySeqs[pos] = NULL;
22504 return(-1);
22505 }
22506 /*
22507 * Consume the compiled value.
22508 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022509 key->type = simpleType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022510 key->val = vctxt->inode->val;
22511 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022512 /*
22513 * Store the key in a global list.
22514 */
22515 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22516 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022517 return (-1);
22518 }
22519 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022520 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022521 }
22522 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022523
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022524 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022525 /* xmlSchemaPSVIIDCBindingPtr bind; */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022526 xmlSchemaPSVIIDCNodePtr ntItem;
22527 xmlSchemaIDCMatcherPtr matcher;
22528 xmlSchemaIDCPtr idc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022529 xmlSchemaItemListPtr targets;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022530 int pos, i, j, nbKeys;
22531 /*
22532 * Here we have the following scenario:
22533 * An IDC 'selector' state object resolved to a target node,
22534 * during the time this target node was in the
22535 * ancestor-or-self axis, the 'field' state object(s) looked
22536 * out for matching nodes to create a key-sequence for this
22537 * target node. Now we are back to this target node and need
22538 * to put the key-sequence, together with the target node
22539 * itself, into the node-table of the corresponding IDC
22540 * binding.
22541 */
22542 matcher = sto->matcher;
22543 idc = matcher->aidc->def;
22544 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022545 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022546 /*
22547 * Check if the matcher has any key-sequences at all, plus
22548 * if it has a key-sequence for the current target node.
22549 */
22550 if ((matcher->keySeqs == NULL) ||
22551 (matcher->sizeKeySeqs <= pos)) {
22552 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22553 goto selector_key_error;
22554 else
22555 goto selector_leave;
22556 }
22557
22558 keySeq = &(matcher->keySeqs[pos]);
22559 if (*keySeq == NULL) {
22560 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22561 goto selector_key_error;
22562 else
22563 goto selector_leave;
22564 }
22565
22566 for (i = 0; i < nbKeys; i++) {
22567 if ((*keySeq)[i] == NULL) {
22568 /*
22569 * Not qualified, if not all fields did resolve.
22570 */
22571 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22572 /*
22573 * All fields of a "key" IDC must resolve.
22574 */
22575 goto selector_key_error;
22576 }
22577 goto selector_leave;
22578 }
22579 }
22580 /*
22581 * All fields did resolve.
22582 */
22583
22584 /*
22585 * 4.1 If the {identity-constraint category} is unique(/key),
22586 * then no two members of the ·qualified node set· have
22587 * ·key-sequences· whose members are pairwise equal, as
22588 * defined by Equal in [XML Schemas: Datatypes].
22589 *
22590 * Get the IDC binding from the matcher and check for
22591 * duplicate key-sequences.
22592 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022593#if 0
22594 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22595#endif
22596 targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022597 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022598 (targets->nbItems != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022599 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022600
22601 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022602 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022603 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022604 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022605 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022606 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022607 bkeySeq =
22608 ((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022609 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022610 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022611 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022612 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022613 if (res == -1) {
22614 return (-1);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022615 } else if (res == 0) {
22616 /*
22617 * One of the keys differs, so the key-sequence
22618 * won't be equal; get out.
22619 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022620 break;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022621 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022622 }
22623 if (res == 1) {
22624 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022625 * Duplicate key-sequence found.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022626 */
22627 break;
22628 }
22629 i++;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022630 } while (i < targets->nbItems);
22631 if (i != targets->nbItems) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022632 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022633 /*
22634 * TODO: Try to report the key-sequence.
22635 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022636 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022637 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022638 WXS_BASIC_CAST idc,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022639 "Duplicate key-sequence %s in %s",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022640 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022641 (*keySeq), nbKeys),
22642 xmlSchemaGetIDCDesignation(&strB, idc));
22643 FREE_AND_NULL(str);
22644 FREE_AND_NULL(strB);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022645 goto selector_leave;
22646 }
22647 }
22648 /*
22649 * Add a node-table item to the IDC binding.
22650 */
22651 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
22652 sizeof(xmlSchemaPSVIIDCNode));
22653 if (ntItem == NULL) {
22654 xmlSchemaVErrMemory(NULL,
22655 "allocating an IDC node-table item", NULL);
22656 xmlFree(*keySeq);
22657 *keySeq = NULL;
22658 return(-1);
22659 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022660 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022661
22662 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022663 * Store the node-table item in a global list.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022664 */
22665 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
22666 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
22667 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022668 xmlFree(*keySeq);
22669 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022670 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022671 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022672 ntItem->nodeQNameID = -1;
22673 } else {
22674 /*
22675 * Save a cached QName for this node on the IDC node, to be
22676 * able to report it, even if the node is not saved.
22677 */
22678 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
22679 vctxt->inode->localName, vctxt->inode->nsName);
22680 if (ntItem->nodeQNameID == -1) {
22681 xmlFree(ntItem);
22682 xmlFree(*keySeq);
22683 *keySeq = NULL;
22684 return (-1);
22685 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022686 }
22687 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022688 * Init the node-table item: Save the node, position and
22689 * consume the key-sequence.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022690 */
22691 ntItem->node = vctxt->node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022692 ntItem->nodeLine = vctxt->inode->nodeLine;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022693 ntItem->keys = *keySeq;
22694 *keySeq = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022695#if 0
22696 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
22697#endif
22698 if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022699 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
22700 /*
22701 * Free the item, since keyref items won't be
22702 * put on a global list.
22703 */
22704 xmlFree(ntItem->keys);
22705 xmlFree(ntItem);
22706 }
22707 return (-1);
22708 }
22709
22710 goto selector_leave;
22711selector_key_error:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022712 {
22713 xmlChar *str = NULL;
22714 /*
22715 * 4.2.1 (KEY) The ·target node set· and the
22716 * ·qualified node set· are equal, that is, every
22717 * member of the ·target node set· is also a member
22718 * of the ·qualified node set· and vice versa.
22719 */
22720 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22721 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022722 WXS_BASIC_CAST idc,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022723 "Not all fields of %s evaluate to a node",
22724 xmlSchemaGetIDCDesignation(&str, idc), NULL);
22725 FREE_AND_NULL(str);
22726 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022727selector_leave:
22728 /*
22729 * Free the key-sequence if not added to the IDC table.
22730 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022731 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022732 xmlFree(*keySeq);
22733 *keySeq = NULL;
22734 }
22735 } /* if selector */
22736
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022737 sto->nbHistory--;
22738
22739deregister_check:
22740 /*
22741 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022742 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022743 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022744#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022745 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
22746 sto->sel->xpath);
22747#endif
22748 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022749 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022750 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022751 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022752 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022753 nextsto = sto->next;
22754 /*
22755 * Unlink from the list of active XPath state objects.
22756 */
22757 vctxt->xpathStates = sto->next;
22758 sto->next = vctxt->xpathStatePool;
22759 /*
22760 * Link it to the pool of reusable state objects.
22761 */
22762 vctxt->xpathStatePool = sto;
22763 sto = nextsto;
22764 } else
22765 sto = sto->next;
22766 } /* while (sto != NULL) */
22767 return (0);
22768}
22769
22770/**
22771 * xmlSchemaIDCRegisterMatchers:
22772 * @vctxt: the WXS validation context
22773 * @elemDecl: the element declaration
22774 *
22775 * Creates helper objects to evaluate IDC selectors/fields
22776 * successively.
22777 *
22778 * Returns 0 if OK and -1 on internal errors.
22779 */
22780static int
22781xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
22782 xmlSchemaElementPtr elemDecl)
22783{
22784 xmlSchemaIDCMatcherPtr matcher, last = NULL;
22785 xmlSchemaIDCPtr idc, refIdc;
22786 xmlSchemaIDCAugPtr aidc;
22787
22788 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
22789 if (idc == NULL)
22790 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022791
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022792#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022793 {
22794 xmlChar *str = NULL;
22795 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022796 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022797 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22798 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022799 FREE_AND_NULL(str)
22800 }
22801#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022802 if (vctxt->inode->idcMatchers != NULL) {
22803 VERROR_INT("xmlSchemaIDCRegisterMatchers",
22804 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022805 return (-1);
22806 }
22807 do {
22808 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
22809 /*
22810 * Since IDCs bubbles are expensive we need to know the
22811 * depth at which the bubbles should stop; this will be
22812 * the depth of the top-most keyref IDC. If no keyref
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022813 * references a key/unique IDC, the keyrefDepth will
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022814 * be -1, indicating that no bubbles are needed.
22815 */
22816 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
22817 if (refIdc != NULL) {
22818 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022819 * Remember that we have keyrefs on this node.
22820 */
22821 vctxt->inode->hasKeyrefs = 1;
22822 /*
22823 * Lookup the referenced augmented IDC info.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022824 */
22825 aidc = vctxt->aidcs;
22826 while (aidc != NULL) {
22827 if (aidc->def == refIdc)
22828 break;
22829 aidc = aidc->next;
22830 }
22831 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022832 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022833 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022834 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022835 return (-1);
22836 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022837 if ((aidc->keyrefDepth == -1) ||
22838 (vctxt->depth < aidc->keyrefDepth))
22839 aidc->keyrefDepth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022840 }
22841 }
22842 /*
22843 * Lookup the augmented IDC item for the IDC definition.
22844 */
22845 aidc = vctxt->aidcs;
22846 while (aidc != NULL) {
22847 if (aidc->def == idc)
22848 break;
22849 aidc = aidc->next;
22850 }
22851 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022852 VERROR_INT("xmlSchemaIDCRegisterMatchers",
22853 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022854 return (-1);
22855 }
22856 /*
22857 * Create an IDC matcher for every IDC definition.
22858 */
22859 matcher = (xmlSchemaIDCMatcherPtr)
22860 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
22861 if (matcher == NULL) {
22862 xmlSchemaVErrMemory(vctxt,
22863 "allocating an IDC matcher", NULL);
22864 return (-1);
22865 }
22866 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
22867 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022868 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022869 else
22870 last->next = matcher;
22871 last = matcher;
22872
22873 matcher->type = IDC_MATCHER;
22874 matcher->depth = vctxt->depth;
22875 matcher->aidc = aidc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022876 matcher->idcType = aidc->def->type;
22877#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022878 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
22879#endif
22880 /*
22881 * Init the automaton state object.
22882 */
22883 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022884 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022885 return (-1);
22886
22887 idc = idc->next;
22888 } while (idc != NULL);
22889 return (0);
22890}
22891
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022892static int
22893xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
22894 xmlSchemaNodeInfoPtr ielem)
22895{
22896 xmlSchemaPSVIIDCBindingPtr bind;
22897 int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
22898 xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
22899 xmlSchemaPSVIIDCNodePtr *targets, *dupls;
22900
22901 xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
22902 /* vctxt->createIDCNodeTables */
22903 while (matcher != NULL) {
22904 /*
22905 * Skip keyref IDCs and empty IDC target-lists.
22906 */
22907 if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
22908 WXS_ILIST_IS_EMPTY(matcher->targets))
22909 {
22910 matcher = matcher->next;
22911 continue;
22912 }
22913 /*
22914 * If we _want_ the IDC node-table to be created in any case
22915 * then do so. Otherwise create them only if keyrefs need them.
22916 */
22917 if ((! vctxt->createIDCNodeTables) &&
22918 ((matcher->aidc->keyrefDepth == -1) ||
22919 (matcher->aidc->keyrefDepth > vctxt->depth)))
22920 {
22921 matcher = matcher->next;
22922 continue;
22923 }
22924 /*
22925 * Get/create the IDC binding on this element for the IDC definition.
22926 */
22927 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22928
22929 if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
22930 dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
22931 nbDupls = bind->dupls->nbItems;
22932 } else {
22933 dupls = NULL;
22934 nbDupls = 0;
22935 }
22936 if (bind->nodeTable != NULL) {
22937 nbNodeTable = bind->nbNodes;
22938 } else {
22939 nbNodeTable = 0;
22940 }
22941
22942 if ((nbNodeTable == 0) && (nbDupls == 0)) {
22943 /*
22944 * Transfer all IDC target-nodes to the IDC node-table.
22945 */
22946 bind->nodeTable =
22947 (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
22948 bind->sizeNodes = matcher->targets->sizeItems;
22949 bind->nbNodes = matcher->targets->nbItems;
22950
22951 matcher->targets->items = NULL;
22952 matcher->targets->sizeItems = 0;
22953 matcher->targets->nbItems = 0;
22954 } else {
22955 /*
22956 * Compare the key-sequences and add to the IDC node-table.
22957 */
22958 nbTargets = matcher->targets->nbItems;
22959 targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
22960 nbFields = matcher->aidc->def->nbFields;
22961 i = 0;
22962 do {
22963 keys = targets[i]->keys;
22964 if (nbDupls) {
22965 /*
22966 * Search in already found duplicates first.
22967 */
22968 j = 0;
22969 do {
22970 if (nbFields == 1) {
22971 res = xmlSchemaAreValuesEqual(keys[0]->val,
22972 dupls[j]->keys[0]->val);
22973 if (res == -1)
22974 goto internal_error;
22975 if (res == 1) {
22976 /*
22977 * Equal key-sequence.
22978 */
22979 goto next_target;
22980 }
22981 } else {
22982 res = 0;
22983 ntkeys = dupls[j]->keys;
22984 for (k = 0; k < nbFields; k++) {
22985 res = xmlSchemaAreValuesEqual(keys[k]->val,
22986 ntkeys[k]->val);
22987 if (res == -1)
22988 goto internal_error;
22989 if (res == 0) {
22990 /*
22991 * One of the keys differs.
22992 */
22993 break;
22994 }
22995 }
22996 if (res == 1) {
22997 /*
22998 * Equal key-sequence found.
22999 */
23000 goto next_target;
23001 }
23002 }
23003 j++;
23004 } while (j < nbDupls);
23005 }
23006 if (nbNodeTable) {
23007 j = 0;
23008 do {
23009 if (nbFields == 1) {
23010 res = xmlSchemaAreValuesEqual(keys[0]->val,
23011 bind->nodeTable[j]->keys[0]->val);
23012 if (res == -1)
23013 goto internal_error;
23014 if (res == 0) {
23015 /*
23016 * The key-sequence differs.
23017 */
23018 goto next_node_table_entry;
23019 }
23020 } else {
23021 res = 0;
23022 ntkeys = bind->nodeTable[j]->keys;
23023 for (k = 0; k < nbFields; k++) {
23024 res = xmlSchemaAreValuesEqual(keys[k]->val,
23025 ntkeys[k]->val);
23026 if (res == -1)
23027 goto internal_error;
23028 if (res == 0) {
23029 /*
23030 * One of the keys differs.
23031 */
23032 goto next_node_table_entry;
23033 }
23034 }
23035 }
23036 /*
23037 * Add the duplicate to the list of duplicates.
23038 */
23039 if (bind->dupls == NULL) {
23040 bind->dupls = xmlSchemaItemListCreate();
23041 if (bind->dupls == NULL)
23042 goto internal_error;
23043 }
23044 if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23045 goto internal_error;
23046 /*
23047 * Remove the duplicate entry from the IDC node-table.
23048 */
23049 bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23050 bind->nbNodes--;
23051
23052 goto next_target;
23053
23054next_node_table_entry:
23055 j++;
23056 } while (j < nbNodeTable);
23057 }
23058 /*
23059 * If everything is fine, then add the IDC target-node to
23060 * the IDC node-table.
23061 */
23062 if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23063 goto internal_error;
23064
23065next_target:
23066 i++;
23067 } while (i < nbTargets);
23068 }
23069 matcher = matcher->next;
23070 }
23071 return(0);
23072
23073internal_error:
23074 return(-1);
23075}
23076
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023077/**
23078 * xmlSchemaBubbleIDCNodeTables:
23079 * @depth: the current tree depth
23080 *
23081 * Merges IDC bindings of an element at @depth into the corresponding IDC
23082 * bindings of its parent element. If a duplicate note-table entry is found,
23083 * both, the parent node-table entry and child entry are discarded from the
23084 * node-table of the parent.
23085 *
23086 * Returns 0 if OK and -1 on internal errors.
23087 */
23088static int
23089xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23090{
23091 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023092 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23093 xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023094 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023095 int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023096
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023097 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023098 if (bind == NULL) {
23099 /* Fine, no table, no bubbles. */
23100 return (0);
23101 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000023102
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023103 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23104 /*
23105 * Walk all bindings; create new or add to existing bindings.
23106 * Remove duplicate key-sequences.
23107 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023108 while (bind != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023109
23110 if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23111 goto next_binding;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023112 /*
23113 * Check if the key/unique IDC table needs to be bubbled.
23114 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023115 if (! vctxt->createIDCNodeTables) {
23116 aidc = vctxt->aidcs;
23117 do {
23118 if (aidc->def == bind->definition) {
23119 if ((aidc->keyrefDepth == -1) ||
23120 (aidc->keyrefDepth >= vctxt->depth)) {
23121 goto next_binding;
23122 }
23123 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023124 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023125 aidc = aidc->next;
23126 } while (aidc != NULL);
23127 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023128
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023129 if (parTable != NULL)
23130 parBind = *parTable;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023131 /*
23132 * Search a matching parent binding for the
23133 * IDC definition.
23134 */
23135 while (parBind != NULL) {
23136 if (parBind->definition == bind->definition)
23137 break;
23138 parBind = parBind->next;
23139 }
23140
23141 if (parBind != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023142 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023143 * Compare every node-table entry of the child node,
23144 * i.e. the key-sequence within, ...
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023145 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023146 oldNum = parBind->nbNodes; /* Skip newly added items. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023147
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023148 if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23149 oldDupls = parBind->dupls->nbItems;
23150 dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23151 } else {
23152 dupls = NULL;
23153 oldDupls = 0;
23154 }
23155
23156 parNodes = parBind->nodeTable;
23157 nbFields = bind->definition->nbFields;
23158
23159 for (i = 0; i < bind->nbNodes; i++) {
23160 node = bind->nodeTable[i];
23161 if (node == NULL)
23162 continue;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023163 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023164 * ...with every key-sequence of the parent node, already
23165 * evaluated to be a duplicate key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023166 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023167 if (oldDupls) {
23168 j = 0;
23169 while (j < oldDupls) {
23170 if (nbFields == 1) {
23171 ret = xmlSchemaAreValuesEqual(
23172 node->keys[0]->val,
23173 dupls[j]->keys[0]->val);
23174 if (ret == -1)
23175 goto internal_error;
23176 if (ret == 0) {
23177 j++;
23178 continue;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023179 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023180 } else {
23181 parNode = dupls[j];
23182 for (k = 0; k < nbFields; k++) {
23183 ret = xmlSchemaAreValuesEqual(
23184 node->keys[k]->val,
23185 parNode->keys[k]->val);
23186 if (ret == -1)
23187 goto internal_error;
23188 if (ret == 0)
23189 break;
23190 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023191 }
23192 if (ret == 1)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023193 /* Duplicate found. */
23194 break;
23195 j++;
23196 }
23197 if (j != oldDupls) {
23198 /* Duplicate found. Skip this entry. */
23199 continue;
23200 }
23201 }
23202 /*
23203 * ... and with every key-sequence of the parent node.
23204 */
23205 if (oldNum) {
23206 j = 0;
23207 while (j < oldNum) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +000023208 parNode = parNodes[j];
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023209 if (nbFields == 1) {
23210 ret = xmlSchemaAreValuesEqual(
23211 node->keys[0]->val,
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +000023212 parNode->keys[0]->val);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023213 if (ret == -1)
23214 goto internal_error;
23215 if (ret == 0) {
23216 j++;
23217 continue;
23218 }
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +000023219 } else {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023220 for (k = 0; k < nbFields; k++) {
23221 ret = xmlSchemaAreValuesEqual(
23222 node->keys[k]->val,
23223 parNode->keys[k]->val);
23224 if (ret == -1)
23225 goto internal_error;
23226 if (ret == 0)
23227 break;
23228 }
23229 }
23230 if (ret == 1)
23231 /* Duplicate found. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023232 break;
23233 j++;
23234 }
23235 if (j != oldNum) {
23236 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023237 * Handle duplicates. Move the duplicate in
23238 * the parent's node-table to the list of
23239 * duplicates.
23240 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023241 oldNum--;
23242 parBind->nbNodes--;
23243 /*
23244 * Move last old item to pos of duplicate.
23245 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023246 parNodes[j] = parNodes[oldNum];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023247
23248 if (parBind->nbNodes != oldNum) {
23249 /*
23250 * If new items exist, move last new item to
23251 * last of old items.
23252 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023253 parNodes[oldNum] =
23254 parNodes[parBind->nbNodes];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023255 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023256 if (parBind->dupls == NULL) {
23257 parBind->dupls = xmlSchemaItemListCreate();
23258 if (parBind->dupls == NULL)
23259 goto internal_error;
23260 }
23261 xmlSchemaItemListAdd(parBind->dupls, parNode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023262 } else {
23263 /*
23264 * Add the node-table entry (node and key-sequence) of
23265 * the child node to the node table of the parent node.
23266 */
23267 if (parBind->nodeTable == NULL) {
23268 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000023269 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023270 if (parBind->nodeTable == NULL) {
23271 xmlSchemaVErrMemory(NULL,
23272 "allocating IDC list of node-table items", NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023273 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023274 }
23275 parBind->sizeNodes = 1;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023276 } else if (parBind->nbNodes >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000023277 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023278 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23279 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23280 sizeof(xmlSchemaPSVIIDCNodePtr));
23281 if (parBind->nodeTable == NULL) {
23282 xmlSchemaVErrMemory(NULL,
23283 "re-allocating IDC list of node-table items", NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023284 goto internal_error;
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000023285 }
23286 }
23287 parNodes = parBind->nodeTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023288 /*
23289 * Append the new node-table entry to the 'new node-table
23290 * entries' section.
23291 */
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000023292 parNodes[parBind->nbNodes++] = node;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023293 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023294
23295 }
23296
23297 }
23298 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023299 /*
23300 * No binding for the IDC was found: create a new one and
23301 * copy all node-tables.
23302 */
23303 parBind = xmlSchemaIDCNewBinding(bind->definition);
23304 if (parBind == NULL)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023305 goto internal_error;
23306
23307 /*
23308 * TODO: Hmm, how to optimize the initial number of
23309 * allocated entries?
23310 */
23311 if (bind->nbNodes != 0) {
23312 /*
23313 * Add all IDC node-table entries.
23314 */
23315 if (! vctxt->psviExposeIDCNodeTables) {
23316 /*
23317 * Just move the entries.
23318 * NOTE: this is quite save here, since
23319 * all the keyref lookups have already been
23320 * performed.
23321 */
23322 parBind->nodeTable = bind->nodeTable;
23323 bind->nodeTable = NULL;
23324 parBind->sizeNodes = bind->sizeNodes;
23325 bind->sizeNodes = 0;
23326 parBind->nbNodes = bind->nbNodes;
23327 bind->nbNodes = 0;
23328 } else {
23329 /*
23330 * Copy the entries.
23331 */
23332 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23333 xmlMalloc(bind->nbNodes *
23334 sizeof(xmlSchemaPSVIIDCNodePtr));
23335 if (parBind->nodeTable == NULL) {
23336 xmlSchemaVErrMemory(NULL,
23337 "allocating an array of IDC node-table "
23338 "items", NULL);
23339 xmlSchemaIDCFreeBinding(parBind);
23340 goto internal_error;
23341 }
23342 parBind->sizeNodes = bind->nbNodes;
23343 parBind->nbNodes = bind->nbNodes;
23344 memcpy(parBind->nodeTable, bind->nodeTable,
23345 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23346 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023347 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023348 if (bind->dupls) {
23349 /*
23350 * Move the duplicates.
23351 */
23352 if (parBind->dupls != NULL)
23353 xmlSchemaItemListFree(parBind->dupls);
23354 parBind->dupls = bind->dupls;
23355 bind->dupls = NULL;
23356 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023357 if (*parTable == NULL)
23358 *parTable = parBind;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023359 else {
23360 parBind->next = *parTable;
23361 *parTable = parBind;
23362 }
23363 }
23364
23365next_binding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023366 bind = bind->next;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023367 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023368 return (0);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023369
23370internal_error:
23371 return(-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023372}
23373
23374/**
23375 * xmlSchemaCheckCVCIDCKeyRef:
23376 * @vctxt: the WXS validation context
23377 * @elemDecl: the element declaration
23378 *
23379 * Check the cvc-idc-keyref constraints.
23380 */
23381static int
23382xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23383{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023384 xmlSchemaIDCMatcherPtr matcher;
23385 xmlSchemaPSVIIDCBindingPtr bind;
23386
23387 matcher = vctxt->inode->idcMatchers;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023388 /*
23389 * Find a keyref.
23390 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023391 while (matcher != NULL) {
23392 if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23393 matcher->targets &&
23394 matcher->targets->nbItems)
23395 {
23396 int i, j, k, res, nbFields, hasDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023397 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023398 xmlSchemaPSVIIDCNodePtr refNode = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023399
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023400 nbFields = matcher->aidc->def->nbFields;
23401
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023402 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023403 * Find the IDC node-table for the referenced IDC key/unique.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023404 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023405 bind = vctxt->inode->idcTable;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023406 while (bind != NULL) {
23407 if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023408 bind->definition)
23409 break;
23410 bind = bind->next;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023411 }
23412 hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023413 /*
23414 * Search for a matching key-sequences.
23415 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023416 for (i = 0; i < matcher->targets->nbItems; i++) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023417 res = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023418 refNode = matcher->targets->items[i];
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023419 if (bind != NULL) {
23420 refKeys = refNode->keys;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023421 for (j = 0; j < bind->nbNodes; j++) {
23422 keys = bind->nodeTable[j]->keys;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023423 for (k = 0; k < nbFields; k++) {
23424 res = xmlSchemaAreValuesEqual(keys[k]->val,
23425 refKeys[k]->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023426 if (res == 0)
23427 break;
23428 else if (res == -1) {
23429 return (-1);
23430 }
23431 }
23432 if (res == 1) {
23433 /*
23434 * Match found.
23435 */
23436 break;
23437 }
23438 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023439 if ((res == 0) && hasDupls) {
23440 /*
23441 * Search in duplicates
23442 */
23443 for (j = 0; j < bind->dupls->nbItems; j++) {
23444 keys = ((xmlSchemaPSVIIDCNodePtr)
23445 bind->dupls->items[j])->keys;
23446 for (k = 0; k < nbFields; k++) {
23447 res = xmlSchemaAreValuesEqual(keys[k]->val,
23448 refKeys[k]->val);
23449 if (res == 0)
23450 break;
23451 else if (res == -1) {
23452 return (-1);
23453 }
23454 }
23455 if (res == 1) {
23456 /*
23457 * Match in duplicates found.
23458 */
23459 xmlChar *str = NULL, *strB = NULL;
23460 xmlSchemaKeyrefErr(vctxt,
23461 XML_SCHEMAV_CVC_IDC, refNode,
23462 (xmlSchemaTypePtr) matcher->aidc->def,
23463 "More than one match found for "
23464 "key-sequence %s of keyref '%s'",
23465 xmlSchemaFormatIDCKeySequence(vctxt, &str,
23466 refNode->keys, nbFields),
23467 xmlSchemaGetComponentQName(&strB,
23468 matcher->aidc->def));
23469 FREE_AND_NULL(str);
23470 FREE_AND_NULL(strB);
23471 break;
23472 }
23473 }
23474 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023475 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023476
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023477 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023478 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023479 xmlSchemaKeyrefErr(vctxt,
23480 XML_SCHEMAV_CVC_IDC, refNode,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023481 (xmlSchemaTypePtr) matcher->aidc->def,
23482 "No match found for key-sequence %s of keyref '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000023483 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023484 refNode->keys, nbFields),
23485 xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023486 FREE_AND_NULL(str);
23487 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023488 }
23489 }
23490 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023491 matcher = matcher->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023492 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023493 /* TODO: Return an error if any error encountered. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023494 return (0);
23495}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023496
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023497/************************************************************************
23498 * *
23499 * XML Reader validation code *
23500 * *
23501 ************************************************************************/
23502
23503static xmlSchemaAttrInfoPtr
23504xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023505{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023506 xmlSchemaAttrInfoPtr iattr;
23507 /*
23508 * Grow/create list of attribute infos.
23509 */
23510 if (vctxt->attrInfos == NULL) {
23511 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23512 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23513 vctxt->sizeAttrInfos = 1;
23514 if (vctxt->attrInfos == NULL) {
23515 xmlSchemaVErrMemory(vctxt,
23516 "allocating attribute info list", NULL);
23517 return (NULL);
23518 }
23519 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23520 vctxt->sizeAttrInfos++;
23521 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23522 xmlRealloc(vctxt->attrInfos,
23523 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23524 if (vctxt->attrInfos == NULL) {
23525 xmlSchemaVErrMemory(vctxt,
23526 "re-allocating attribute info list", NULL);
23527 return (NULL);
23528 }
23529 } else {
23530 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23531 if (iattr->localName != NULL) {
23532 VERROR_INT("xmlSchemaGetFreshAttrInfo",
23533 "attr info not cleared");
23534 return (NULL);
23535 }
23536 iattr->nodeType = XML_ATTRIBUTE_NODE;
23537 return (iattr);
23538 }
23539 /*
23540 * Create an attribute info.
23541 */
23542 iattr = (xmlSchemaAttrInfoPtr)
23543 xmlMalloc(sizeof(xmlSchemaAttrInfo));
23544 if (iattr == NULL) {
23545 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23546 return (NULL);
23547 }
23548 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23549 iattr->nodeType = XML_ATTRIBUTE_NODE;
23550 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23551
23552 return (iattr);
23553}
23554
23555static int
23556xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23557 xmlNodePtr attrNode,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023558 int nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023559 const xmlChar *localName,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023560 const xmlChar *nsName,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023561 int ownedNames,
23562 xmlChar *value,
23563 int ownedValue)
23564{
23565 xmlSchemaAttrInfoPtr attr;
23566
23567 attr = xmlSchemaGetFreshAttrInfo(vctxt);
23568 if (attr == NULL) {
23569 VERROR_INT("xmlSchemaPushAttribute",
23570 "calling xmlSchemaGetFreshAttrInfo()");
23571 return (-1);
23572 }
23573 attr->node = attrNode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023574 attr->nodeLine = nodeLine;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023575 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23576 attr->localName = localName;
23577 attr->nsName = nsName;
23578 if (ownedNames)
23579 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23580 /*
23581 * Evaluate if it's an XSI attribute.
23582 */
23583 if (nsName != NULL) {
23584 if (xmlStrEqual(localName, BAD_CAST "nil")) {
23585 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23586 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23587 }
23588 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
23589 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23590 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23591 }
23592 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23593 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23594 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23595 }
23596 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23597 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23598 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23599 }
23600 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
23601 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
23602 }
23603 }
23604 attr->value = value;
23605 if (ownedValue)
23606 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23607 if (attr->metaType != 0)
23608 attr->state = XML_SCHEMAS_ATTR_META;
23609 return (0);
23610}
23611
23612static void
23613xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
23614{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023615 ielem->hasKeyrefs = 0;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000023616 ielem->appliedXPath = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023617 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
23618 FREE_AND_NULL(ielem->localName);
23619 FREE_AND_NULL(ielem->nsName);
23620 } else {
23621 ielem->localName = NULL;
23622 ielem->nsName = NULL;
23623 }
23624 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
23625 FREE_AND_NULL(ielem->value);
23626 } else {
23627 ielem->value = NULL;
23628 }
23629 if (ielem->val != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023630 /*
23631 * PSVI TODO: Be careful not to free it when the value is
23632 * exposed via PSVI.
23633 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023634 xmlSchemaFreeValue(ielem->val);
23635 ielem->val = NULL;
23636 }
23637 if (ielem->idcMatchers != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023638 /*
23639 * URGENT OPTIMIZE TODO: Use a pool of IDC matchers.
23640 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023641 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
23642 ielem->idcMatchers = NULL;
23643 }
23644 if (ielem->idcTable != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023645 /*
23646 * OPTIMIZE TODO: Use a pool of IDC tables??.
23647 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023648 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
23649 ielem->idcTable = NULL;
23650 }
23651 if (ielem->regexCtxt != NULL) {
23652 xmlRegFreeExecCtxt(ielem->regexCtxt);
23653 ielem->regexCtxt = NULL;
23654 }
23655 if (ielem->nsBindings != NULL) {
23656 xmlFree((xmlChar **)ielem->nsBindings);
23657 ielem->nsBindings = NULL;
23658 ielem->nbNsBindings = 0;
23659 ielem->sizeNsBindings = 0;
23660 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023661}
23662
23663/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023664 * xmlSchemaGetFreshElemInfo:
23665 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023666 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023667 * Creates/reuses and initializes the element info item for
23668 * the currect tree depth.
23669 *
23670 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023671 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023672static xmlSchemaNodeInfoPtr
23673xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023674{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023675 xmlSchemaNodeInfoPtr info = NULL;
23676
23677 if (vctxt->depth > vctxt->sizeElemInfos) {
23678 VERROR_INT("xmlSchemaGetFreshElemInfo",
23679 "inconsistent depth encountered");
23680 return (NULL);
23681 }
23682 if (vctxt->elemInfos == NULL) {
23683 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
23684 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
23685 if (vctxt->elemInfos == NULL) {
23686 xmlSchemaVErrMemory(vctxt,
23687 "allocating the element info array", NULL);
23688 return (NULL);
23689 }
23690 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
23691 vctxt->sizeElemInfos = 10;
23692 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
23693 int i = vctxt->sizeElemInfos;
23694
23695 vctxt->sizeElemInfos *= 2;
23696 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
23697 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
23698 sizeof(xmlSchemaNodeInfoPtr));
23699 if (vctxt->elemInfos == NULL) {
23700 xmlSchemaVErrMemory(vctxt,
23701 "re-allocating the element info array", NULL);
23702 return (NULL);
23703 }
23704 /*
23705 * We need the new memory to be NULLed.
23706 * TODO: Use memset instead?
23707 */
23708 for (; i < vctxt->sizeElemInfos; i++)
23709 vctxt->elemInfos[i] = NULL;
23710 } else
23711 info = vctxt->elemInfos[vctxt->depth];
23712
23713 if (info == NULL) {
23714 info = (xmlSchemaNodeInfoPtr)
23715 xmlMalloc(sizeof(xmlSchemaNodeInfo));
23716 if (info == NULL) {
23717 xmlSchemaVErrMemory(vctxt,
23718 "allocating an element info", NULL);
23719 return (NULL);
23720 }
23721 vctxt->elemInfos[vctxt->depth] = info;
23722 } else {
23723 if (info->localName != NULL) {
23724 VERROR_INT("xmlSchemaGetFreshElemInfo",
23725 "elem info has not been cleared");
23726 return (NULL);
23727 }
23728 }
23729 memset(info, 0, sizeof(xmlSchemaNodeInfo));
23730 info->nodeType = XML_ELEMENT_NODE;
23731 info->depth = vctxt->depth;
23732
23733 return (info);
23734}
23735
23736#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
23737#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
23738#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
23739
23740static int
23741xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
23742 xmlNodePtr node,
23743 xmlSchemaTypePtr type,
23744 xmlSchemaValType valType,
23745 const xmlChar * value,
23746 xmlSchemaValPtr val,
23747 unsigned long length,
23748 int fireErrors)
23749{
23750 int ret, error = 0;
23751
23752 xmlSchemaTypePtr tmpType;
23753 xmlSchemaFacetLinkPtr facetLink;
23754 xmlSchemaFacetPtr facet;
23755 unsigned long len = 0;
23756 xmlSchemaWhitespaceValueType ws;
23757
23758 /*
23759 * In Libxml2, derived built-in types have currently no explicit facets.
23760 */
23761 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023762 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023763
23764 /*
23765 * NOTE: Do not jump away, if the facetSet of the given type is
23766 * empty: until now, "pattern" and "enumeration" facets of the
23767 * *base types* need to be checked as well.
23768 */
23769 if (type->facetSet == NULL)
23770 goto pattern_and_enum;
23771
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023772 if (! WXS_IS_ATOMIC(type)) {
23773 if (WXS_IS_LIST(type))
23774 goto WXS_IS_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023775 else
23776 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023777 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023778 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023779 * Whitespace handling is only of importance for string-based
23780 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023781 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023782 tmpType = xmlSchemaGetPrimitiveType(type);
23783 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023784 WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023785 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
23786 } else
23787 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
23788 /*
23789 * If the value was not computed (for string or
23790 * anySimpleType based types), then use the provided
23791 * type.
23792 */
23793 if (val == NULL)
23794 valType = valType;
23795 else
23796 valType = xmlSchemaGetValType(val);
23797
23798 ret = 0;
23799 for (facetLink = type->facetSet; facetLink != NULL;
23800 facetLink = facetLink->next) {
23801 /*
23802 * Skip the pattern "whiteSpace": it is used to
23803 * format the character content beforehand.
23804 */
23805 switch (facetLink->facet->type) {
23806 case XML_SCHEMA_FACET_WHITESPACE:
23807 case XML_SCHEMA_FACET_PATTERN:
23808 case XML_SCHEMA_FACET_ENUMERATION:
23809 continue;
23810 case XML_SCHEMA_FACET_LENGTH:
23811 case XML_SCHEMA_FACET_MINLENGTH:
23812 case XML_SCHEMA_FACET_MAXLENGTH:
23813 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
23814 valType, value, val, &len, ws);
23815 break;
23816 default:
23817 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
23818 valType, value, val, ws);
23819 break;
23820 }
23821 if (ret < 0) {
23822 AERROR_INT("xmlSchemaValidateFacets",
23823 "validating against a atomic type facet");
23824 return (-1);
23825 } else if (ret > 0) {
23826 if (fireErrors)
23827 xmlSchemaFacetErr(actxt, ret, node,
23828 value, len, type, facetLink->facet, NULL, NULL, NULL);
23829 else
23830 return (ret);
23831 if (error == 0)
23832 error = ret;
23833 }
23834 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023835 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023836
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023837WXS_IS_LIST:
23838 if (! WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023839 goto pattern_and_enum;
23840 /*
23841 * "length", "minLength" and "maxLength" of list types.
23842 */
23843 ret = 0;
23844 for (facetLink = type->facetSet; facetLink != NULL;
23845 facetLink = facetLink->next) {
23846
23847 switch (facetLink->facet->type) {
23848 case XML_SCHEMA_FACET_LENGTH:
23849 case XML_SCHEMA_FACET_MINLENGTH:
23850 case XML_SCHEMA_FACET_MAXLENGTH:
23851 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
23852 value, length, NULL);
23853 break;
23854 default:
23855 continue;
23856 }
23857 if (ret < 0) {
23858 AERROR_INT("xmlSchemaValidateFacets",
23859 "validating against a list type facet");
23860 return (-1);
23861 } else if (ret > 0) {
23862 if (fireErrors)
23863 xmlSchemaFacetErr(actxt, ret, node,
23864 value, length, type, facetLink->facet, NULL, NULL, NULL);
23865 else
23866 return (ret);
23867 if (error == 0)
23868 error = ret;
23869 }
23870 ret = 0;
23871 }
23872
23873pattern_and_enum:
23874 if (error >= 0) {
23875 int found = 0;
23876 /*
23877 * Process enumerations. Facet values are in the value space
23878 * of the defining type's base type. This seems to be a bug in the
23879 * XML Schema 1.0 spec. Use the whitespace type of the base type.
23880 * Only the first set of enumerations in the ancestor-or-self axis
23881 * is used for validation.
23882 */
23883 ret = 0;
23884 tmpType = type;
23885 do {
23886 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
23887 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
23888 continue;
23889 found = 1;
23890 ret = xmlSchemaAreValuesEqual(facet->val, val);
23891 if (ret == 1)
23892 break;
23893 else if (ret < 0) {
23894 AERROR_INT("xmlSchemaValidateFacets",
23895 "validating against an enumeration facet");
23896 return (-1);
23897 }
23898 }
23899 if (ret != 0)
23900 break;
23901 tmpType = tmpType->baseType;
23902 } while ((tmpType != NULL) &&
23903 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
23904 if (found && (ret == 0)) {
23905 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
23906 if (fireErrors) {
23907 xmlSchemaFacetErr(actxt, ret, node,
23908 value, 0, type, NULL, NULL, NULL, NULL);
23909 } else
23910 return (ret);
23911 if (error == 0)
23912 error = ret;
23913 }
23914 }
23915
23916 if (error >= 0) {
23917 int found;
23918 /*
23919 * Process patters. Pattern facets are ORed at type level
23920 * and ANDed if derived. Walk the base type axis.
23921 */
23922 tmpType = type;
23923 facet = NULL;
23924 do {
23925 found = 0;
23926 for (facetLink = tmpType->facetSet; facetLink != NULL;
23927 facetLink = facetLink->next) {
23928 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
23929 continue;
23930 found = 1;
23931 /*
23932 * NOTE that for patterns, @value needs to be the
23933 * normalized vaule.
23934 */
23935 ret = xmlRegexpExec(facetLink->facet->regexp, value);
23936 if (ret == 1)
23937 break;
23938 else if (ret < 0) {
23939 AERROR_INT("xmlSchemaValidateFacets",
23940 "validating against a pattern facet");
23941 return (-1);
23942 } else {
23943 /*
23944 * Save the last non-validating facet.
23945 */
23946 facet = facetLink->facet;
23947 }
23948 }
23949 if (found && (ret != 1)) {
23950 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
23951 if (fireErrors) {
23952 xmlSchemaFacetErr(actxt, ret, node,
23953 value, 0, type, facet, NULL, NULL, NULL);
23954 } else
23955 return (ret);
23956 if (error == 0)
23957 error = ret;
23958 break;
23959 }
23960 tmpType = tmpType->baseType;
23961 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
23962 }
23963
23964 return (error);
23965}
23966
23967static xmlChar *
23968xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
23969 const xmlChar *value)
23970{
23971 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
23972 case XML_SCHEMA_WHITESPACE_COLLAPSE:
23973 return (xmlSchemaCollapseString(value));
23974 case XML_SCHEMA_WHITESPACE_REPLACE:
23975 return (xmlSchemaWhiteSpaceReplace(value));
23976 default:
23977 return (NULL);
23978 }
23979}
23980
23981static int
23982xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
23983 const xmlChar *value,
23984 xmlSchemaValPtr *val,
23985 int valNeeded)
23986{
23987 int ret;
23988 const xmlChar *nsName;
23989 xmlChar *local, *prefix = NULL;
23990
23991 ret = xmlValidateQName(value, 1);
23992 if (ret != 0) {
23993 if (ret == -1) {
23994 VERROR_INT("xmlSchemaValidateQName",
23995 "calling xmlValidateQName()");
23996 return (-1);
23997 }
23998 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
23999 }
24000 /*
24001 * NOTE: xmlSplitQName2 will always return a duplicated
24002 * strings.
24003 */
24004 local = xmlSplitQName2(value, &prefix);
24005 if (local == NULL)
24006 local = xmlStrdup(value);
24007 /*
24008 * OPTIMIZE TODO: Use flags for:
24009 * - is there any namespace binding?
24010 * - is there a default namespace?
24011 */
24012 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24013
24014 if (prefix != NULL) {
24015 xmlFree(prefix);
24016 /*
24017 * A namespace must be found if the prefix is
24018 * NOT NULL.
24019 */
24020 if (nsName == NULL) {
24021 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024022 xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024023 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024024 "The QName value '%s' has no "
24025 "corresponding namespace declaration in "
24026 "scope", value, NULL);
24027 if (local != NULL)
24028 xmlFree(local);
24029 return (ret);
24030 }
24031 }
24032 if (valNeeded && val) {
24033 if (nsName != NULL)
24034 *val = xmlSchemaNewQNameValue(
24035 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24036 else
24037 *val = xmlSchemaNewQNameValue(NULL,
24038 BAD_CAST local);
24039 } else
24040 xmlFree(local);
24041 return (0);
24042}
24043
24044/*
24045* cvc-simple-type
24046*/
24047static int
24048xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24049 xmlNodePtr node,
24050 xmlSchemaTypePtr type,
24051 const xmlChar *value,
24052 xmlSchemaValPtr *retVal,
24053 int fireErrors,
24054 int normalize,
24055 int isNormalized)
24056{
24057 int ret = 0, valNeeded = (retVal) ? 1 : 0;
24058 xmlSchemaValPtr val = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024059 /* xmlSchemaWhitespaceValueType ws; */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024060 xmlChar *normValue = NULL;
24061
24062#define NORMALIZE(atype) \
24063 if ((! isNormalized) && \
24064 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24065 normValue = xmlSchemaNormalizeValue(atype, value); \
24066 if (normValue != NULL) \
24067 value = normValue; \
24068 isNormalized = 1; \
24069 }
24070
24071 if ((retVal != NULL) && (*retVal != NULL)) {
24072 xmlSchemaFreeValue(*retVal);
24073 *retVal = NULL;
24074 }
24075 /*
24076 * 3.14.4 Simple Type Definition Validation Rules
24077 * Validation Rule: String Valid
24078 */
24079 /*
24080 * 1 It is schema-valid with respect to that definition as defined
24081 * by Datatype Valid in [XML Schemas: Datatypes].
24082 */
24083 /*
24084 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24085 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
24086 * the string must be a ·declared entity name·.
24087 */
24088 /*
24089 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24090 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
24091 * then every whitespace-delimited substring of the string must be a ·declared
24092 * entity name·.
24093 */
24094 /*
24095 * 2.3 otherwise no further condition applies.
24096 */
24097 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24098 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000024099 if (value == NULL)
24100 value = BAD_CAST "";
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024101 if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024102 xmlSchemaTypePtr biType; /* The built-in type. */
24103 /*
24104 * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match·
24105 * a literal in the ·lexical space· of {base type definition}"
24106 */
24107 /*
24108 * Whitespace-normalize.
24109 */
24110 NORMALIZE(type);
24111 if (type->type != XML_SCHEMA_TYPE_BASIC) {
24112 /*
24113 * Get the built-in type.
24114 */
24115 biType = type->baseType;
24116 while ((biType != NULL) &&
24117 (biType->type != XML_SCHEMA_TYPE_BASIC))
24118 biType = biType->baseType;
24119
24120 if (biType == NULL) {
24121 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24122 "could not get the built-in type");
24123 goto internal_error;
24124 }
24125 } else
24126 biType = type;
24127 /*
24128 * NOTATIONs need to be processed here, since they need
24129 * to lookup in the hashtable of NOTATION declarations of the schema.
24130 */
24131 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24132 switch (biType->builtInType) {
24133 case XML_SCHEMAS_NOTATION:
24134 ret = xmlSchemaValidateNotation(
24135 (xmlSchemaValidCtxtPtr) actxt,
24136 ((xmlSchemaValidCtxtPtr) actxt)->schema,
24137 NULL, value, &val, valNeeded);
24138 break;
24139 case XML_SCHEMAS_QNAME:
24140 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24141 value, &val, valNeeded);
24142 break;
24143 default:
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024144 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024145 if (valNeeded)
24146 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24147 value, &val, NULL);
24148 else
24149 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24150 value, NULL, NULL);
24151 break;
24152 }
24153 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24154 switch (biType->builtInType) {
24155 case XML_SCHEMAS_NOTATION:
24156 ret = xmlSchemaValidateNotation(NULL,
24157 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24158 value, &val, valNeeded);
24159 break;
24160 default:
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024161 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024162 if (valNeeded)
24163 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24164 value, &val, node);
24165 else
24166 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24167 value, NULL, node);
24168 break;
24169 }
24170 } else {
24171 /*
24172 * Validation via a public API is not implemented yet.
24173 */
24174 TODO
24175 goto internal_error;
24176 }
24177 if (ret != 0) {
24178 if (ret < 0) {
24179 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24180 "validating against a built-in type");
24181 goto internal_error;
24182 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024183 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024184 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24185 else
24186 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24187 }
24188 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24189 /*
24190 * Check facets.
24191 */
24192 ret = xmlSchemaValidateFacets(actxt, node, type,
24193 (xmlSchemaValType) biType->builtInType, value, val,
24194 0, fireErrors);
24195 if (ret != 0) {
24196 if (ret < 0) {
24197 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24198 "validating facets of atomic simple type");
24199 goto internal_error;
24200 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024201 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024202 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24203 else
24204 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24205 }
24206 }
24207 if (fireErrors && (ret > 0))
24208 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024209 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024210
24211 xmlSchemaTypePtr itemType;
24212 const xmlChar *cur, *end;
24213 xmlChar *tmpValue = NULL;
24214 unsigned long len = 0;
24215 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24216 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
24217 * of white space separated tokens, each of which ·match·es a literal
24218 * in the ·lexical space· of {item type definition}
24219 */
24220 /*
24221 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24222 * the list type has an enum or pattern facet.
24223 */
24224 NORMALIZE(type);
24225 /*
24226 * VAL TODO: Optimize validation of empty values.
24227 * VAL TODO: We do not have computed values for lists.
24228 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024229 itemType = WXS_LIST_ITEMTYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024230 cur = value;
24231 do {
24232 while (IS_BLANK_CH(*cur))
24233 cur++;
24234 end = cur;
24235 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24236 end++;
24237 if (end == cur)
24238 break;
24239 tmpValue = xmlStrndup(cur, end - cur);
24240 len++;
24241
24242 if (valNeeded)
24243 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24244 tmpValue, &curVal, fireErrors, 0, 1);
24245 else
24246 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24247 tmpValue, NULL, fireErrors, 0, 1);
24248 FREE_AND_NULL(tmpValue);
24249 if (curVal != NULL) {
24250 /*
24251 * Add to list of computed values.
24252 */
24253 if (val == NULL)
24254 val = curVal;
24255 else
24256 xmlSchemaValueAppend(prevVal, curVal);
24257 prevVal = curVal;
24258 curVal = NULL;
24259 }
24260 if (ret != 0) {
24261 if (ret < 0) {
24262 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24263 "validating an item of list simple type");
24264 goto internal_error;
24265 }
24266 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24267 break;
24268 }
24269 cur = end;
24270 } while (*cur != 0);
24271 FREE_AND_NULL(tmpValue);
24272 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24273 /*
24274 * Apply facets (pattern, enumeration).
24275 */
24276 ret = xmlSchemaValidateFacets(actxt, node, type,
24277 XML_SCHEMAS_UNKNOWN, value, val,
24278 len, fireErrors);
24279 if (ret != 0) {
24280 if (ret < 0) {
24281 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24282 "validating facets of list simple type");
24283 goto internal_error;
24284 }
24285 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24286 }
24287 }
24288 if (fireErrors && (ret > 0)) {
24289 /*
24290 * Report the normalized value.
24291 */
24292 normalize = 1;
24293 NORMALIZE(type);
24294 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24295 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024296 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024297 xmlSchemaTypeLinkPtr memberLink;
24298 /*
24299 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
24300 * not apply directly; however, the normalization behavior of ·union·
24301 * types is controlled by the value of whiteSpace on that one of the
24302 * ·memberTypes· against which the ·union· is successfully validated.
24303 *
24304 * This means that the value is normalized by the first validating
24305 * member type, then the facets of the union type are applied. This
24306 * needs changing of the value!
24307 */
24308
24309 /*
24310 * 1.2.3 if {variety} is ·union· then the string must ·match· a
24311 * literal in the ·lexical space· of at least one member of
24312 * {member type definitions}
24313 */
24314 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24315 if (memberLink == NULL) {
24316 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24317 "union simple type has no member types");
24318 goto internal_error;
24319 }
24320 /*
24321 * Always normalize union type values, since we currently
24322 * cannot store the whitespace information with the value
24323 * itself; otherwise a later value-comparison would be
24324 * not possible.
24325 */
24326 while (memberLink != NULL) {
24327 if (valNeeded)
24328 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24329 memberLink->type, value, &val, 0, 1, 0);
24330 else
24331 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24332 memberLink->type, value, NULL, 0, 1, 0);
24333 if (ret <= 0)
24334 break;
24335 memberLink = memberLink->next;
24336 }
24337 if (ret != 0) {
24338 if (ret < 0) {
24339 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24340 "validating members of union simple type");
24341 goto internal_error;
24342 }
24343 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24344 }
24345 /*
24346 * Apply facets (pattern, enumeration).
24347 */
24348 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24349 /*
24350 * The normalization behavior of ·union· types is controlled by
24351 * the value of whiteSpace on that one of the ·memberTypes·
24352 * against which the ·union· is successfully validated.
24353 */
24354 NORMALIZE(memberLink->type);
24355 ret = xmlSchemaValidateFacets(actxt, node, type,
24356 XML_SCHEMAS_UNKNOWN, value, val,
24357 0, fireErrors);
24358 if (ret != 0) {
24359 if (ret < 0) {
24360 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24361 "validating facets of union simple type");
24362 goto internal_error;
24363 }
24364 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24365 }
24366 }
24367 if (fireErrors && (ret > 0))
24368 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24369 }
24370
24371 if (normValue != NULL)
24372 xmlFree(normValue);
24373 if (ret == 0) {
24374 if (retVal != NULL)
24375 *retVal = val;
24376 else if (val != NULL)
24377 xmlSchemaFreeValue(val);
24378 } else if (val != NULL)
24379 xmlSchemaFreeValue(val);
24380 return (ret);
24381internal_error:
24382 if (normValue != NULL)
24383 xmlFree(normValue);
24384 if (val != NULL)
24385 xmlSchemaFreeValue(val);
24386 return (-1);
24387}
24388
24389static int
24390xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24391 const xmlChar *value,
24392 const xmlChar **nsName,
24393 const xmlChar **localName)
24394{
24395 int ret = 0;
24396
24397 if ((nsName == NULL) || (localName == NULL))
24398 return (-1);
24399 *nsName = NULL;
24400 *localName = NULL;
24401
24402 ret = xmlValidateQName(value, 1);
24403 if (ret == -1)
24404 return (-1);
24405 if (ret > 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024406 xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024407 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24408 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24409 return (1);
24410 }
24411 {
24412 xmlChar *local = NULL;
24413 xmlChar *prefix;
24414
24415 /*
24416 * NOTE: xmlSplitQName2 will return a duplicated
24417 * string.
24418 */
24419 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024420 if (local == NULL)
24421 *localName = xmlDictLookup(vctxt->dict, value, -1);
24422 else {
24423 *localName = xmlDictLookup(vctxt->dict, local, -1);
24424 xmlFree(local);
24425 }
24426
24427 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24428
24429 if (prefix != NULL) {
24430 xmlFree(prefix);
24431 /*
24432 * A namespace must be found if the prefix is NOT NULL.
24433 */
24434 if (*nsName == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024435 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024436 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024437 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024438 "The QName value '%s' has no "
24439 "corresponding namespace declaration in scope",
24440 value, NULL);
24441 return (2);
24442 }
24443 }
24444 }
24445 return (0);
24446}
24447
24448static int
24449xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24450 xmlSchemaAttrInfoPtr iattr,
24451 xmlSchemaTypePtr *localType,
24452 xmlSchemaElementPtr elemDecl)
24453{
24454 int ret = 0;
24455 /*
24456 * cvc-elt (3.3.4) : (4)
24457 * AND
24458 * Schema-Validity Assessment (Element) (cvc-assess-elt)
24459 * (1.2.1.2.1) - (1.2.1.2.4)
24460 * Handle 'xsi:type'.
24461 */
24462 if (localType == NULL)
24463 return (-1);
24464 *localType = NULL;
24465 if (iattr == NULL)
24466 return (0);
24467 else {
24468 const xmlChar *nsName = NULL, *local = NULL;
24469 /*
24470 * TODO: We should report a *warning* that the type was overriden
24471 * by the instance.
24472 */
24473 ACTIVATE_ATTRIBUTE(iattr);
24474 /*
24475 * (cvc-elt) (3.3.4) : (4.1)
24476 * (cvc-assess-elt) (1.2.1.2.2)
24477 */
24478 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24479 &nsName, &local);
24480 if (ret != 0) {
24481 if (ret < 0) {
24482 VERROR_INT("xmlSchemaValidateElementByDeclaration",
24483 "calling xmlSchemaQNameExpand() to validate the "
24484 "attribute 'xsi:type'");
24485 goto internal_error;
24486 }
24487 goto exit;
24488 }
24489 /*
24490 * (cvc-elt) (3.3.4) : (4.2)
24491 * (cvc-assess-elt) (1.2.1.2.3)
24492 */
24493 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24494 if (*localType == NULL) {
24495 xmlChar *str = NULL;
24496
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024497 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024498 XML_SCHEMAV_CVC_ELT_4_2, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024499 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024500 "The QName value '%s' of the xsi:type attribute does not "
24501 "resolve to a type definition",
24502 xmlSchemaFormatQName(&str, nsName, local), NULL);
24503 FREE_AND_NULL(str);
24504 ret = vctxt->err;
24505 goto exit;
24506 }
24507 if (elemDecl != NULL) {
24508 int set = 0;
24509
24510 /*
24511 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24512 * "The ·local type definition· must be validly
24513 * derived from the {type definition} given the union of
24514 * the {disallowed substitutions} and the {type definition}'s
24515 * {prohibited substitutions}, as defined in
24516 * Type Derivation OK (Complex) (§3.4.6)
24517 * (if it is a complex type definition),
24518 * or given {disallowed substitutions} as defined in Type
24519 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
24520 * definition)."
24521 *
24522 * {disallowed substitutions}: the "block" on the element decl.
24523 * {prohibited substitutions}: the "block" on the type def.
24524 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000024525 /*
24526 * OPTIMIZE TODO: We could map types already evaluated
24527 * to be validly derived from other types to avoid checking
24528 * this over and over for the same types.
24529 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024530 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24531 (elemDecl->subtypes->flags &
24532 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24533 set |= SUBSET_EXTENSION;
24534
24535 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24536 (elemDecl->subtypes->flags &
24537 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24538 set |= SUBSET_RESTRICTION;
24539
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000024540 /*
24541 * REMOVED and CHANGED since this produced a parser context
24542 * which adds to the string dict of the schema. So this would
24543 * change the schema and we don't want this. We don't need
24544 * the parser context anymore.
24545 *
24546 * if ((vctxt->pctxt == NULL) &&
24547 * (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24548 * return (-1);
24549 */
24550
24551 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024552 elemDecl->subtypes, set) != 0) {
24553 xmlChar *str = NULL;
24554
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024555 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024556 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24557 "The type definition '%s', specified by xsi:type, is "
24558 "blocked or not validly derived from the type definition "
24559 "of the element declaration",
24560 xmlSchemaFormatQName(&str,
24561 (*localType)->targetNamespace,
24562 (*localType)->name),
24563 NULL);
24564 FREE_AND_NULL(str);
24565 ret = vctxt->err;
24566 *localType = NULL;
24567 }
24568 }
24569 }
24570exit:
24571 ACTIVATE_ELEM;
24572 return (ret);
24573internal_error:
24574 ACTIVATE_ELEM;
24575 return (-1);
24576}
24577
24578static int
24579xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24580{
24581 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024582 xmlSchemaTypePtr actualType = WXS_ELEM_TYPEDEF(elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024583
24584 /*
24585 * cvc-elt (3.3.4) : 1
24586 */
24587 if (elemDecl == NULL) {
24588 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
24589 "No matching declaration available");
24590 return (vctxt->err);
24591 }
24592 /*
24593 * cvc-elt (3.3.4) : 2
24594 */
24595 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
24596 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
24597 "The element declaration is abstract");
24598 return (vctxt->err);
24599 }
24600 if (actualType == NULL) {
24601 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24602 "The type definition is absent");
24603 return (XML_SCHEMAV_CVC_TYPE_1);
24604 }
24605 if (vctxt->nbAttrInfos != 0) {
24606 int ret;
24607 xmlSchemaAttrInfoPtr iattr;
24608 /*
24609 * cvc-elt (3.3.4) : 3
24610 * Handle 'xsi:nil'.
24611 */
24612 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24613 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
24614 if (iattr) {
24615 ACTIVATE_ATTRIBUTE(iattr);
24616 /*
24617 * Validate the value.
24618 */
24619 ret = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024620 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024621 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
24622 iattr->value, &(iattr->val), 1, 0, 0);
24623 ACTIVATE_ELEM;
24624 if (ret < 0) {
24625 VERROR_INT("xmlSchemaValidateElemDecl",
24626 "calling xmlSchemaVCheckCVCSimpleType() to "
24627 "validate the attribute 'xsi:nil'");
24628 return (-1);
24629 }
24630 if (ret == 0) {
24631 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
24632 /*
24633 * cvc-elt (3.3.4) : 3.1
24634 */
24635 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
24636 "The element is not 'nillable'");
24637 /* Does not return an error on purpose. */
24638 } else {
24639 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
24640 /*
24641 * cvc-elt (3.3.4) : 3.2.2
24642 */
24643 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
24644 (elemDecl->value != NULL)) {
24645 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
24646 "The element cannot be 'nilled' because "
24647 "there is a fixed value constraint defined "
24648 "for it");
24649 /* Does not return an error on purpose. */
24650 } else
24651 vctxt->inode->flags |=
24652 XML_SCHEMA_ELEM_INFO_NILLED;
24653 }
24654 }
24655 }
24656 }
24657 /*
24658 * cvc-elt (3.3.4) : 4
24659 * Handle 'xsi:type'.
24660 */
24661 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24662 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
24663 if (iattr) {
24664 xmlSchemaTypePtr localType = NULL;
24665
24666 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
24667 elemDecl);
24668 if (ret != 0) {
24669 if (ret == -1) {
24670 VERROR_INT("xmlSchemaValidateElemDecl",
24671 "calling xmlSchemaProcessXSIType() to "
24672 "process the attribute 'xsi:type'");
24673 return (-1);
24674 }
24675 /* Does not return an error on purpose. */
24676 }
24677 if (localType != NULL) {
24678 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
24679 actualType = localType;
24680 }
24681 }
24682 }
24683 /*
24684 * IDC: Register identity-constraint XPath matchers.
24685 */
24686 if ((elemDecl->idcs != NULL) &&
24687 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
24688 return (-1);
24689 /*
24690 * No actual type definition.
24691 */
24692 if (actualType == NULL) {
24693 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24694 "The type definition is absent");
24695 return (XML_SCHEMAV_CVC_TYPE_1);
24696 }
24697 /*
24698 * Remember the actual type definition.
24699 */
24700 vctxt->inode->typeDef = actualType;
24701
24702 return (0);
24703}
24704
24705static int
24706xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
24707{
24708 xmlSchemaAttrInfoPtr iattr;
24709 int ret = 0, i;
24710
24711 /*
24712 * SPEC cvc-type (3.1.1)
24713 * "The attributes of must be empty, excepting those whose namespace
24714 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
24715 * whose local name is one of type, nil, schemaLocation or
24716 * noNamespaceSchemaLocation."
24717 */
24718 if (vctxt->nbAttrInfos == 0)
24719 return (0);
24720 for (i = 0; i < vctxt->nbAttrInfos; i++) {
24721 iattr = vctxt->attrInfos[i];
24722 if (! iattr->metaType) {
24723 ACTIVATE_ATTRIBUTE(iattr)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024724 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024725 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
24726 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
24727 }
24728 }
24729 ACTIVATE_ELEM
24730 return (ret);
24731}
24732
24733/*
24734* Cleanup currently used attribute infos.
24735*/
24736static void
24737xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
24738{
24739 int i;
24740 xmlSchemaAttrInfoPtr attr;
24741
24742 if (vctxt->nbAttrInfos == 0)
24743 return;
24744 for (i = 0; i < vctxt->nbAttrInfos; i++) {
24745 attr = vctxt->attrInfos[i];
24746 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24747 if (attr->localName != NULL)
24748 xmlFree((xmlChar *) attr->localName);
24749 if (attr->nsName != NULL)
24750 xmlFree((xmlChar *) attr->nsName);
24751 }
24752 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24753 if (attr->value != NULL)
24754 xmlFree((xmlChar *) attr->value);
24755 }
24756 if (attr->val != NULL) {
24757 xmlSchemaFreeValue(attr->val);
24758 attr->val = NULL;
24759 }
24760 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
24761 }
24762 vctxt->nbAttrInfos = 0;
24763}
24764
24765/*
24766* 3.4.4 Complex Type Definition Validation Rules
24767* Element Locally Valid (Complex Type) (cvc-complex-type)
24768* 3.2.4 Attribute Declaration Validation Rules
24769* Validation Rule: Attribute Locally Valid (cvc-attribute)
24770* Attribute Locally Valid (Use) (cvc-au)
24771*
24772* Only "assessed" attribute information items will be visible to
24773* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
24774*/
24775static int
24776xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
24777{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024778 xmlSchemaTypePtr type = vctxt->inode->typeDef;
24779 xmlSchemaItemListPtr attrUseList;
24780 xmlSchemaAttributeUsePtr attrUse = NULL;
24781 xmlSchemaAttributePtr attrDecl = NULL;
24782 xmlSchemaAttrInfoPtr iattr, tmpiattr;
24783 int i, j, found, nbAttrs, nbUses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024784 int xpathRes = 0, res, wildIDs = 0, fixed;
24785
24786 /*
24787 * SPEC (cvc-attribute)
24788 * (1) "The declaration must not be ·absent· (see Missing
24789 * Sub-components (§5.3) for how this can fail to be
24790 * the case)."
24791 * (2) "Its {type definition} must not be absent."
24792 *
24793 * NOTE (1) + (2): This is not handled here, since we currently do not
24794 * allow validation against schemas which have missing sub-components.
24795 *
24796 * SPEC (cvc-complex-type)
24797 * (3) "For each attribute information item in the element information
24798 * item's [attributes] excepting those whose [namespace name] is
24799 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
24800 * [local name] is one of type, nil, schemaLocation or
24801 * noNamespaceSchemaLocation, the appropriate case among the following
24802 * must be true:
24803 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024804 */
24805 attrUseList = (xmlSchemaItemListPtr) type->attrUses;
24806 /*
24807 * @nbAttrs is the number of attributes present in the instance.
24808 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024809 nbAttrs = vctxt->nbAttrInfos;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024810 if (attrUseList != NULL)
24811 nbUses = attrUseList->nbItems;
24812 else
24813 nbUses = 0;
24814 for (i = 0; i < nbUses; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024815 found = 0;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024816 attrUse = attrUseList->items[i];
24817 attrDecl = WXS_ATTRUSE_DECL(attrUse);
24818 for (j = 0; j < nbAttrs; j++) {
24819 iattr = vctxt->attrInfos[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024820 /*
24821 * SPEC (cvc-complex-type) (3)
24822 * Skip meta attributes.
24823 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024824 if (iattr->metaType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024825 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024826 if (iattr->localName[0] != attrDecl->name[0])
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024827 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024828 if (!xmlStrEqual(iattr->localName, attrDecl->name))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024829 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024830 if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024831 continue;
24832 found = 1;
24833 /*
24834 * SPEC (cvc-complex-type)
24835 * (3.1) "If there is among the {attribute uses} an attribute
24836 * use with an {attribute declaration} whose {name} matches
24837 * the attribute information item's [local name] and whose
24838 * {target namespace} is identical to the attribute information
24839 * item's [namespace name] (where an ·absent· {target namespace}
24840 * is taken to be identical to a [namespace name] with no value),
24841 * then the attribute information must be ·valid· with respect
24842 * to that attribute use as per Attribute Locally Valid (Use)
24843 * (§3.5.4). In this case the {attribute declaration} of that
24844 * attribute use is the ·context-determined declaration· for the
24845 * attribute information item with respect to Schema-Validity
24846 * Assessment (Attribute) (§3.2.4) and
24847 * Assessment Outcome (Attribute) (§3.2.5).
24848 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024849 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
24850 iattr->use = attrUse;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024851 /*
24852 * Context-determined declaration.
24853 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024854 iattr->decl = attrDecl;
24855 iattr->typeDef = attrDecl->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024856 break;
24857 }
24858
24859 if (found)
24860 continue;
24861
24862 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
24863 /*
24864 * Handle non-existent, required attributes.
24865 *
24866 * SPEC (cvc-complex-type)
24867 * (4) "The {attribute declaration} of each attribute use in
24868 * the {attribute uses} whose {required} is true matches one
24869 * of the attribute information items in the element information
24870 * item's [attributes] as per clause 3.1 above."
24871 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024872 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
24873 if (tmpiattr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024874 VERROR_INT(
24875 "xmlSchemaVAttributesComplex",
24876 "calling xmlSchemaGetFreshAttrInfo()");
24877 return (-1);
24878 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024879 tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
24880 tmpiattr->use = attrUse;
24881 tmpiattr->decl = attrDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024882 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
24883 ((attrUse->defValue != NULL) ||
24884 (attrDecl->defValue != NULL))) {
24885 /*
24886 * Handle non-existent, optional, default/fixed attributes.
24887 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024888 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
24889 if (tmpiattr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024890 VERROR_INT(
24891 "xmlSchemaVAttributesComplex",
24892 "calling xmlSchemaGetFreshAttrInfo()");
24893 return (-1);
24894 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024895 tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
24896 tmpiattr->use = attrUse;
24897 tmpiattr->decl = attrDecl;
24898 tmpiattr->typeDef = attrDecl->subtypes;
24899 tmpiattr->localName = attrDecl->name;
24900 tmpiattr->nsName = attrDecl->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024901 }
24902 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024903
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024904 if (vctxt->nbAttrInfos == 0)
24905 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024906 nbUses = vctxt->nbAttrInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024907 /*
24908 * Validate against the wildcard.
24909 */
24910 if (type->attributeWildcard != NULL) {
24911 /*
24912 * SPEC (cvc-complex-type)
24913 * (3.2.1) "There must be an {attribute wildcard}."
24914 */
24915 for (i = 0; i < nbAttrs; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024916 iattr = vctxt->attrInfos[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024917 /*
24918 * SPEC (cvc-complex-type) (3)
24919 * Skip meta attributes.
24920 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024921 if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024922 continue;
24923 /*
24924 * SPEC (cvc-complex-type)
24925 * (3.2.2) "The attribute information item must be ·valid· with
24926 * respect to it as defined in Item Valid (Wildcard) (§3.10.4)."
24927 *
24928 * SPEC Item Valid (Wildcard) (cvc-wildcard)
24929 * "... its [namespace name] must be ·valid· with respect to
24930 * the wildcard constraint, as defined in Wildcard allows
24931 * Namespace Name (§3.10.4)."
24932 */
24933 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024934 iattr->nsName) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024935 /*
24936 * Handle processContents.
24937 *
24938 * SPEC (cvc-wildcard):
24939 * processContents | context-determined declaration:
24940 * "strict" "mustFind"
24941 * "lax" "none"
24942 * "skip" "skip"
24943 */
24944 if (type->attributeWildcard->processContents ==
24945 XML_SCHEMAS_ANY_SKIP) {
24946 /*
24947 * context-determined declaration = "skip"
24948 *
24949 * SPEC PSVI Assessment Outcome (Attribute)
24950 * [validity] = "notKnown"
24951 * [validation attempted] = "none"
24952 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024953 iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024954 continue;
24955 }
24956 /*
24957 * Find an attribute declaration.
24958 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024959 iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
24960 iattr->localName, iattr->nsName);
24961 if (iattr->decl != NULL) {
24962 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024963 /*
24964 * SPEC (cvc-complex-type)
24965 * (5) "Let [Definition:] the wild IDs be the set of
24966 * all attribute information item to which clause 3.2
24967 * applied and whose ·validation· resulted in a
24968 * ·context-determined declaration· of mustFind or no
24969 * ·context-determined declaration· at all, and whose
24970 * [local name] and [namespace name] resolve (as
24971 * defined by QName resolution (Instance) (§3.15.4)) to
24972 * an attribute declaration whose {type definition} is
24973 * or is derived from ID. Then all of the following
24974 * must be true:"
24975 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024976 iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024977 if (xmlSchemaIsDerivedFromBuiltInType(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024978 iattr->typeDef, XML_SCHEMAS_ID)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024979 /*
24980 * SPEC (5.1) "There must be no more than one
24981 * item in ·wild IDs·."
24982 */
24983 if (wildIDs != 0) {
24984 /* VAL TODO */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024985 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024986 TODO
24987 continue;
24988 }
24989 wildIDs++;
24990 /*
24991 * SPEC (cvc-complex-type)
24992 * (5.2) "If ·wild IDs· is non-empty, there must not
24993 * be any attribute uses among the {attribute uses}
24994 * whose {attribute declaration}'s {type definition}
24995 * is or is derived from ID."
24996 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024997 for (j = 0; j < attrUseList->nbItems; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024998 if (xmlSchemaIsDerivedFromBuiltInType(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024999 WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025000 XML_SCHEMAS_ID)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025001 /* URGENT VAL TODO: implement */
25002 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025003 TODO
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025004 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025005 }
25006 }
25007 }
25008 } else if (type->attributeWildcard->processContents ==
25009 XML_SCHEMAS_ANY_LAX) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025010 iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025011 /*
25012 * SPEC PSVI Assessment Outcome (Attribute)
25013 * [validity] = "notKnown"
25014 * [validation attempted] = "none"
25015 */
25016 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025017 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025018 }
25019 }
25020 }
25021 }
25022
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025023 if (vctxt->nbAttrInfos == 0)
25024 return (0);
25025
25026 /*
25027 * Validate values, create default attributes, evaluate IDCs.
25028 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025029 for (i = 0; i < vctxt->nbAttrInfos; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025030 iattr = vctxt->attrInfos[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025031 /*
25032 * VAL TODO: Note that we won't try to resolve IDCs to
25033 * "lax" and "skip" validated attributes. Check what to
25034 * do in this case.
25035 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025036 if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25037 (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025038 continue;
25039 /*
25040 * VAL TODO: What to do if the type definition is missing?
25041 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025042 if (iattr->typeDef == NULL) {
25043 iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025044 continue;
25045 }
25046
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025047 ACTIVATE_ATTRIBUTE(iattr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000025048 fixed = 0;
25049 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025050
25051 if (vctxt->xpathStates != NULL) {
25052 /*
25053 * Evaluate IDCs.
25054 */
25055 xpathRes = xmlSchemaXPathEvaluate(vctxt,
25056 XML_ATTRIBUTE_NODE);
25057 if (xpathRes == -1) {
25058 VERROR_INT("xmlSchemaVAttributesComplex",
25059 "calling xmlSchemaXPathEvaluate()");
25060 goto internal_error;
25061 }
25062 }
25063
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025064 if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025065 /*
25066 * Default/fixed attributes.
25067 */
25068 if (xpathRes) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025069 if (iattr->use->defValue != NULL) {
25070 iattr->value = (xmlChar *) iattr->use->defValue;
25071 iattr->val = iattr->use->defVal;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025072 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025073 iattr->value = (xmlChar *) iattr->decl->defValue;
25074 iattr->val = iattr->decl->defVal;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025075 }
25076 /*
25077 * IDCs will consume the precomputed default value,
25078 * so we need to clone it.
25079 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025080 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025081 VERROR_INT("xmlSchemaVAttributesComplex",
25082 "default/fixed value on an attribute use was "
25083 "not precomputed");
25084 goto internal_error;
25085 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025086 iattr->val = xmlSchemaCopyValue(iattr->val);
25087 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025088 VERROR_INT("xmlSchemaVAttributesComplex",
25089 "calling xmlSchemaCopyValue()");
25090 goto internal_error;
25091 }
25092 }
25093 /*
25094 * PSVI: Add the default attribute to the current element.
25095 * VAL TODO: Should we use the *normalized* value? This currently
25096 * uses the *initial* value.
25097 */
25098 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025099 (iattr->node != NULL) && (iattr->node->doc != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025100 xmlChar *normValue;
25101 const xmlChar *value;
25102
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025103 value = iattr->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025104 /*
25105 * Normalize the value.
25106 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025107 normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25108 iattr->value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025109 if (normValue != NULL)
25110 value = BAD_CAST normValue;
25111
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025112 if (iattr->nsName == NULL) {
25113 if (xmlNewProp(iattr->node->parent,
25114 iattr->localName, value) == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025115 VERROR_INT("xmlSchemaVAttributesComplex",
25116 "callling xmlNewProp()");
25117 if (normValue != NULL)
25118 xmlFree(normValue);
25119 goto internal_error;
25120 }
25121 } else {
25122 xmlNsPtr ns;
25123
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025124 ns = xmlSearchNsByHref(iattr->node->doc,
25125 iattr->node->parent, iattr->nsName);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025126 if (ns == NULL) {
25127 xmlChar prefix[12];
25128 int counter = 0;
25129
25130 /*
25131 * Create a namespace declaration on the validation
25132 * root node if no namespace declaration is in scope.
25133 */
25134 do {
25135 snprintf((char *) prefix, 12, "p%d", counter++);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025136 ns = xmlSearchNs(iattr->node->doc,
25137 iattr->node->parent, BAD_CAST prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025138 if (counter > 1000) {
25139 VERROR_INT(
25140 "xmlSchemaVAttributesComplex",
25141 "could not compute a ns prefix for a "
25142 "default/fixed attribute");
25143 if (normValue != NULL)
25144 xmlFree(normValue);
25145 goto internal_error;
25146 }
25147 } while (ns != NULL);
25148 ns = xmlNewNs(vctxt->validationRoot,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025149 iattr->nsName, BAD_CAST prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025150 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025151 /*
25152 * TODO:
25153 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25154 * If we have QNames: do we need to ensure there's a
25155 * prefix defined for the QName?
25156 */
25157 xmlNewNsProp(iattr->node->parent, ns,
25158 iattr->localName, value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025159 }
25160 if (normValue != NULL)
25161 xmlFree(normValue);
25162 }
25163 /*
25164 * Go directly to IDC evaluation.
25165 */
25166 goto eval_idcs;
25167 }
25168 /*
25169 * Validate the value.
25170 */
25171 if (vctxt->value != NULL) {
25172 /*
25173 * Free last computed value; just for safety reasons.
25174 */
25175 xmlSchemaFreeValue(vctxt->value);
25176 vctxt->value = NULL;
25177 }
25178 /*
25179 * Note that the attribute *use* can be unavailable, if
25180 * the attribute was a wild attribute.
25181 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025182 if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25183 ((iattr->use != NULL) &&
25184 (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025185 fixed = 1;
25186 else
25187 fixed = 0;
25188 /*
25189 * SPEC (cvc-attribute)
25190 * (3) "The item's ·normalized value· must be locally ·valid·
25191 * with respect to that {type definition} as per
25192 * String Valid (§3.14.4)."
25193 *
25194 * VAL TODO: Do we already have the
25195 * "normalized attribute value" here?
25196 */
25197 if (xpathRes || fixed) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025198 iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025199 /*
25200 * Request a computed value.
25201 */
25202 res = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025203 ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025204 iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025205 1, 1, 0);
25206 } else {
25207 res = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025208 ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025209 iattr->node, iattr->typeDef, iattr->value, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025210 1, 0, 0);
25211 }
25212
25213 if (res != 0) {
25214 if (res == -1) {
25215 VERROR_INT("xmlSchemaVAttributesComplex",
25216 "calling xmlSchemaStreamValidateSimpleTypeValue()");
25217 goto internal_error;
25218 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025219 iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025220 /*
25221 * SPEC PSVI Assessment Outcome (Attribute)
25222 * [validity] = "invalid"
25223 */
25224 goto eval_idcs;
25225 }
25226
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025227 if (fixed) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025228 /*
25229 * SPEC Attribute Locally Valid (Use) (cvc-au)
25230 * "For an attribute information item to be·valid·
25231 * with respect to an attribute use its *normalized*
25232 * value· must match the *canonical* lexical
25233 * representation of the attribute use's {value
25234 * constraint}value, if it is present and fixed."
25235 *
25236 * VAL TODO: The requirement for the *canonical* value
25237 * will be removed in XML Schema 1.1.
25238 */
25239 /*
25240 * SPEC Attribute Locally Valid (cvc-attribute)
25241 * (4) "The item's *actual* value· must match the *value* of
25242 * the {value constraint}, if it is present and fixed."
25243 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025244 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025245 /* VAL TODO: A value was not precomputed. */
25246 TODO
25247 goto eval_idcs;
25248 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025249 if ((iattr->use != NULL) &&
25250 (iattr->use->defValue != NULL)) {
25251 if (iattr->use->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025252 /* VAL TODO: A default value was not precomputed. */
25253 TODO
25254 goto eval_idcs;
25255 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025256 iattr->vcValue = iattr->use->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025257 /*
25258 if (xmlSchemaCompareValuesWhtsp(attr->val,
25259 (xmlSchemaWhitespaceValueType) ws,
25260 attr->use->defVal,
25261 (xmlSchemaWhitespaceValueType) ws) != 0) {
25262 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025263 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25264 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025265 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025266 if (iattr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025267 /* VAL TODO: A default value was not precomputed. */
25268 TODO
25269 goto eval_idcs;
25270 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025271 iattr->vcValue = iattr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025272 /*
25273 if (xmlSchemaCompareValuesWhtsp(attr->val,
25274 (xmlSchemaWhitespaceValueType) ws,
25275 attrDecl->defVal,
25276 (xmlSchemaWhitespaceValueType) ws) != 0) {
25277 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025278 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25279 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025280 }
25281 /*
25282 * [validity] = "valid"
25283 */
25284 }
25285eval_idcs:
25286 /*
25287 * Evaluate IDCs.
25288 */
25289 if (xpathRes) {
25290 if (xmlSchemaXPathProcessHistory(vctxt,
25291 vctxt->depth +1) == -1) {
25292 VERROR_INT("xmlSchemaVAttributesComplex",
25293 "calling xmlSchemaXPathEvaluate()");
25294 goto internal_error;
25295 }
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000025296 } else if (vctxt->xpathStates != NULL)
25297 xmlSchemaXPathPop(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025298 }
25299
25300 /*
25301 * Report errors.
25302 */
25303 for (i = 0; i < vctxt->nbAttrInfos; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025304 iattr = vctxt->attrInfos[i];
25305 if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25306 (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25307 (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25308 (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025309 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025310 ACTIVATE_ATTRIBUTE(iattr);
25311 switch (iattr->state) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025312 case XML_SCHEMAS_ATTR_ERR_MISSING: {
25313 xmlChar *str = NULL;
25314 ACTIVATE_ELEM;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025315 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025316 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25317 "The attribute '%s' is required but missing",
25318 xmlSchemaFormatQName(&str,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025319 iattr->decl->targetNamespace,
25320 iattr->decl->name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025321 NULL);
25322 FREE_AND_NULL(str)
25323 break;
25324 }
25325 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25326 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25327 "The type definition is absent");
25328 break;
25329 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025330 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025331 XML_SCHEMAV_CVC_AU, NULL, NULL,
25332 "The value '%s' does not match the fixed "
25333 "value constraint '%s'",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025334 iattr->value, iattr->vcValue);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025335 break;
25336 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25337 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25338 "No matching global attribute declaration available, but "
25339 "demanded by the strict wildcard");
25340 break;
25341 case XML_SCHEMAS_ATTR_UNKNOWN:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025342 if (iattr->metaType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025343 break;
25344 /*
25345 * MAYBE VAL TODO: One might report different error messages
25346 * for the following errors.
25347 */
25348 if (type->attributeWildcard == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025349 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025350 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025351 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025352 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025353 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025354 }
25355 break;
25356 default:
25357 break;
25358 }
25359 }
25360
25361 ACTIVATE_ELEM;
25362 return (0);
25363internal_error:
25364 ACTIVATE_ELEM;
25365 return (-1);
25366}
25367
25368static int
25369xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25370 int *skip)
25371{
25372 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25373 /*
25374 * The namespace of the element was already identified to be
25375 * matching the wildcard.
25376 */
25377 if ((skip == NULL) || (wild == NULL) ||
25378 (wild->type != XML_SCHEMA_TYPE_ANY)) {
25379 VERROR_INT("xmlSchemaValidateElemWildcard",
25380 "bad arguments");
25381 return (-1);
25382 }
25383 *skip = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025384 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25385 /*
25386 * URGENT VAL TODO: Either we need to position the stream to the
25387 * next sibling, or walk the whole subtree.
25388 */
25389 *skip = 1;
25390 return (0);
25391 }
25392 {
25393 xmlSchemaElementPtr decl = NULL;
25394
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025395 decl = xmlSchemaGetElem(vctxt->schema,
25396 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025397 if (decl != NULL) {
25398 vctxt->inode->decl = decl;
25399 return (0);
25400 }
25401 }
25402 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25403 /* VAL TODO: Change to proper error code. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025404 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025405 "No matching global element declaration available, but "
25406 "demanded by the strict wildcard");
25407 return (vctxt->err);
25408 }
25409 if (vctxt->nbAttrInfos != 0) {
25410 xmlSchemaAttrInfoPtr iattr;
25411 /*
25412 * SPEC Validation Rule: Schema-Validity Assessment (Element)
25413 * (1.2.1.2.1) - (1.2.1.2.3 )
25414 *
25415 * Use the xsi:type attribute for the type definition.
25416 */
25417 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25418 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25419 if (iattr != NULL) {
25420 if (xmlSchemaProcessXSIType(vctxt, iattr,
25421 &(vctxt->inode->typeDef), NULL) == -1) {
25422 VERROR_INT("xmlSchemaValidateElemWildcard",
25423 "calling xmlSchemaProcessXSIType() to "
25424 "process the attribute 'xsi:nil'");
25425 return (-1);
25426 }
25427 /*
25428 * Don't return an error on purpose.
25429 */
25430 return (0);
25431 }
25432 }
25433 /*
25434 * SPEC Validation Rule: Schema-Validity Assessment (Element)
25435 *
25436 * Fallback to "anyType".
25437 */
25438 vctxt->inode->typeDef =
25439 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25440 return (0);
25441}
25442
25443/*
25444* xmlSchemaCheckCOSValidDefault:
25445*
25446* This will be called if: not nilled, no content and a default/fixed
25447* value is provided.
25448*/
25449
25450static int
25451xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25452 const xmlChar *value,
25453 xmlSchemaValPtr *val)
25454{
25455 int ret = 0;
25456 xmlSchemaNodeInfoPtr inode = vctxt->inode;
25457
25458 /*
25459 * cos-valid-default:
25460 * Schema Component Constraint: Element Default Valid (Immediate)
25461 * For a string to be a valid default with respect to a type
25462 * definition the appropriate case among the following must be true:
25463 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025464 if WXS_IS_COMPLEX(inode->typeDef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025465 /*
25466 * Complex type.
25467 *
25468 * SPEC (2.1) "its {content type} must be a simple type definition
25469 * or mixed."
25470 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
25471 * type}'s particle must be ·emptiable· as defined by
25472 * Particle Emptiable (§3.9.6)."
25473 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025474 if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25475 ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25476 (! WXS_EMPTIABLE(inode->typeDef)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025477 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25478 /* NOTE that this covers (2.2.2) as well. */
25479 VERROR(ret, NULL,
25480 "For a string to be a valid default, the type definition "
25481 "must be a simple type or a complex type with simple content "
25482 "or mixed content and a particle emptiable");
25483 return(ret);
25484 }
25485 }
25486 /*
25487 * 1 If the type definition is a simple type definition, then the string
25488 * must be ·valid· with respect to that definition as defined by String
25489 * Valid (§3.14.4).
25490 *
25491 * AND
25492 *
25493 * 2.2.1 If the {content type} is a simple type definition, then the
25494 * string must be ·valid· with respect to that simple type definition
25495 * as defined by String Valid (§3.14.4).
25496 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025497 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025498
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025499 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025500 NULL, inode->typeDef, value, val, 1, 1, 0);
25501
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025502 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025503
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025504 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025505 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25506 }
25507 if (ret < 0) {
25508 VERROR_INT("xmlSchemaCheckCOSValidDefault",
25509 "calling xmlSchemaVCheckCVCSimpleType()");
25510 }
25511 return (ret);
25512}
25513
25514static void
25515xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25516 const xmlChar * name ATTRIBUTE_UNUSED,
25517 xmlSchemaElementPtr item,
25518 xmlSchemaNodeInfoPtr inode)
25519{
25520 inode->decl = item;
25521#ifdef DEBUG_CONTENT
25522 {
25523 xmlChar *str = NULL;
25524
25525 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25526 xmlGenericError(xmlGenericErrorContext,
25527 "AUTOMATON callback for '%s' [declaration]\n",
25528 xmlSchemaFormatQName(&str,
25529 inode->localName, inode->nsName));
25530 } else {
25531 xmlGenericError(xmlGenericErrorContext,
25532 "AUTOMATON callback for '%s' [wildcard]\n",
25533 xmlSchemaFormatQName(&str,
25534 inode->localName, inode->nsName));
25535
25536 }
25537 FREE_AND_NULL(str)
25538 }
25539#endif
25540}
25541
25542static int
25543xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000025544{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025545 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25546 if (vctxt->inode == NULL) {
25547 VERROR_INT("xmlSchemaValidatorPushElem",
25548 "calling xmlSchemaGetFreshElemInfo()");
25549 return (-1);
25550 }
25551 vctxt->nbAttrInfos = 0;
25552 return (0);
25553}
25554
25555static int
25556xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25557 xmlSchemaNodeInfoPtr inode,
25558 xmlSchemaTypePtr type,
25559 const xmlChar *value)
25560{
25561 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25562 return (xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025563 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025564 type, value, &(inode->val), 1, 1, 0));
25565 else
25566 return (xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025567 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025568 type, value, NULL, 1, 0, 0));
25569}
25570
25571
25572
25573/*
25574* Process END of element.
25575*/
25576static int
25577xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
25578{
25579 int ret = 0;
25580 xmlSchemaNodeInfoPtr inode = vctxt->inode;
25581
25582 if (vctxt->nbAttrInfos != 0)
25583 xmlSchemaClearAttrInfos(vctxt);
25584 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
25585 /*
25586 * This element was not expected;
25587 * we will not validate child elements of broken parents.
25588 * Skip validation of all content of the parent.
25589 */
25590 vctxt->skipDepth = vctxt->depth -1;
25591 goto end_elem;
25592 }
25593 if ((inode->typeDef == NULL) ||
25594 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
25595 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000025596 * 1. the type definition might be missing if the element was
25597 * error prone
25598 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025599 */
25600 goto end_elem;
25601 }
25602 /*
25603 * Check the content model.
25604 */
25605 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
25606 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
25607
25608 /*
25609 * Workaround for "anyType".
25610 */
25611 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
25612 goto character_content;
25613
25614 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
25615 xmlChar *values[10];
25616 int terminal, nbval = 10, nbneg;
25617
25618 if (inode->regexCtxt == NULL) {
25619 /*
25620 * Create the regex context.
25621 */
25622 inode->regexCtxt =
25623 xmlRegNewExecCtxt(inode->typeDef->contModel,
25624 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
25625 vctxt);
25626 if (inode->regexCtxt == NULL) {
25627 VERROR_INT("xmlSchemaValidatorPopElem",
25628 "failed to create a regex context");
25629 goto internal_error;
25630 }
25631#ifdef DEBUG_AUTOMATA
25632 xmlGenericError(xmlGenericErrorContext,
25633 "AUTOMATON create on '%s'\n", inode->localName);
25634#endif
25635 }
25636 /*
25637 * Get hold of the still expected content, since a further
25638 * call to xmlRegExecPushString() will loose this information.
25639 */
25640 xmlRegExecNextValues(inode->regexCtxt,
25641 &nbval, &nbneg, &values[0], &terminal);
25642 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
25643 if (ret <= 0) {
25644 /*
25645 * Still missing something.
25646 */
25647 ret = 1;
25648 inode->flags |=
25649 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025650 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025651 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
25652 "Missing child element(s)",
25653 nbval, nbneg, values);
25654#ifdef DEBUG_AUTOMATA
25655 xmlGenericError(xmlGenericErrorContext,
25656 "AUTOMATON missing ERROR on '%s'\n",
25657 inode->localName);
25658#endif
25659 } else {
25660 /*
25661 * Content model is satisfied.
25662 */
25663 ret = 0;
25664#ifdef DEBUG_AUTOMATA
25665 xmlGenericError(xmlGenericErrorContext,
25666 "AUTOMATON succeeded on '%s'\n",
25667 inode->localName);
25668#endif
25669 }
25670
25671 }
25672 }
25673 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
25674 goto end_elem;
25675
25676character_content:
25677
25678 if (vctxt->value != NULL) {
25679 xmlSchemaFreeValue(vctxt->value);
25680 vctxt->value = NULL;
25681 }
25682 /*
25683 * Check character content.
25684 */
25685 if (inode->decl == NULL) {
25686 /*
25687 * Speedup if no declaration exists.
25688 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025689 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025690 ret = xmlSchemaVCheckINodeDataType(vctxt,
25691 inode, inode->typeDef, inode->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025692 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025693 ret = xmlSchemaVCheckINodeDataType(vctxt,
25694 inode, inode->typeDef->contentTypeDef,
25695 inode->value);
25696 }
25697 if (ret < 0) {
25698 VERROR_INT("xmlSchemaValidatorPopElem",
25699 "calling xmlSchemaVCheckCVCSimpleType()");
25700 goto internal_error;
25701 }
25702 goto end_elem;
25703 }
25704 /*
25705 * cvc-elt (3.3.4) : 5
25706 * The appropriate case among the following must be true:
25707 */
25708 /*
25709 * cvc-elt (3.3.4) : 5.1
25710 * If the declaration has a {value constraint},
25711 * the item has neither element nor character [children] and
25712 * clause 3.2 has not applied, then all of the following must be true:
25713 */
25714 if ((inode->decl->value != NULL) &&
25715 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
25716 (! INODE_NILLED(inode))) {
25717 /*
25718 * cvc-elt (3.3.4) : 5.1.1
25719 * If the ·actual type definition· is a ·local type definition·
25720 * then the canonical lexical representation of the {value constraint}
25721 * value must be a valid default for the ·actual type definition· as
25722 * defined in Element Default Valid (Immediate) (§3.3.6).
25723 */
25724 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025725 * NOTE: 'local' above means types acquired by xsi:type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025726 * NOTE: Although the *canonical* value is stated, it is not
25727 * relevant if canonical or not. Additionally XML Schema 1.1
25728 * will removed this requirement as well.
25729 */
25730 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
25731
25732 ret = xmlSchemaCheckCOSValidDefault(vctxt,
25733 inode->decl->value, &(inode->val));
25734 if (ret != 0) {
25735 if (ret < 0) {
25736 VERROR_INT("xmlSchemaValidatorPopElem",
25737 "calling xmlSchemaCheckCOSValidDefault()");
25738 goto internal_error;
25739 }
25740 goto end_elem;
25741 }
25742 /*
25743 * Stop here, to avoid redundant validation of the value
25744 * (see following).
25745 */
25746 goto default_psvi;
25747 }
25748 /*
25749 * cvc-elt (3.3.4) : 5.1.2
25750 * The element information item with the canonical lexical
25751 * representation of the {value constraint} value used as its
25752 * ·normalized value· must be ·valid· with respect to the
25753 * ·actual type definition· as defined by Element Locally Valid (Type)
25754 * (§3.3.4).
25755 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025756 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025757 ret = xmlSchemaVCheckINodeDataType(vctxt,
25758 inode, inode->typeDef, inode->decl->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025759 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025760 ret = xmlSchemaVCheckINodeDataType(vctxt,
25761 inode, inode->typeDef->contentTypeDef,
25762 inode->decl->value);
25763 }
25764 if (ret != 0) {
25765 if (ret < 0) {
25766 VERROR_INT("xmlSchemaValidatorPopElem",
25767 "calling xmlSchemaVCheckCVCSimpleType()");
25768 goto internal_error;
25769 }
25770 goto end_elem;
25771 }
25772
25773default_psvi:
25774 /*
25775 * PSVI: Create a text node on the instance element.
25776 */
25777 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
25778 (inode->node != NULL)) {
25779 xmlNodePtr textChild;
25780 xmlChar *normValue;
25781 /*
25782 * VAL TODO: Normalize the value.
25783 */
25784 normValue = xmlSchemaNormalizeValue(inode->typeDef,
25785 inode->decl->value);
25786 if (normValue != NULL) {
25787 textChild = xmlNewText(BAD_CAST normValue);
25788 xmlFree(normValue);
25789 } else
25790 textChild = xmlNewText(inode->decl->value);
25791 if (textChild == NULL) {
25792 VERROR_INT("xmlSchemaValidatorPopElem",
25793 "calling xmlNewText()");
25794 goto internal_error;
25795 } else
25796 xmlAddChild(inode->node, textChild);
25797 }
25798
25799 } else if (! INODE_NILLED(inode)) {
25800 /*
25801 * 5.2.1 The element information item must be ·valid· with respect
25802 * to the ·actual type definition· as defined by Element Locally
25803 * Valid (Type) (§3.3.4).
25804 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025805 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025806 /*
25807 * SPEC (cvc-type) (3.1)
25808 * "If the type definition is a simple type definition, ..."
25809 * (3.1.3) "If clause 3.2 of Element Locally Valid
25810 * (Element) (§3.3.4) did not apply, then the ·normalized value·
25811 * must be ·valid· with respect to the type definition as defined
25812 * by String Valid (§3.14.4).
25813 */
25814 ret = xmlSchemaVCheckINodeDataType(vctxt,
25815 inode, inode->typeDef, inode->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025816 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025817 /*
25818 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
25819 * definition, then the element information item must be
25820 * ·valid· with respect to the type definition as per
25821 * Element Locally Valid (Complex Type) (§3.4.4);"
25822 *
25823 * SPEC (cvc-complex-type) (2.2)
25824 * "If the {content type} is a simple type definition, ...
25825 * the ·normalized value· of the element information item is
25826 * ·valid· with respect to that simple type definition as
25827 * defined by String Valid (§3.14.4)."
25828 */
25829 ret = xmlSchemaVCheckINodeDataType(vctxt,
25830 inode, inode->typeDef->contentTypeDef, inode->value);
25831 }
25832 if (ret != 0) {
25833 if (ret < 0) {
25834 VERROR_INT("xmlSchemaValidatorPopElem",
25835 "calling xmlSchemaVCheckCVCSimpleType()");
25836 goto internal_error;
25837 }
25838 goto end_elem;
25839 }
25840 /*
25841 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
25842 * not applied, all of the following must be true:
25843 */
25844 if ((inode->decl->value != NULL) &&
25845 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
25846
25847 /*
25848 * TODO: We will need a computed value, when comparison is
25849 * done on computed values.
25850 */
25851 /*
25852 * 5.2.2.1 The element information item must have no element
25853 * information item [children].
25854 */
25855 if (inode->flags &
25856 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
25857 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
25858 VERROR(ret, NULL,
25859 "The content must not containt element nodes since "
25860 "there is a fixed value constraint");
25861 goto end_elem;
25862 } else {
25863 /*
25864 * 5.2.2.2 The appropriate case among the following must
25865 * be true:
25866 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025867 if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025868 /*
25869 * 5.2.2.2.1 If the {content type} of the ·actual type
25870 * definition· is mixed, then the *initial value* of the
25871 * item must match the canonical lexical representation
25872 * of the {value constraint} value.
25873 *
25874 * ... the *initial value* of an element information
25875 * item is the string composed of, in order, the
25876 * [character code] of each character information item in
25877 * the [children] of that element information item.
25878 */
25879 if (! xmlStrEqual(inode->value, inode->decl->value)){
25880 /*
25881 * VAL TODO: Report invalid & expected values as well.
25882 * VAL TODO: Implement the canonical stuff.
25883 */
25884 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025885 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025886 ret, NULL, NULL,
25887 "The initial value '%s' does not match the fixed "
25888 "value constraint '%s'",
25889 inode->value, inode->decl->value);
25890 goto end_elem;
25891 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025892 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025893 /*
25894 * 5.2.2.2.2 If the {content type} of the ·actual type
25895 * definition· is a simple type definition, then the
25896 * *actual value* of the item must match the canonical
25897 * lexical representation of the {value constraint} value.
25898 */
25899 /*
25900 * VAL TODO: *actual value* is the normalized value, impl.
25901 * this.
25902 * VAL TODO: Report invalid & expected values as well.
25903 * VAL TODO: Implement a comparison with the computed values.
25904 */
25905 if (! xmlStrEqual(inode->value,
25906 inode->decl->value)) {
25907 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025908 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025909 ret, NULL, NULL,
25910 "The actual value '%s' does not match the fixed "
25911 "value constraint '%s'",
25912 inode->value,
25913 inode->decl->value);
25914 goto end_elem;
25915 }
25916 }
25917 }
25918 }
25919 }
25920
25921end_elem:
25922 if (vctxt->depth < 0) {
25923 /* TODO: raise error? */
25924 return (0);
25925 }
25926 if (vctxt->depth == vctxt->skipDepth)
25927 vctxt->skipDepth = -1;
25928 /*
25929 * Evaluate the history of XPath state objects.
25930 */
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000025931 if (inode->appliedXPath &&
25932 (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025933 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025934 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025935 * MAYBE TODO:
25936 * SPEC (6) "The element information item must be ·valid· with
25937 * respect to each of the {identity-constraint definitions} as per
25938 * Identity-constraint Satisfied (§3.11.4)."
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025939 */
25940 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025941 * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
25942 * need to be built in any case.
25943 * We will currently build IDC node-tables and bubble them only if
25944 * keyrefs do exist.
25945 */
25946
25947 /*
25948 * Add the current IDC target-nodes to the IDC node-tables.
25949 */
25950 if ((inode->idcMatchers != NULL) &&
25951 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
25952 {
25953 if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
25954 goto internal_error;
25955 }
25956 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025957 * Validate IDC keyrefs.
25958 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025959 if (vctxt->inode->hasKeyrefs)
25960 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
25961 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025962 /*
25963 * Merge/free the IDC table.
25964 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025965 if (inode->idcTable != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025966#ifdef DEBUG_IDC_NODE_TABLE
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025967 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025968 inode->nsName,
25969 inode->localName,
25970 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025971#endif
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025972 if ((vctxt->depth > 0) &&
25973 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
25974 {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025975 /*
25976 * Merge the IDC node table with the table of the parent node.
25977 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025978 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
25979 goto internal_error;
25980 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025981 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025982 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025983 * Clear the current ielem.
25984 * VAL TODO: Don't free the PSVI IDC tables if they are
25985 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025986 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025987 xmlSchemaClearElemInfo(inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025988 /*
25989 * Skip further processing if we are on the validation root.
25990 */
25991 if (vctxt->depth == 0) {
25992 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025993 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000025994 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025995 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025996 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025997 * Reset the keyrefDepth if needed.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025998 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025999 if (vctxt->aidcs != NULL) {
26000 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26001 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026002 if (aidc->keyrefDepth == vctxt->depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026003 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026004 * A 'keyrefDepth' of a key/unique IDC matches the current
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026005 * depth, this means that we are leaving the scope of the
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026006 * top-most keyref IDC which refers to this IDC.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026007 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026008 aidc->keyrefDepth = -1;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026009 }
26010 aidc = aidc->next;
26011 } while (aidc != NULL);
26012 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026013 vctxt->depth--;
26014 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000026015 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026016 * VAL TODO: 7 If the element information item is the ·validation root·, it must be
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026017 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
26018 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026019 return (ret);
26020
26021internal_error:
26022 vctxt->err = -1;
26023 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000026024}
26025
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026026/*
26027* 3.4.4 Complex Type Definition Validation Rules
26028* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26029*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000026030static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026031xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000026032{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026033 xmlSchemaNodeInfoPtr pielem;
26034 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000026035 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000026036
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026037 if (vctxt->depth <= 0) {
26038 VERROR_INT("xmlSchemaValidateChildElem",
26039 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026040 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026041 }
26042 pielem = vctxt->elemInfos[vctxt->depth -1];
26043 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26044 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026045 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026046 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026047 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026048 if (INODE_NILLED(pielem)) {
26049 /*
26050 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
26051 */
26052 ACTIVATE_PARENT_ELEM;
26053 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26054 VERROR(ret, NULL,
26055 "Neither character nor element content is allowed, "
26056 "because the element was 'nilled'");
26057 ACTIVATE_ELEM;
26058 goto unexpected_elem;
26059 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026060
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026061 ptype = pielem->typeDef;
26062
26063 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26064 /*
26065 * Workaround for "anyType": we have currently no content model
26066 * assigned for "anyType", so handle it explicitely.
26067 * "anyType" has an unbounded, lax "any" wildcard.
26068 */
26069 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26070 vctxt->inode->localName,
26071 vctxt->inode->nsName);
26072
26073 if (vctxt->inode->decl == NULL) {
26074 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026075 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026076 * Process "xsi:type".
26077 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026078 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026079 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26080 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26081 if (iattr != NULL) {
26082 ret = xmlSchemaProcessXSIType(vctxt, iattr,
26083 &(vctxt->inode->typeDef), NULL);
26084 if (ret != 0) {
26085 if (ret == -1) {
26086 VERROR_INT("xmlSchemaValidateChildElem",
26087 "calling xmlSchemaProcessXSIType() to "
26088 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000026089 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000026090 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026091 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000026092 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026093 } else {
26094 /*
26095 * Fallback to "anyType".
26096 *
26097 * SPEC (cvc-assess-elt)
26098 * "If the item cannot be ·strictly assessed·, [...]
26099 * an element information item's schema validity may be laxly
26100 * assessed if its ·context-determined declaration· is not
26101 * skip by ·validating· with respect to the ·ur-type
26102 * definition· as per Element Locally Valid (Type) (§3.3.4)."
26103 */
26104 vctxt->inode->typeDef =
26105 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026106 }
26107 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026108 return (0);
26109 }
26110
26111 switch (ptype->contentType) {
26112 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026113 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026114 * SPEC (2.1) "If the {content type} is empty, then the
26115 * element information item has no character or element
26116 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026117 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026118 ACTIVATE_PARENT_ELEM
26119 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26120 VERROR(ret, NULL,
26121 "Element content is not allowed, "
26122 "because the content type is empty");
26123 ACTIVATE_ELEM
26124 goto unexpected_elem;
26125 break;
26126
26127 case XML_SCHEMA_CONTENT_MIXED:
26128 case XML_SCHEMA_CONTENT_ELEMENTS: {
26129 xmlRegExecCtxtPtr regexCtxt;
26130 xmlChar *values[10];
26131 int terminal, nbval = 10, nbneg;
26132
26133 /* VAL TODO: Optimized "anyType" validation.*/
26134
26135 if (ptype->contModel == NULL) {
26136 VERROR_INT("xmlSchemaValidateChildElem",
26137 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026138 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000026139 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026140 /*
26141 * Safety belf for evaluation if the cont. model was already
26142 * examined to be invalid.
26143 */
26144 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26145 VERROR_INT("xmlSchemaValidateChildElem",
26146 "validating elem, but elem content is already invalid");
26147 return (-1);
26148 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000026149
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026150 regexCtxt = pielem->regexCtxt;
26151 if (regexCtxt == NULL) {
26152 /*
26153 * Create the regex context.
26154 */
26155 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26156 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26157 vctxt);
26158 if (regexCtxt == NULL) {
26159 VERROR_INT("xmlSchemaValidateChildElem",
26160 "failed to create a regex context");
26161 return (-1);
26162 }
26163 pielem->regexCtxt = regexCtxt;
26164#ifdef DEBUG_AUTOMATA
26165 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26166 pielem->localName);
26167#endif
26168 }
26169
26170 /*
26171 * SPEC (2.4) "If the {content type} is element-only or mixed,
26172 * then the sequence of the element information item's
26173 * element information item [children], if any, taken in
26174 * order, is ·valid· with respect to the {content type}'s
26175 * particle, as defined in Element Sequence Locally Valid
26176 * (Particle) (§3.9.4)."
26177 */
26178 ret = xmlRegExecPushString2(regexCtxt,
26179 vctxt->inode->localName,
26180 vctxt->inode->nsName,
26181 vctxt->inode);
26182#ifdef DEBUG_AUTOMATA
26183 if (ret < 0)
26184 xmlGenericError(xmlGenericErrorContext,
26185 "AUTOMATON push ERROR for '%s' on '%s'\n",
26186 vctxt->inode->localName, pielem->localName);
26187 else
26188 xmlGenericError(xmlGenericErrorContext,
26189 "AUTOMATON push OK for '%s' on '%s'\n",
26190 vctxt->inode->localName, pielem->localName);
26191#endif
26192 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26193 VERROR_INT("xmlSchemaValidateChildElem",
26194 "calling xmlRegExecPushString2()");
26195 return (-1);
26196 }
26197 if (ret < 0) {
26198 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26199 &values[0], &terminal);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026200 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026201 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26202 "This element is not expected",
26203 nbval, nbneg, values);
26204 ret = vctxt->err;
26205 goto unexpected_elem;
26206 } else
26207 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000026208 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026209 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026210 case XML_SCHEMA_CONTENT_SIMPLE:
26211 case XML_SCHEMA_CONTENT_BASIC:
26212 ACTIVATE_PARENT_ELEM
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026213 if (WXS_IS_COMPLEX(ptype)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026214 /*
26215 * SPEC (cvc-complex-type) (2.2)
26216 * "If the {content type} is a simple type definition, then
26217 * the element information item has no element information
26218 * item [children], ..."
26219 */
26220 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26221 VERROR(ret, NULL, "Element content is not allowed, "
26222 "because the content type is a simple type definition");
26223 } else {
26224 /*
26225 * SPEC (cvc-type) (3.1.2) "The element information item must
26226 * have no element information item [children]."
26227 */
26228 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26229 VERROR(ret, NULL, "Element content is not allowed, "
26230 "because the type definition is simple");
26231 }
26232 ACTIVATE_ELEM
26233 ret = vctxt->err;
26234 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026235 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026236
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026237 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026238 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026239 }
26240 return (ret);
26241unexpected_elem:
26242 /*
26243 * Pop this element and set the skipDepth to skip
26244 * all further content of the parent element.
26245 */
26246 vctxt->skipDepth = vctxt->depth;
26247 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26248 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26249 return (ret);
26250}
26251
26252#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26253#define XML_SCHEMA_PUSH_TEXT_CREATED 2
26254#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26255
26256static int
26257xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26258 int nodeType, const xmlChar *value, int len,
26259 int mode, int *consumed)
26260{
26261 /*
26262 * Unfortunately we have to duplicate the text sometimes.
26263 * OPTIMIZE: Maybe we could skip it, if:
26264 * 1. content type is simple
26265 * 2. whitespace is "collapse"
26266 * 3. it consists of whitespace only
26267 *
26268 * Process character content.
26269 */
26270 if (consumed != NULL)
26271 *consumed = 0;
26272 if (INODE_NILLED(vctxt->inode)) {
26273 /*
26274 * SPEC cvc-elt (3.3.4 - 3.2.1)
26275 * "The element information item must have no character or
26276 * element information item [children]."
26277 */
26278 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26279 "Neither character nor element content is allowed "
26280 "because the element is 'nilled'");
26281 return (vctxt->err);
26282 }
26283 /*
26284 * SPEC (2.1) "If the {content type} is empty, then the
26285 * element information item has no character or element
26286 * information item [children]."
26287 */
26288 if (vctxt->inode->typeDef->contentType ==
26289 XML_SCHEMA_CONTENT_EMPTY) {
26290 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26291 "Character content is not allowed, "
26292 "because the content type is empty");
26293 return (vctxt->err);
26294 }
26295
26296 if (vctxt->inode->typeDef->contentType ==
26297 XML_SCHEMA_CONTENT_ELEMENTS) {
26298 if ((nodeType != XML_TEXT_NODE) ||
26299 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26300 /*
26301 * SPEC cvc-complex-type (2.3)
26302 * "If the {content type} is element-only, then the
26303 * element information item has no character information
26304 * item [children] other than those whose [character
26305 * code] is defined as a white space in [XML 1.0 (Second
26306 * Edition)]."
26307 */
26308 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26309 "Character content other than whitespace is not allowed "
26310 "because the content type is 'element-only'");
26311 return (vctxt->err);
26312 }
26313 return (0);
26314 }
26315
26316 if ((value == NULL) || (value[0] == 0))
26317 return (0);
26318 /*
26319 * Save the value.
26320 * NOTE that even if the content type is *mixed*, we need the
26321 * *initial value* for default/fixed value constraints.
26322 */
26323 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26324 ((vctxt->inode->decl == NULL) ||
26325 (vctxt->inode->decl->value == NULL)))
26326 return (0);
26327
26328 if (vctxt->inode->value == NULL) {
26329 /*
26330 * Set the value.
26331 */
26332 switch (mode) {
26333 case XML_SCHEMA_PUSH_TEXT_PERSIST:
26334 /*
26335 * When working on a tree.
26336 */
26337 vctxt->inode->value = value;
26338 break;
26339 case XML_SCHEMA_PUSH_TEXT_CREATED:
26340 /*
26341 * When working with the reader.
26342 * The value will be freed by the element info.
26343 */
26344 vctxt->inode->value = value;
26345 if (consumed != NULL)
26346 *consumed = 1;
26347 vctxt->inode->flags |=
26348 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26349 break;
26350 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26351 /*
26352 * When working with SAX.
26353 * The value will be freed by the element info.
26354 */
26355 if (len != -1)
26356 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26357 else
26358 vctxt->inode->value = BAD_CAST xmlStrdup(value);
26359 vctxt->inode->flags |=
26360 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26361 break;
26362 default:
26363 break;
26364 }
Kasimier T. Buchcik5bb0c082005-12-20 10:48:33 +000026365 } else {
26366 if (len < 0)
26367 len = xmlStrlen(value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026368 /*
26369 * Concat the value.
26370 */
26371 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000026372 vctxt->inode->value = BAD_CAST xmlStrncat(
26373 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026374 } else {
26375 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026376 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026377 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26378 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026379 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026380
26381 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000026382}
26383
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026384static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026385xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000026386{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026387 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000026388
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026389 if ((vctxt->skipDepth != -1) &&
26390 (vctxt->depth >= vctxt->skipDepth)) {
26391 VERROR_INT("xmlSchemaValidateElem",
26392 "in skip-state");
26393 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026394 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026395 if (vctxt->xsiAssemble) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026396 /*
Kasimier T. Buchcik215406f2005-12-07 12:14:09 +000026397 * We will stop validation if there was an error during
26398 * dynamic schema construction.
26399 * Note that we simply set @skipDepth to 0, this could
26400 * mean that a streaming document via SAX would be
26401 * still read to the end but it won't be validated any more.
26402 * TODO: If we are sure how to stop the validation at once
26403 * for all input scenarios, then this should be changed to
26404 * instantly stop the validation.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026405 */
Kasimier T. Buchcik215406f2005-12-07 12:14:09 +000026406 ret = xmlSchemaAssembleByXSI(vctxt);
26407 if (ret != 0) {
26408 if (ret == -1)
26409 goto internal_error;
26410 vctxt->skipDepth = 0;
26411 return(ret);
26412 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026413 }
26414 if (vctxt->depth > 0) {
26415 /*
26416 * Validate this element against the content model
26417 * of the parent.
26418 */
26419 ret = xmlSchemaValidateChildElem(vctxt);
26420 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026421 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026422 VERROR_INT("xmlSchemaValidateElem",
26423 "calling xmlSchemaStreamValidateChildElement()");
26424 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026425 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026426 goto exit;
26427 }
26428 if (vctxt->depth == vctxt->skipDepth)
26429 goto exit;
26430 if ((vctxt->inode->decl == NULL) &&
26431 (vctxt->inode->typeDef == NULL)) {
26432 VERROR_INT("xmlSchemaValidateElem",
26433 "the child element was valid but neither the "
26434 "declaration nor the type was set");
26435 goto internal_error;
26436 }
26437 } else {
26438 /*
26439 * Get the declaration of the validation root.
26440 */
26441 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26442 vctxt->inode->localName,
26443 vctxt->inode->nsName);
26444 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026445 ret = XML_SCHEMAV_CVC_ELT_1;
26446 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026447 "No matching global declaration available "
26448 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026449 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026450 }
26451 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026452
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026453 if (vctxt->inode->decl == NULL)
26454 goto type_validation;
26455
26456 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26457 int skip;
26458 /*
26459 * Wildcards.
26460 */
26461 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26462 if (ret != 0) {
26463 if (ret < 0) {
26464 VERROR_INT("xmlSchemaValidateElem",
26465 "calling xmlSchemaValidateElemWildcard()");
26466 goto internal_error;
26467 }
26468 goto exit;
26469 }
26470 if (skip) {
26471 vctxt->skipDepth = vctxt->depth;
26472 goto exit;
26473 }
26474 /*
26475 * The declaration might be set by the wildcard validation,
26476 * when the processContents is "lax" or "strict".
26477 */
26478 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26479 /*
26480 * Clear the "decl" field to not confuse further processing.
26481 */
26482 vctxt->inode->decl = NULL;
26483 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026484 }
Daniel Veillard4255d502002-04-16 15:50:10 +000026485 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026486 /*
26487 * Validate against the declaration.
26488 */
26489 ret = xmlSchemaValidateElemDecl(vctxt);
26490 if (ret != 0) {
26491 if (ret < 0) {
26492 VERROR_INT("xmlSchemaValidateElem",
26493 "calling xmlSchemaValidateElemDecl()");
26494 goto internal_error;
26495 }
26496 goto exit;
26497 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026498 /*
26499 * Validate against the type definition.
26500 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026501type_validation:
26502
26503 if (vctxt->inode->typeDef == NULL) {
26504 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26505 ret = XML_SCHEMAV_CVC_TYPE_1;
26506 VERROR(ret, NULL,
26507 "The type definition is absent");
26508 goto exit;
26509 }
26510 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26511 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26512 ret = XML_SCHEMAV_CVC_TYPE_2;
26513 VERROR(ret, NULL,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026514 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026515 goto exit;
26516 }
26517 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026518 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026519 * during validation against the declaration. This must be done
26520 * _before_ attribute validation.
26521 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026522 if (vctxt->xpathStates != NULL) {
26523 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000026524 vctxt->inode->appliedXPath = 1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026525 if (ret == -1) {
26526 VERROR_INT("xmlSchemaValidateElem",
26527 "calling xmlSchemaXPathEvaluate()");
26528 goto internal_error;
26529 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026530 }
26531 /*
26532 * Validate attributes.
26533 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026534 if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026535 if ((vctxt->nbAttrInfos != 0) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026536 (vctxt->inode->typeDef->attrUses != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026537
26538 ret = xmlSchemaVAttributesComplex(vctxt);
26539 }
26540 } else if (vctxt->nbAttrInfos != 0) {
26541
26542 ret = xmlSchemaVAttributesSimple(vctxt);
26543 }
26544 /*
26545 * Clear registered attributes.
26546 */
26547 if (vctxt->nbAttrInfos != 0)
26548 xmlSchemaClearAttrInfos(vctxt);
26549 if (ret == -1) {
26550 VERROR_INT("xmlSchemaValidateElem",
26551 "calling attributes validation");
26552 goto internal_error;
26553 }
26554 /*
26555 * Don't return an error if attributes are invalid on purpose.
26556 */
26557 ret = 0;
26558
26559exit:
26560 if (ret != 0)
26561 vctxt->skipDepth = vctxt->depth;
26562 return (ret);
26563internal_error:
26564 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000026565}
26566
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026567#ifdef XML_SCHEMA_READER_ENABLED
26568static int
26569xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000026570{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026571 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
26572 int depth, nodeType, ret = 0, consumed;
26573 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000026574
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026575 vctxt->depth = -1;
26576 ret = xmlTextReaderRead(vctxt->reader);
26577 /*
26578 * Move to the document element.
26579 */
26580 while (ret == 1) {
26581 nodeType = xmlTextReaderNodeType(vctxt->reader);
26582 if (nodeType == XML_ELEMENT_NODE)
26583 goto root_found;
26584 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026585 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026586 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026587
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026588root_found:
26589
26590 do {
26591 depth = xmlTextReaderDepth(vctxt->reader);
26592 nodeType = xmlTextReaderNodeType(vctxt->reader);
26593
26594 if (nodeType == XML_ELEMENT_NODE) {
26595
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026596 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026597 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26598 VERROR_INT("xmlSchemaVReaderWalk",
26599 "calling xmlSchemaValidatorPushElem()");
26600 goto internal_error;
26601 }
26602 ielem = vctxt->inode;
26603 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
26604 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
26605 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
26606 /*
26607 * Is the element empty?
26608 */
26609 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
26610 if (ret == -1) {
26611 VERROR_INT("xmlSchemaVReaderWalk",
26612 "calling xmlTextReaderIsEmptyElement()");
26613 goto internal_error;
26614 }
26615 if (ret) {
26616 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26617 }
26618 /*
26619 * Register attributes.
26620 */
26621 vctxt->nbAttrInfos = 0;
26622 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
26623 if (ret == -1) {
26624 VERROR_INT("xmlSchemaVReaderWalk",
26625 "calling xmlTextReaderMoveToFirstAttribute()");
26626 goto internal_error;
26627 }
26628 if (ret == 1) {
26629 do {
26630 /*
26631 * VAL TODO: How do we know that the reader works on a
26632 * node tree, to be able to pass a node here?
26633 */
26634 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
26635 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
26636 xmlTextReaderNamespaceUri(vctxt->reader), 1,
26637 xmlTextReaderValue(vctxt->reader), 1) == -1) {
26638
26639 VERROR_INT("xmlSchemaVReaderWalk",
26640 "calling xmlSchemaValidatorPushAttribute()");
26641 goto internal_error;
26642 }
26643 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
26644 if (ret == -1) {
26645 VERROR_INT("xmlSchemaVReaderWalk",
26646 "calling xmlTextReaderMoveToFirstAttribute()");
26647 goto internal_error;
26648 }
26649 } while (ret == 1);
26650 /*
26651 * Back to element position.
26652 */
26653 ret = xmlTextReaderMoveToElement(vctxt->reader);
26654 if (ret == -1) {
26655 VERROR_INT("xmlSchemaVReaderWalk",
26656 "calling xmlTextReaderMoveToElement()");
26657 goto internal_error;
26658 }
26659 }
26660 /*
26661 * Validate the element.
26662 */
26663 ret= xmlSchemaValidateElem(vctxt);
26664 if (ret != 0) {
26665 if (ret == -1) {
26666 VERROR_INT("xmlSchemaVReaderWalk",
26667 "calling xmlSchemaValidateElem()");
26668 goto internal_error;
26669 }
26670 goto exit;
26671 }
26672 if (vctxt->depth == vctxt->skipDepth) {
26673 int curDepth;
26674 /*
26675 * Skip all content.
26676 */
26677 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
26678 ret = xmlTextReaderRead(vctxt->reader);
26679 curDepth = xmlTextReaderDepth(vctxt->reader);
26680 while ((ret == 1) && (curDepth != depth)) {
26681 ret = xmlTextReaderRead(vctxt->reader);
26682 curDepth = xmlTextReaderDepth(vctxt->reader);
26683 }
26684 if (ret < 0) {
26685 /*
26686 * VAL TODO: A reader error occured; what to do here?
26687 */
26688 ret = 1;
26689 goto exit;
26690 }
26691 }
26692 goto leave_elem;
26693 }
26694 /*
26695 * READER VAL TODO: Is an END_ELEM really never called
26696 * if the elem is empty?
26697 */
26698 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26699 goto leave_elem;
26700 } else if (nodeType == END_ELEM) {
26701 /*
26702 * Process END of element.
26703 */
26704leave_elem:
26705 ret = xmlSchemaValidatorPopElem(vctxt);
26706 if (ret != 0) {
26707 if (ret < 0) {
26708 VERROR_INT("xmlSchemaVReaderWalk",
26709 "calling xmlSchemaValidatorPopElem()");
26710 goto internal_error;
26711 }
26712 goto exit;
26713 }
26714 if (vctxt->depth >= 0)
26715 ielem = vctxt->inode;
26716 else
26717 ielem = NULL;
26718 } else if ((nodeType == XML_TEXT_NODE) ||
26719 (nodeType == XML_CDATA_SECTION_NODE) ||
26720 (nodeType == WHTSP) ||
26721 (nodeType == SIGN_WHTSP)) {
26722 /*
26723 * Process character content.
26724 */
26725 xmlChar *value;
26726
26727 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
26728 nodeType = XML_TEXT_NODE;
26729
26730 value = xmlTextReaderValue(vctxt->reader);
26731 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
26732 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
26733 if (! consumed)
26734 xmlFree(value);
26735 if (ret == -1) {
26736 VERROR_INT("xmlSchemaVReaderWalk",
26737 "calling xmlSchemaVPushText()");
26738 goto internal_error;
26739 }
26740 } else if ((nodeType == XML_ENTITY_NODE) ||
26741 (nodeType == XML_ENTITY_REF_NODE)) {
26742 /*
26743 * VAL TODO: What to do with entities?
26744 */
26745 TODO
26746 }
26747 /*
26748 * Read next node.
26749 */
26750 ret = xmlTextReaderRead(vctxt->reader);
26751 } while (ret == 1);
26752
26753exit:
26754 return (ret);
26755internal_error:
26756 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000026757}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026758#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000026759
26760/************************************************************************
26761 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026762 * SAX validation handlers *
Daniel Veillard4255d502002-04-16 15:50:10 +000026763 * *
26764 ************************************************************************/
26765
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026766/*
26767* Process text content.
26768*/
26769static void
26770xmlSchemaSAXHandleText(void *ctx,
26771 const xmlChar * ch,
26772 int len)
26773{
26774 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26775
26776 if (vctxt->depth < 0)
26777 return;
26778 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26779 return;
26780 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26781 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26782 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
26783 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
26784 VERROR_INT("xmlSchemaSAXHandleCDataSection",
26785 "calling xmlSchemaVPushText()");
26786 vctxt->err = -1;
26787 xmlStopParser(vctxt->parserCtxt);
26788 }
26789}
26790
26791/*
26792* Process CDATA content.
26793*/
26794static void
26795xmlSchemaSAXHandleCDataSection(void *ctx,
26796 const xmlChar * ch,
26797 int len)
26798{
26799 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26800
26801 if (vctxt->depth < 0)
26802 return;
26803 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26804 return;
26805 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26806 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26807 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
26808 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
26809 VERROR_INT("xmlSchemaSAXHandleCDataSection",
26810 "calling xmlSchemaVPushText()");
26811 vctxt->err = -1;
26812 xmlStopParser(vctxt->parserCtxt);
26813 }
26814}
26815
26816static void
26817xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
26818 const xmlChar * name ATTRIBUTE_UNUSED)
26819{
26820 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26821
26822 if (vctxt->depth < 0)
26823 return;
26824 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26825 return;
26826 /* SAX VAL TODO: What to do here? */
26827 TODO
26828}
26829
26830static void
26831xmlSchemaSAXHandleStartElementNs(void *ctx,
26832 const xmlChar * localname,
26833 const xmlChar * prefix ATTRIBUTE_UNUSED,
26834 const xmlChar * URI,
26835 int nb_namespaces,
26836 const xmlChar ** namespaces,
26837 int nb_attributes,
26838 int nb_defaulted ATTRIBUTE_UNUSED,
26839 const xmlChar ** attributes)
26840{
26841 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26842 int ret;
26843 xmlSchemaNodeInfoPtr ielem;
26844 int i, j;
26845
26846 /*
26847 * SAX VAL TODO: What to do with nb_defaulted?
26848 */
26849 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026850 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026851 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026852 vctxt->depth++;
26853 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026854 return;
26855 /*
26856 * Push the element.
26857 */
26858 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26859 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26860 "calling xmlSchemaValidatorPushElem()");
26861 goto internal_error;
26862 }
26863 ielem = vctxt->inode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026864 /*
26865 * TODO: Is this OK?
26866 */
26867 ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026868 ielem->localName = localname;
26869 ielem->nsName = URI;
26870 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26871 /*
26872 * Register namespaces on the elem info.
26873 */
26874 if (nb_namespaces != 0) {
26875 /*
26876 * Although the parser builds its own namespace list,
26877 * we have no access to it, so we'll use an own one.
26878 */
26879 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
26880 /*
26881 * Store prefix and namespace name.
26882 */
26883 if (ielem->nsBindings == NULL) {
26884 ielem->nsBindings =
26885 (const xmlChar **) xmlMalloc(10 *
26886 sizeof(const xmlChar *));
26887 if (ielem->nsBindings == NULL) {
26888 xmlSchemaVErrMemory(vctxt,
26889 "allocating namespace bindings for SAX validation",
26890 NULL);
26891 goto internal_error;
26892 }
26893 ielem->nbNsBindings = 0;
26894 ielem->sizeNsBindings = 5;
26895 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
26896 ielem->sizeNsBindings *= 2;
26897 ielem->nsBindings =
26898 (const xmlChar **) xmlRealloc(
26899 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026900 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026901 if (ielem->nsBindings == NULL) {
26902 xmlSchemaVErrMemory(vctxt,
26903 "re-allocating namespace bindings for SAX validation",
26904 NULL);
26905 goto internal_error;
26906 }
26907 }
26908
26909 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
26910 if (namespaces[j+1][0] == 0) {
26911 /*
26912 * Handle xmlns="".
26913 */
26914 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
26915 } else
26916 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
26917 namespaces[j+1];
26918 ielem->nbNsBindings++;
26919 }
26920 }
26921 /*
26922 * Register attributes.
26923 * SAX VAL TODO: We are not adding namespace declaration
26924 * attributes yet.
26925 */
26926 if (nb_attributes != 0) {
26927 xmlChar *value;
26928
26929 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
26930 /*
26931 * Duplicate the value.
26932 */
26933 value = xmlStrndup(attributes[j+3],
26934 attributes[j+4] - attributes[j+3]);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026935 /*
26936 * TODO: Set the node line.
26937 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026938 ret = xmlSchemaValidatorPushAttribute(vctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026939 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026940 value, 1);
26941 if (ret == -1) {
26942 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26943 "calling xmlSchemaValidatorPushAttribute()");
26944 goto internal_error;
26945 }
26946 }
26947 }
26948 /*
26949 * Validate the element.
26950 */
26951 ret = xmlSchemaValidateElem(vctxt);
26952 if (ret != 0) {
26953 if (ret == -1) {
26954 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26955 "calling xmlSchemaValidateElem()");
26956 goto internal_error;
26957 }
26958 goto exit;
26959 }
26960
26961exit:
26962 return;
26963internal_error:
26964 vctxt->err = -1;
26965 xmlStopParser(vctxt->parserCtxt);
26966 return;
26967}
26968
26969static void
26970xmlSchemaSAXHandleEndElementNs(void *ctx,
26971 const xmlChar * localname ATTRIBUTE_UNUSED,
26972 const xmlChar * prefix ATTRIBUTE_UNUSED,
26973 const xmlChar * URI ATTRIBUTE_UNUSED)
26974{
26975 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26976 int res;
26977
26978 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026979 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026980 */
26981 if (vctxt->skipDepth != -1) {
26982 if (vctxt->depth > vctxt->skipDepth) {
26983 vctxt->depth--;
26984 return;
26985 } else
26986 vctxt->skipDepth = -1;
26987 }
26988 /*
26989 * SAX VAL TODO: Just a temporary check.
26990 */
26991 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
26992 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
26993 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
26994 "elem pop mismatch");
26995 }
26996 res = xmlSchemaValidatorPopElem(vctxt);
26997 if (res != 0) {
26998 if (res < 0) {
26999 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27000 "calling xmlSchemaValidatorPopElem()");
27001 goto internal_error;
27002 }
27003 goto exit;
27004 }
27005exit:
27006 return;
27007internal_error:
27008 vctxt->err = -1;
27009 xmlStopParser(vctxt->parserCtxt);
27010 return;
27011}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027012
Daniel Veillard4255d502002-04-16 15:50:10 +000027013/************************************************************************
27014 * *
27015 * Validation interfaces *
27016 * *
27017 ************************************************************************/
27018
27019/**
27020 * xmlSchemaNewValidCtxt:
27021 * @schema: a precompiled XML Schemas
27022 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027023 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000027024 *
27025 * Returns the validation context or NULL in case of error
27026 */
27027xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027028xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27029{
Daniel Veillard4255d502002-04-16 15:50:10 +000027030 xmlSchemaValidCtxtPtr ret;
27031
27032 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27033 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027034 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000027035 return (NULL);
27036 }
27037 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027038 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027039 ret->dict = xmlDictCreate();
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000027040 ret->nodeQNames = xmlSchemaItemListCreate();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027041 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000027042 return (ret);
27043}
27044
27045/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027046 * xmlSchemaClearValidCtxt:
27047 * @ctxt: the schema validation context
27048 *
27049 * Free the resources associated to the schema validation context;
27050 * leaves some fields alive intended for reuse of the context.
27051 */
27052static void
27053xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27054{
27055 if (vctxt == NULL)
27056 return;
27057
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027058 /*
27059 * TODO: Should we clear the flags?
27060 * Might be problematic if one reuses the context
27061 * and assumes that the options remain the same.
27062 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000027063 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027064 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027065 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000027066#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027067 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000027068#endif
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027069 vctxt->hasKeyrefs = 0;
27070
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027071 if (vctxt->value != NULL) {
27072 xmlSchemaFreeValue(vctxt->value);
27073 vctxt->value = NULL;
27074 }
27075 /*
27076 * Augmented IDC information.
27077 */
27078 if (vctxt->aidcs != NULL) {
27079 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27080 do {
27081 next = cur->next;
27082 xmlFree(cur);
27083 cur = next;
27084 } while (cur != NULL);
27085 vctxt->aidcs = NULL;
27086 }
27087 if (vctxt->idcNodes != NULL) {
27088 int i;
27089 xmlSchemaPSVIIDCNodePtr item;
27090
27091 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027092 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027093 xmlFree(item->keys);
27094 xmlFree(item);
27095 }
27096 xmlFree(vctxt->idcNodes);
27097 vctxt->idcNodes = NULL;
27098 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027099 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027100 * Note that we won't delete the XPath state pool here.
27101 */
27102 if (vctxt->xpathStates != NULL) {
27103 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27104 vctxt->xpathStates = NULL;
27105 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027106 /*
27107 * Attribute info.
27108 */
27109 if (vctxt->nbAttrInfos != 0) {
27110 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027111 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027112 /*
27113 * Element info.
27114 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027115 if (vctxt->elemInfos != NULL) {
27116 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027117 xmlSchemaNodeInfoPtr ei;
27118
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027119 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027120 ei = vctxt->elemInfos[i];
27121 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027122 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027123 xmlSchemaClearElemInfo(ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027124 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027125 }
27126 xmlSchemaItemListClear(vctxt->nodeQNames);
27127 /* Recreate the dict. */
27128 xmlDictFree(vctxt->dict);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027129 /*
27130 * TODO: Is is save to recreate it? Do we have a scenario
27131 * where the user provides the dict?
27132 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027133 vctxt->dict = xmlDictCreate();
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027134}
27135
27136/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027137 * xmlSchemaFreeValidCtxt:
27138 * @ctxt: the schema validation context
27139 *
27140 * Free the resources associated to the schema validation context
27141 */
27142void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027143xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27144{
Daniel Veillard4255d502002-04-16 15:50:10 +000027145 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027146 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000027147 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027148 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027149 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027150 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027151 if (ctxt->idcNodes != NULL) {
27152 int i;
27153 xmlSchemaPSVIIDCNodePtr item;
27154
27155 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027156 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027157 xmlFree(item->keys);
27158 xmlFree(item);
27159 }
27160 xmlFree(ctxt->idcNodes);
27161 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027162 if (ctxt->idcKeys != NULL) {
27163 int i;
27164 for (i = 0; i < ctxt->nbIdcKeys; i++)
27165 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27166 xmlFree(ctxt->idcKeys);
27167 }
27168
27169 if (ctxt->xpathStates != NULL)
27170 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27171 if (ctxt->xpathStatePool != NULL)
27172 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27173
27174 /*
27175 * Augmented IDC information.
27176 */
27177 if (ctxt->aidcs != NULL) {
27178 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27179 do {
27180 next = cur->next;
27181 xmlFree(cur);
27182 cur = next;
27183 } while (cur != NULL);
27184 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027185 if (ctxt->attrInfos != NULL) {
27186 int i;
27187 xmlSchemaAttrInfoPtr attr;
27188
27189 /* Just a paranoid call to the cleanup. */
27190 if (ctxt->nbAttrInfos != 0)
27191 xmlSchemaClearAttrInfos(ctxt);
27192 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27193 attr = ctxt->attrInfos[i];
27194 xmlFree(attr);
27195 }
27196 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000027197 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027198 if (ctxt->elemInfos != NULL) {
27199 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027200 xmlSchemaNodeInfoPtr ei;
27201
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027202 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027203 ei = ctxt->elemInfos[i];
27204 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027205 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027206 xmlSchemaClearElemInfo(ei);
27207 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027208 }
27209 xmlFree(ctxt->elemInfos);
27210 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027211 if (ctxt->nodeQNames != NULL)
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000027212 xmlSchemaItemListFree(ctxt->nodeQNames);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027213 if (ctxt->dict != NULL)
27214 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000027215 xmlFree(ctxt);
27216}
27217
27218/**
Daniel Veillardf10ae122005-07-10 19:03:16 +000027219 * xmlSchemaIsValid:
27220 * @ctxt: the schema validation context
27221 *
27222 * Check if any error was detected during validation.
27223 *
27224 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27225 * of internal error.
27226 */
27227int
27228xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27229{
27230 if (ctxt == NULL)
27231 return(-1);
27232 return(ctxt->err == 0);
27233}
27234
27235/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027236 * xmlSchemaSetValidErrors:
27237 * @ctxt: a schema validation context
27238 * @err: the error function
27239 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000027240 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000027241 *
William M. Brack2f2a6632004-08-20 23:09:47 +000027242 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000027243 */
27244void
27245xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027246 xmlSchemaValidityErrorFunc err,
27247 xmlSchemaValidityWarningFunc warn, void *ctx)
27248{
Daniel Veillard4255d502002-04-16 15:50:10 +000027249 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027250 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000027251 ctxt->error = err;
27252 ctxt->warning = warn;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027253 ctxt->errCtxt = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027254 if (ctxt->pctxt != NULL)
27255 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000027256}
27257
27258/**
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027259 * xmlSchemaSetValidStructuredErrors:
27260 * @ctxt: a schema validation context
27261 * @serror: the structured error function
27262 * @ctx: the functions context
27263 *
27264 * Set the structured error callback
27265 */
27266void
27267xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027268 xmlStructuredErrorFunc serror, void *ctx)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027269{
27270 if (ctxt == NULL)
27271 return;
27272 ctxt->serror = serror;
27273 ctxt->error = NULL;
27274 ctxt->warning = NULL;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027275 ctxt->errCtxt = ctx;
27276 if (ctxt->pctxt != NULL)
27277 xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027278}
27279
27280/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000027281 * xmlSchemaGetValidErrors:
27282 * @ctxt: a XML-Schema validation context
27283 * @err: the error function result
27284 * @warn: the warning function result
27285 * @ctx: the functions context result
27286 *
27287 * Get the error and warning callback informations
27288 *
27289 * Returns -1 in case of error and 0 otherwise
27290 */
27291int
27292xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027293 xmlSchemaValidityErrorFunc * err,
27294 xmlSchemaValidityWarningFunc * warn, void **ctx)
Daniel Veillard259f0df2004-08-18 09:13:18 +000027295{
27296 if (ctxt == NULL)
27297 return (-1);
27298 if (err != NULL)
27299 *err = ctxt->error;
27300 if (warn != NULL)
27301 *warn = ctxt->warning;
27302 if (ctx != NULL)
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027303 *ctx = ctxt->errCtxt;
Daniel Veillard259f0df2004-08-18 09:13:18 +000027304 return (0);
27305}
27306
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027307
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027308/**
Daniel Veillard6927b102004-10-27 17:29:04 +000027309 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027310 * @ctxt: a schema validation context
27311 * @options: a combination of xmlSchemaValidOption
27312 *
27313 * Sets the options to be used during the validation.
27314 *
27315 * Returns 0 in case of success, -1 in case of an
27316 * API error.
27317 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027318int
27319xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27320 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027321
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027322{
27323 int i;
27324
27325 if (ctxt == NULL)
27326 return (-1);
27327 /*
27328 * WARNING: Change the start value if adding to the
27329 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027330 * TODO: Is there an other, more easy to maintain,
27331 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027332 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027333 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027334 if (options & 1<<i)
27335 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027336 }
27337 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027338 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027339}
27340
27341/**
Daniel Veillard6927b102004-10-27 17:29:04 +000027342 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027343 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027344 *
William M. Brack21e4ef22005-01-02 09:53:13 +000027345 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027346 *
William M. Brack21e4ef22005-01-02 09:53:13 +000027347 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027348 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027349int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027350xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027351
27352{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027353 if (ctxt == NULL)
27354 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027355 else
27356 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027357}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027358
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027359static int
27360xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27361{
27362 xmlAttrPtr attr;
27363 int ret = 0;
27364 xmlSchemaNodeInfoPtr ielem = NULL;
27365 xmlNodePtr node, valRoot;
27366 const xmlChar *nsName;
27367
27368 /* DOC VAL TODO: Move this to the start function. */
27369 valRoot = xmlDocGetRootElement(vctxt->doc);
27370 if (valRoot == NULL) {
27371 /* VAL TODO: Error code? */
27372 VERROR(1, NULL, "The document has no document element");
27373 return (1);
27374 }
27375 vctxt->depth = -1;
27376 vctxt->validationRoot = valRoot;
27377 node = valRoot;
27378 while (node != NULL) {
27379 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27380 goto next_sibling;
27381 if (node->type == XML_ELEMENT_NODE) {
27382
27383 /*
27384 * Init the node-info.
27385 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000027386 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027387 if (xmlSchemaValidatorPushElem(vctxt) == -1)
27388 goto internal_error;
27389 ielem = vctxt->inode;
27390 ielem->node = node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027391 ielem->nodeLine = node->line;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027392 ielem->localName = node->name;
27393 if (node->ns != NULL)
27394 ielem->nsName = node->ns->href;
27395 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27396 /*
27397 * Register attributes.
27398 * DOC VAL TODO: We do not register namespace declaration
27399 * attributes yet.
27400 */
27401 vctxt->nbAttrInfos = 0;
27402 if (node->properties != NULL) {
27403 attr = node->properties;
27404 do {
27405 if (attr->ns != NULL)
27406 nsName = attr->ns->href;
27407 else
27408 nsName = NULL;
27409 ret = xmlSchemaValidatorPushAttribute(vctxt,
27410 (xmlNodePtr) attr,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027411 /*
27412 * Note that we give it the line number of the
27413 * parent element.
27414 */
27415 ielem->nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027416 attr->name, nsName, 0,
27417 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27418 if (ret == -1) {
27419 VERROR_INT("xmlSchemaDocWalk",
27420 "calling xmlSchemaValidatorPushAttribute()");
27421 goto internal_error;
27422 }
27423 attr = attr->next;
27424 } while (attr);
27425 }
27426 /*
27427 * Validate the element.
27428 */
27429 ret = xmlSchemaValidateElem(vctxt);
27430 if (ret != 0) {
27431 if (ret == -1) {
27432 VERROR_INT("xmlSchemaDocWalk",
27433 "calling xmlSchemaValidateElem()");
27434 goto internal_error;
27435 }
27436 /*
27437 * Don't stop validation; just skip the content
27438 * of this element.
27439 */
27440 goto leave_node;
27441 }
27442 if ((vctxt->skipDepth != -1) &&
27443 (vctxt->depth >= vctxt->skipDepth))
27444 goto leave_node;
27445 } else if ((node->type == XML_TEXT_NODE) ||
27446 (node->type == XML_CDATA_SECTION_NODE)) {
27447 /*
27448 * Process character content.
27449 */
27450 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27451 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27452 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27453 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27454 if (ret < 0) {
27455 VERROR_INT("xmlSchemaVDocWalk",
27456 "calling xmlSchemaVPushText()");
27457 goto internal_error;
27458 }
27459 /*
27460 * DOC VAL TODO: Should we skip further validation of the
27461 * element content here?
27462 */
27463 } else if ((node->type == XML_ENTITY_NODE) ||
27464 (node->type == XML_ENTITY_REF_NODE)) {
27465 /*
27466 * DOC VAL TODO: What to do with entities?
27467 */
27468 TODO
27469 } else {
27470 goto leave_node;
27471 /*
27472 * DOC VAL TODO: XInclude nodes, etc.
27473 */
27474 }
27475 /*
27476 * Walk the doc.
27477 */
27478 if (node->children != NULL) {
27479 node = node->children;
27480 continue;
27481 }
27482leave_node:
27483 if (node->type == XML_ELEMENT_NODE) {
27484 /*
27485 * Leaving the scope of an element.
27486 */
27487 if (node != vctxt->inode->node) {
27488 VERROR_INT("xmlSchemaVDocWalk",
27489 "element position mismatch");
27490 goto internal_error;
27491 }
27492 ret = xmlSchemaValidatorPopElem(vctxt);
27493 if (ret != 0) {
27494 if (ret < 0) {
27495 VERROR_INT("xmlSchemaVDocWalk",
27496 "calling xmlSchemaValidatorPopElem()");
27497 goto internal_error;
27498 }
27499 }
27500 if (node == valRoot)
27501 goto exit;
27502 }
27503next_sibling:
27504 if (node->next != NULL)
27505 node = node->next;
27506 else {
27507 node = node->parent;
27508 goto leave_node;
27509 }
27510 }
27511
27512exit:
27513 return (ret);
27514internal_error:
27515 return (-1);
27516}
27517
27518static int
Daniel Veillardf10ae122005-07-10 19:03:16 +000027519xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027520 /*
27521 * Some initialization.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027522 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027523 vctxt->err = 0;
27524 vctxt->nberrors = 0;
27525 vctxt->depth = -1;
27526 vctxt->skipDepth = -1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027527 vctxt->xsiAssemble = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027528 vctxt->hasKeyrefs = 0;
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000027529#ifdef ENABLE_IDC_NODE_TABLES_TEST
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027530 vctxt->createIDCNodeTables = 1;
27531#else
27532 vctxt->createIDCNodeTables = 0;
27533#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027534 /*
27535 * Create a schema + parser if necessary.
27536 */
27537 if (vctxt->schema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027538 xmlSchemaParserCtxtPtr pctxt;
27539
27540 vctxt->xsiAssemble = 1;
27541 /*
27542 * If not schema was given then we will create a schema
27543 * dynamically using XSI schema locations.
27544 *
27545 * Create the schema parser context.
27546 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027547 if ((vctxt->pctxt == NULL) &&
27548 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
27549 return (-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027550 pctxt = vctxt->pctxt;
27551 pctxt->xsiAssemble = 1;
27552 /*
27553 * Create the schema.
27554 */
27555 vctxt->schema = xmlSchemaNewSchema(pctxt);
27556 if (vctxt->schema == NULL)
27557 return (-1);
27558 /*
27559 * Create the schema construction context.
27560 */
27561 pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
27562 if (pctxt->constructor == NULL)
27563 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000027564 pctxt->constructor->mainSchema = vctxt->schema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027565 /*
27566 * Take ownership of the constructor to be able to free it.
27567 */
27568 pctxt->ownsConstructor = 1;
27569 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027570 /*
27571 * Augment the IDC definitions.
27572 */
27573 if (vctxt->schema->idcDef != NULL) {
27574 xmlHashScan(vctxt->schema->idcDef,
27575 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
27576 }
Daniel Veillardf10ae122005-07-10 19:03:16 +000027577 return(0);
27578}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027579
Daniel Veillardf10ae122005-07-10 19:03:16 +000027580static void
27581xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027582 if (vctxt->xsiAssemble) {
27583 if (vctxt->schema != NULL) {
27584 xmlSchemaFree(vctxt->schema);
27585 vctxt->schema = NULL;
27586 }
27587 }
27588 xmlSchemaClearValidCtxt(vctxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +000027589}
27590
27591static int
27592xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
27593{
27594 int ret = 0;
27595
27596 if (xmlSchemaPreRun(vctxt) < 0)
27597 return(-1);
27598
27599 if (vctxt->doc != NULL) {
27600 /*
27601 * Tree validation.
27602 */
27603 ret = xmlSchemaVDocWalk(vctxt);
27604#ifdef LIBXML_READER_ENABLED
27605 } else if (vctxt->reader != NULL) {
27606 /*
27607 * XML Reader validation.
27608 */
27609#ifdef XML_SCHEMA_READER_ENABLED
27610 ret = xmlSchemaVReaderWalk(vctxt);
27611#endif
27612#endif
27613 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
27614 /*
27615 * SAX validation.
27616 */
27617 ret = xmlParseDocument(vctxt->parserCtxt);
27618 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027619 VERROR_INT("xmlSchemaVStart",
Daniel Veillardf10ae122005-07-10 19:03:16 +000027620 "no instance to validate");
27621 ret = -1;
27622 }
27623
27624 xmlSchemaPostRun(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027625 if (ret == 0)
27626 ret = vctxt->err;
27627 return (ret);
27628}
27629
27630/**
27631 * xmlSchemaValidateOneElement:
27632 * @ctxt: a schema validation context
27633 * @elem: an element node
27634 *
27635 * Validate a branch of a tree, starting with the given @elem.
27636 *
27637 * Returns 0 if the element and its subtree is valid, a positive error
27638 * code number otherwise and -1 in case of an internal or API error.
27639 */
27640int
27641xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
27642{
27643 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
27644 return (-1);
27645
27646 if (ctxt->schema == NULL)
27647 return (-1);
27648
27649 ctxt->doc = elem->doc;
27650 ctxt->node = elem;
27651 ctxt->validationRoot = elem;
27652 return(xmlSchemaVStart(ctxt));
27653}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027654
Daniel Veillard259f0df2004-08-18 09:13:18 +000027655/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027656 * xmlSchemaValidateDoc:
27657 * @ctxt: a schema validation context
27658 * @doc: a parsed document tree
27659 *
27660 * Validate a document tree in memory.
27661 *
27662 * Returns 0 if the document is schemas valid, a positive error code
27663 * number otherwise and -1 in case of internal or API error.
27664 */
27665int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027666xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
27667{
Daniel Veillard4255d502002-04-16 15:50:10 +000027668 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027669 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000027670
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027671 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027672 ctxt->node = xmlDocGetRootElement(doc);
27673 if (ctxt->node == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027674 xmlSchemaCustomErr(ACTXT_CAST ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027675 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
27676 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027677 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027678 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027679 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027680 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027681 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000027682}
27683
Daniel Veillardcdc82732005-07-08 15:04:06 +000027684
27685/************************************************************************
27686 * *
27687 * Function and data for SAX streaming API *
27688 * *
27689 ************************************************************************/
27690typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
27691typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
27692
27693struct _xmlSchemaSplitSAXData {
27694 xmlSAXHandlerPtr user_sax;
27695 void *user_data;
27696 xmlSchemaValidCtxtPtr ctxt;
27697 xmlSAXHandlerPtr schemas_sax;
27698};
27699
Daniel Veillard971771e2005-07-09 17:32:57 +000027700#define XML_SAX_PLUG_MAGIC 0xdc43ba21
27701
27702struct _xmlSchemaSAXPlug {
27703 unsigned int magic;
27704
27705 /* the original callbacks informations */
27706 xmlSAXHandlerPtr *user_sax_ptr;
27707 xmlSAXHandlerPtr user_sax;
27708 void **user_data_ptr;
27709 void *user_data;
27710
27711 /* the block plugged back and validation informations */
27712 xmlSAXHandler schemas_sax;
27713 xmlSchemaValidCtxtPtr ctxt;
27714};
27715
Daniel Veillardcdc82732005-07-08 15:04:06 +000027716/* All those functions just bounces to the user provided SAX handlers */
27717static void
27718internalSubsetSplit(void *ctx, const xmlChar *name,
27719 const xmlChar *ExternalID, const xmlChar *SystemID)
27720{
Daniel Veillard971771e2005-07-09 17:32:57 +000027721 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027722 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27723 (ctxt->user_sax->internalSubset != NULL))
27724 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
27725 SystemID);
27726}
27727
27728static int
27729isStandaloneSplit(void *ctx)
27730{
Daniel Veillard971771e2005-07-09 17:32:57 +000027731 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027732 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27733 (ctxt->user_sax->isStandalone != NULL))
27734 return(ctxt->user_sax->isStandalone(ctxt->user_data));
27735 return(0);
27736}
27737
27738static int
27739hasInternalSubsetSplit(void *ctx)
27740{
Daniel Veillard971771e2005-07-09 17:32:57 +000027741 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027742 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27743 (ctxt->user_sax->hasInternalSubset != NULL))
27744 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
27745 return(0);
27746}
27747
27748static int
27749hasExternalSubsetSplit(void *ctx)
27750{
Daniel Veillard971771e2005-07-09 17:32:57 +000027751 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027752 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27753 (ctxt->user_sax->hasExternalSubset != NULL))
27754 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
27755 return(0);
27756}
27757
27758static void
27759externalSubsetSplit(void *ctx, const xmlChar *name,
27760 const xmlChar *ExternalID, const xmlChar *SystemID)
27761{
Daniel Veillard971771e2005-07-09 17:32:57 +000027762 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027763 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27764 (ctxt->user_sax->internalSubset != NULL))
27765 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
27766 SystemID);
27767}
27768
27769static xmlParserInputPtr
27770resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
27771{
Daniel Veillard971771e2005-07-09 17:32:57 +000027772 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027773 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27774 (ctxt->user_sax->resolveEntity != NULL))
27775 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
27776 systemId));
27777 return(NULL);
27778}
27779
27780static xmlEntityPtr
27781getEntitySplit(void *ctx, const xmlChar *name)
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->getEntity != NULL))
27786 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
27787 return(NULL);
27788}
27789
27790static xmlEntityPtr
27791getParameterEntitySplit(void *ctx, const xmlChar *name)
27792{
Daniel Veillard971771e2005-07-09 17:32:57 +000027793 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027794 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27795 (ctxt->user_sax->getParameterEntity != NULL))
27796 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
27797 return(NULL);
27798}
27799
27800
27801static void
27802entityDeclSplit(void *ctx, const xmlChar *name, int type,
27803 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
27804{
Daniel Veillard971771e2005-07-09 17:32:57 +000027805 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027806 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27807 (ctxt->user_sax->entityDecl != NULL))
27808 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
27809 systemId, content);
27810}
27811
27812static void
27813attributeDeclSplit(void *ctx, const xmlChar * elem,
27814 const xmlChar * name, int type, int def,
27815 const xmlChar * defaultValue, xmlEnumerationPtr tree)
27816{
Daniel Veillard971771e2005-07-09 17:32:57 +000027817 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027818 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27819 (ctxt->user_sax->attributeDecl != NULL)) {
27820 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
27821 def, defaultValue, tree);
27822 } else {
27823 xmlFreeEnumeration(tree);
27824 }
27825}
27826
27827static void
27828elementDeclSplit(void *ctx, const xmlChar *name, int type,
27829 xmlElementContentPtr content)
27830{
Daniel Veillard971771e2005-07-09 17:32:57 +000027831 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027832 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27833 (ctxt->user_sax->elementDecl != NULL))
27834 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
27835}
27836
27837static void
27838notationDeclSplit(void *ctx, const xmlChar *name,
27839 const xmlChar *publicId, const xmlChar *systemId)
27840{
Daniel Veillard971771e2005-07-09 17:32:57 +000027841 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027842 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27843 (ctxt->user_sax->notationDecl != NULL))
27844 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
27845 systemId);
27846}
27847
27848static void
27849unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
27850 const xmlChar *publicId, const xmlChar *systemId,
27851 const xmlChar *notationName)
27852{
Daniel Veillard971771e2005-07-09 17:32:57 +000027853 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027854 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27855 (ctxt->user_sax->unparsedEntityDecl != NULL))
27856 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
27857 systemId, notationName);
27858}
27859
27860static void
27861setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
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->setDocumentLocator != NULL))
27866 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
27867}
27868
27869static void
27870startDocumentSplit(void *ctx)
27871{
Daniel Veillard971771e2005-07-09 17:32:57 +000027872 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027873 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27874 (ctxt->user_sax->startDocument != NULL))
27875 ctxt->user_sax->startDocument(ctxt->user_data);
27876}
27877
27878static void
27879endDocumentSplit(void *ctx)
27880{
Daniel Veillard971771e2005-07-09 17:32:57 +000027881 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027882 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27883 (ctxt->user_sax->endDocument != NULL))
27884 ctxt->user_sax->endDocument(ctxt->user_data);
27885}
27886
27887static void
27888processingInstructionSplit(void *ctx, const xmlChar *target,
27889 const xmlChar *data)
27890{
Daniel Veillard971771e2005-07-09 17:32:57 +000027891 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027892 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27893 (ctxt->user_sax->processingInstruction != NULL))
27894 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
27895}
27896
27897static void
27898commentSplit(void *ctx, const xmlChar *value)
27899{
Daniel Veillard971771e2005-07-09 17:32:57 +000027900 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027901 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27902 (ctxt->user_sax->comment != NULL))
27903 ctxt->user_sax->comment(ctxt->user_data, value);
27904}
27905
27906/*
27907 * Varargs error callbacks to the user application, harder ...
27908 */
27909
Daniel Veillardffa3c742005-07-21 13:24:09 +000027910static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027911warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027912 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027913 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27914 (ctxt->user_sax->warning != NULL)) {
27915 TODO
27916 }
27917}
Daniel Veillardffa3c742005-07-21 13:24:09 +000027918static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027919errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027920 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027921 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27922 (ctxt->user_sax->error != NULL)) {
27923 TODO
27924 }
27925}
Daniel Veillardffa3c742005-07-21 13:24:09 +000027926static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027927fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027928 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027929 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27930 (ctxt->user_sax->fatalError != NULL)) {
27931 TODO
27932 }
27933}
27934
27935/*
27936 * Those are function where both the user handler and the schemas handler
27937 * need to be called.
27938 */
27939static void
27940charactersSplit(void *ctx, const xmlChar *ch, int len)
27941{
Daniel Veillard971771e2005-07-09 17:32:57 +000027942 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027943 if (ctxt == NULL)
27944 return;
27945 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
27946 ctxt->user_sax->characters(ctxt->user_data, ch, len);
27947 if (ctxt->ctxt != NULL)
27948 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
27949}
27950
27951static void
27952ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
27953{
Daniel Veillard971771e2005-07-09 17:32:57 +000027954 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027955 if (ctxt == NULL)
27956 return;
27957 if ((ctxt->user_sax != NULL) &&
27958 (ctxt->user_sax->ignorableWhitespace != NULL))
27959 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
27960 if (ctxt->ctxt != NULL)
27961 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
27962}
27963
27964static void
27965cdataBlockSplit(void *ctx, const xmlChar *value, int len)
27966{
Daniel Veillard971771e2005-07-09 17:32:57 +000027967 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027968 if (ctxt == NULL)
27969 return;
27970 if ((ctxt->user_sax != NULL) &&
27971 (ctxt->user_sax->ignorableWhitespace != NULL))
27972 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, value, len);
27973 if (ctxt->ctxt != NULL)
27974 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
27975}
27976
27977static void
27978referenceSplit(void *ctx, const xmlChar *name)
27979{
Daniel Veillard971771e2005-07-09 17:32:57 +000027980 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027981 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27982 (ctxt->user_sax->reference != NULL))
27983 ctxt->user_sax->reference(ctxt->user_data, name);
27984 if (ctxt->ctxt != NULL)
27985 xmlSchemaSAXHandleReference(ctxt->user_data, name);
27986}
27987
27988static void
27989startElementNsSplit(void *ctx, const xmlChar * localname,
27990 const xmlChar * prefix, const xmlChar * URI,
27991 int nb_namespaces, const xmlChar ** namespaces,
27992 int nb_attributes, int nb_defaulted,
27993 const xmlChar ** attributes) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027994 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027995 if (ctxt == NULL)
27996 return;
27997 if ((ctxt->user_sax != NULL) &&
27998 (ctxt->user_sax->startElementNs != NULL))
27999 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28000 URI, nb_namespaces, namespaces,
28001 nb_attributes, nb_defaulted,
28002 attributes);
28003 if (ctxt->ctxt != NULL)
28004 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28005 URI, nb_namespaces, namespaces,
28006 nb_attributes, nb_defaulted,
28007 attributes);
28008}
28009
28010static void
28011endElementNsSplit(void *ctx, const xmlChar * localname,
28012 const xmlChar * prefix, const xmlChar * URI) {
Daniel Veillard971771e2005-07-09 17:32:57 +000028013 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028014 if (ctxt == NULL)
28015 return;
28016 if ((ctxt->user_sax != NULL) &&
28017 (ctxt->user_sax->endElementNs != NULL))
28018 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28019 if (ctxt->ctxt != NULL)
28020 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28021}
28022
Daniel Veillard4255d502002-04-16 15:50:10 +000028023/**
Daniel Veillard971771e2005-07-09 17:32:57 +000028024 * xmlSchemaSAXPlug:
28025 * @ctxt: a schema validation context
Daniel Veillard1f33c4d2005-07-10 21:38:31 +000028026 * @sax: a pointer to the original xmlSAXHandlerPtr
28027 * @user_data: a pointer to the original SAX user data pointer
Daniel Veillard971771e2005-07-09 17:32:57 +000028028 *
28029 * Plug a SAX based validation layer in a SAX parsing event flow.
28030 * The original @saxptr and @dataptr data are replaced by new pointers
28031 * but the calls to the original will be maintained.
28032 *
28033 * Returns a pointer to a data structure needed to unplug the validation layer
28034 * or NULL in case of errors.
28035 */
28036xmlSchemaSAXPlugPtr
28037xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28038 xmlSAXHandlerPtr *sax, void **user_data)
28039{
28040 xmlSchemaSAXPlugPtr ret;
28041 xmlSAXHandlerPtr old_sax;
28042
28043 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28044 return(NULL);
28045
28046 /*
28047 * We only allow to plug into SAX2 event streams
28048 */
28049 old_sax = *sax;
28050 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28051 return(NULL);
28052 if ((old_sax != NULL) &&
28053 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28054 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28055 return(NULL);
28056
28057 /*
28058 * everything seems right allocate the local data needed for that layer
28059 */
28060 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28061 if (ret == NULL) {
28062 return(NULL);
28063 }
28064 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28065 ret->magic = XML_SAX_PLUG_MAGIC;
28066 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28067 ret->ctxt = ctxt;
28068 ret->user_sax_ptr = sax;
28069 ret->user_sax = old_sax;
28070 if (old_sax == NULL) {
28071 /*
28072 * go direct, no need for the split block and functions.
28073 */
28074 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28075 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28076 /*
28077 * Note that we use the same text-function for both, to prevent
28078 * the parser from testing for ignorable whitespace.
28079 */
28080 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28081 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28082
28083 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28084 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28085
28086 ret->user_data = ctxt;
28087 *user_data = ctxt;
28088 } else {
28089 /*
28090 * for each callback unused by Schemas initialize it to the Split
28091 * routine only if non NULL in the user block, this can speed up
28092 * things at the SAX level.
28093 */
28094 if (old_sax->internalSubset != NULL)
28095 ret->schemas_sax.internalSubset = internalSubsetSplit;
28096 if (old_sax->isStandalone != NULL)
28097 ret->schemas_sax.isStandalone = isStandaloneSplit;
28098 if (old_sax->hasInternalSubset != NULL)
28099 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28100 if (old_sax->hasExternalSubset != NULL)
28101 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28102 if (old_sax->resolveEntity != NULL)
28103 ret->schemas_sax.resolveEntity = resolveEntitySplit;
28104 if (old_sax->getEntity != NULL)
28105 ret->schemas_sax.getEntity = getEntitySplit;
28106 if (old_sax->entityDecl != NULL)
28107 ret->schemas_sax.entityDecl = entityDeclSplit;
28108 if (old_sax->notationDecl != NULL)
28109 ret->schemas_sax.notationDecl = notationDeclSplit;
28110 if (old_sax->attributeDecl != NULL)
28111 ret->schemas_sax.attributeDecl = attributeDeclSplit;
28112 if (old_sax->elementDecl != NULL)
28113 ret->schemas_sax.elementDecl = elementDeclSplit;
28114 if (old_sax->unparsedEntityDecl != NULL)
28115 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28116 if (old_sax->setDocumentLocator != NULL)
28117 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28118 if (old_sax->startDocument != NULL)
28119 ret->schemas_sax.startDocument = startDocumentSplit;
28120 if (old_sax->endDocument != NULL)
28121 ret->schemas_sax.endDocument = endDocumentSplit;
28122 if (old_sax->processingInstruction != NULL)
28123 ret->schemas_sax.processingInstruction = processingInstructionSplit;
28124 if (old_sax->comment != NULL)
28125 ret->schemas_sax.comment = commentSplit;
28126 if (old_sax->warning != NULL)
28127 ret->schemas_sax.warning = warningSplit;
28128 if (old_sax->error != NULL)
28129 ret->schemas_sax.error = errorSplit;
28130 if (old_sax->fatalError != NULL)
28131 ret->schemas_sax.fatalError = fatalErrorSplit;
28132 if (old_sax->getParameterEntity != NULL)
28133 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28134 if (old_sax->externalSubset != NULL)
28135 ret->schemas_sax.externalSubset = externalSubsetSplit;
28136
28137 /*
28138 * the 6 schemas callback have to go to the splitter functions
28139 * Note that we use the same text-function for ignorableWhitespace
28140 * if possible, to prevent the parser from testing for ignorable
28141 * whitespace.
28142 */
28143 ret->schemas_sax.characters = charactersSplit;
28144 if ((old_sax->ignorableWhitespace != NULL) &&
28145 (old_sax->ignorableWhitespace != old_sax->characters))
28146 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28147 else
28148 ret->schemas_sax.ignorableWhitespace = charactersSplit;
28149 ret->schemas_sax.cdataBlock = cdataBlockSplit;
28150 ret->schemas_sax.reference = referenceSplit;
28151 ret->schemas_sax.startElementNs = startElementNsSplit;
28152 ret->schemas_sax.endElementNs = endElementNsSplit;
28153
28154 ret->user_data_ptr = user_data;
28155 ret->user_data = *user_data;
28156 *user_data = ret;
28157 }
28158
28159 /*
28160 * plug the pointers back.
28161 */
28162 *sax = &(ret->schemas_sax);
Daniel Veillardf10ae122005-07-10 19:03:16 +000028163 ctxt->sax = *sax;
28164 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28165 xmlSchemaPreRun(ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000028166 return(ret);
28167}
28168
28169/**
28170 * xmlSchemaSAXUnplug:
28171 * @plug: a data structure returned by xmlSchemaSAXPlug
28172 *
28173 * Unplug a SAX based validation layer in a SAX parsing event flow.
28174 * The original pointers used in the call are restored.
28175 *
28176 * Returns 0 in case of success and -1 in case of failure.
28177 */
28178int
28179xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28180{
28181 xmlSAXHandlerPtr *sax;
28182 void **user_data;
28183
28184 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28185 return(-1);
28186 plug->magic = 0;
28187
Daniel Veillardf10ae122005-07-10 19:03:16 +000028188 xmlSchemaPostRun(plug->ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000028189 /* restore the data */
28190 sax = plug->user_sax_ptr;
28191 *sax = plug->user_sax;
28192 if (plug->user_sax != NULL) {
28193 user_data = plug->user_data_ptr;
28194 *user_data = plug->user_data;
28195 }
28196
28197 /* free and return */
28198 xmlFree(plug);
28199 return(0);
28200}
28201
28202/**
Daniel Veillard4255d502002-04-16 15:50:10 +000028203 * xmlSchemaValidateStream:
28204 * @ctxt: a schema validation context
28205 * @input: the input to use for reading the data
28206 * @enc: an optional encoding information
28207 * @sax: a SAX handler for the resulting events
28208 * @user_data: the context to provide to the SAX handler.
28209 *
Daniel Veillardcdc82732005-07-08 15:04:06 +000028210 * Validate an input based on a flow of SAX event from the parser
28211 * and forward the events to the @sax handler with the provided @user_data
28212 * the user provided @sax handler must be a SAX2 one.
Daniel Veillard4255d502002-04-16 15:50:10 +000028213 *
28214 * Returns 0 if the document is schemas valid, a positive error code
28215 * number otherwise and -1 in case of internal or API error.
28216 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028217int
Daniel Veillard4255d502002-04-16 15:50:10 +000028218xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028219 xmlParserInputBufferPtr input, xmlCharEncoding enc,
28220 xmlSAXHandlerPtr sax, void *user_data)
28221{
Daniel Veillard971771e2005-07-09 17:32:57 +000028222 xmlSchemaSAXPlugPtr plug = NULL;
28223 xmlSAXHandlerPtr old_sax = NULL;
28224 xmlParserCtxtPtr pctxt = NULL;
28225 xmlParserInputPtr inputStream = NULL;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028226 int ret;
28227
Daniel Veillard4255d502002-04-16 15:50:10 +000028228 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028229 return (-1);
Daniel Veillardcdc82732005-07-08 15:04:06 +000028230
Daniel Veillardcdc82732005-07-08 15:04:06 +000028231 /*
28232 * prepare the parser
28233 */
28234 pctxt = xmlNewParserCtxt();
28235 if (pctxt == NULL)
28236 return (-1);
28237 old_sax = pctxt->sax;
Daniel Veillard971771e2005-07-09 17:32:57 +000028238 pctxt->sax = sax;
28239 pctxt->userData = user_data;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028240#if 0
28241 if (options)
28242 xmlCtxtUseOptions(pctxt, options);
28243#endif
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000028244 pctxt->linenumbers = 1;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028245
Daniel Veillardf0af8ec2005-07-08 17:27:33 +000028246 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028247 if (inputStream == NULL) {
28248 ret = -1;
28249 goto done;
28250 }
28251 inputPush(pctxt, inputStream);
28252 ctxt->parserCtxt = pctxt;
28253 ctxt->input = input;
28254
28255 /*
Daniel Veillard971771e2005-07-09 17:32:57 +000028256 * Plug the validation and launch the parsing
Daniel Veillardcdc82732005-07-08 15:04:06 +000028257 */
Daniel Veillard971771e2005-07-09 17:32:57 +000028258 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28259 if (plug == NULL) {
28260 ret = -1;
28261 goto done;
28262 }
28263 ctxt->input = input;
28264 ctxt->enc = enc;
28265 ctxt->sax = pctxt->sax;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028266 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28267 ret = xmlSchemaVStart(ctxt);
28268
28269 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28270 ret = ctxt->parserCtxt->errNo;
28271 if (ret == 0)
28272 ret = 1;
28273 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028274
28275done:
Daniel Veillard971771e2005-07-09 17:32:57 +000028276 ctxt->parserCtxt = NULL;
28277 ctxt->sax = NULL;
28278 ctxt->input = NULL;
28279 if (plug != NULL) {
28280 xmlSchemaSAXUnplug(plug);
28281 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028282 /* cleanup */
Daniel Veillard971771e2005-07-09 17:32:57 +000028283 if (pctxt != NULL) {
28284 pctxt->sax = old_sax;
28285 xmlFreeParserCtxt(pctxt);
28286 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028287 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000028288}
28289
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028290/**
28291 * xmlSchemaValidateFile:
28292 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000028293 * @filename: the URI of the instance
28294 * @options: a future set of options, currently unused
28295 *
28296 * Do a schemas validation of the given resource, it will use the
28297 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028298 *
28299 * Returns 0 if the document is valid, a positive error code
28300 * number otherwise and -1 in case of an internal or API error.
28301 */
28302int
28303xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000028304 const char * filename,
28305 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028306{
28307 int ret;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028308 xmlParserInputBufferPtr input;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028309
28310 if ((ctxt == NULL) || (filename == NULL))
28311 return (-1);
28312
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028313 input = xmlParserInputBufferCreateFilename(filename,
28314 XML_CHAR_ENCODING_NONE);
28315 if (input == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028316 return (-1);
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028317 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28318 NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028319 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000028320}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028321
Daniel Veillard5d4644e2005-04-01 13:11:58 +000028322#define bottom_xmlschemas
28323#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000028324#endif /* LIBXML_SCHEMAS_ENABLED */