blob: d64949d1353df7e2f8dc5f94c873dd10f39a4fff [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
Daniel Veillard14b56432006-03-09 18:41:40 +00002235 if (actxt == NULL)
2236 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002237 msg = xmlStrdup(BAD_CAST "Internal error: ");
2238 msg = xmlStrcat(msg, BAD_CAST funcName);
2239 msg = xmlStrcat(msg, BAD_CAST ", ");
2240 msg = xmlStrcat(msg, BAD_CAST message);
2241 msg = xmlStrcat(msg, BAD_CAST ".\n");
2242
2243 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2244 xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002245 (const char *) msg, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002246
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002247 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002248 xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002249 (const char *) msg, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002250
2251 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002252}
2253
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002254static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002255xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2256 const char *funcName,
2257 const char *message)
2258{
2259 xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2260}
2261
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002262#if 0
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002263static void
2264xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2265 const char *funcName,
2266 const char *message,
2267 const xmlChar *str1,
2268 const xmlChar *str2)
2269{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002270 xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002271 str1, str2);
2272}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002273#endif
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002274
2275static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002276xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2277 xmlParserErrors error,
2278 xmlNodePtr node,
2279 xmlSchemaBasicItemPtr item,
2280 const char *message,
2281 const xmlChar *str1, const xmlChar *str2,
2282 const xmlChar *str3, const xmlChar *str4)
2283{
2284 xmlChar *msg = NULL;
2285
2286 if ((node == NULL) && (item != NULL) &&
2287 (actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2288 node = WXS_ITEM_NODE(item);
2289 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2290 msg = xmlStrcat(msg, BAD_CAST ": ");
2291 } else
2292 xmlSchemaFormatNodeForError(&msg, actxt, node);
2293 msg = xmlStrcat(msg, (const xmlChar *) message);
2294 msg = xmlStrcat(msg, BAD_CAST ".\n");
2295 xmlSchemaErr4(actxt, error, node,
2296 (const char *) msg, str1, str2, str3, str4);
2297 FREE_AND_NULL(msg)
2298}
2299
2300static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002301xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2302 xmlParserErrors error,
2303 xmlNodePtr node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002304 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002305 const char *message,
2306 const xmlChar *str1,
2307 const xmlChar *str2)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002308{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002309 xmlSchemaCustomErr4(actxt, error, node, item,
2310 message, str1, str2, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002311}
2312
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002313
2314
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002315static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002316xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2317 xmlParserErrors error,
2318 xmlNodePtr node,
2319 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2320 const char *message,
2321 const xmlChar *str1,
2322 const xmlChar *str2,
2323 const xmlChar *str3)
2324{
2325 xmlChar *msg = NULL;
2326
2327 xmlSchemaFormatNodeForError(&msg, actxt, node);
2328 msg = xmlStrcat(msg, (const xmlChar *) message);
2329 msg = xmlStrcat(msg, BAD_CAST ".\n");
2330
2331 /* URGENT TODO: Set the error code to something sane. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002332 xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2333 (const char *) msg, str1, str2, str3, NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002334
2335 FREE_AND_NULL(msg)
2336}
2337
2338
2339
2340static void
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002341xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2342 xmlParserErrors error,
2343 xmlSchemaPSVIIDCNodePtr idcNode,
2344 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2345 const char *message,
2346 const xmlChar *str1,
2347 const xmlChar *str2)
2348{
2349 xmlChar *msg = NULL, *qname = NULL;
2350
2351 msg = xmlStrdup(BAD_CAST "Element '%s': ");
2352 msg = xmlStrcat(msg, (const xmlChar *) message);
2353 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002354 xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002355 error, NULL, idcNode->nodeLine, (const char *) msg,
2356 xmlSchemaFormatQName(&qname,
2357 vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2358 vctxt->nodeQNames->items[idcNode->nodeQNameID]),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002359 str1, str2, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002360 FREE_AND_NULL(qname);
2361 FREE_AND_NULL(msg);
2362}
2363
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002364static int
2365xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2366 xmlNodePtr node)
2367{
2368 if (node != NULL)
2369 return (node->type);
2370 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2371 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2372 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2373 return (-1);
2374}
2375
2376static int
2377xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2378{
2379 switch (item->type) {
2380 case XML_SCHEMA_TYPE_COMPLEX:
2381 case XML_SCHEMA_TYPE_SIMPLE:
2382 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2383 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002384 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002385 case XML_SCHEMA_TYPE_GROUP:
2386 return (1);
2387 case XML_SCHEMA_TYPE_ELEMENT:
2388 if ( ((xmlSchemaElementPtr) item)->flags &
2389 XML_SCHEMAS_ELEM_GLOBAL)
2390 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002391 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002392 case XML_SCHEMA_TYPE_ATTRIBUTE:
2393 if ( ((xmlSchemaAttributePtr) item)->flags &
2394 XML_SCHEMAS_ATTR_GLOBAL)
2395 return(1);
2396 break;
2397 /* Note that attribute groups are always global. */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002398 default:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002399 return(1);
2400 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002401 return (0);
2402}
2403
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002404static void
2405xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2406 xmlParserErrors error,
2407 xmlNodePtr node,
2408 const xmlChar *value,
2409 xmlSchemaTypePtr type,
2410 int displayValue)
2411{
2412 xmlChar *msg = NULL;
2413
2414 xmlSchemaFormatNodeForError(&msg, actxt, node);
2415
2416 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2417 XML_ATTRIBUTE_NODE))
2418 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2419 else
2420 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2421 "value of ");
2422
2423 if (! xmlSchemaIsGlobalItem(type))
2424 msg = xmlStrcat(msg, BAD_CAST "the local ");
2425 else
2426 msg = xmlStrcat(msg, BAD_CAST "the ");
2427
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002428 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002429 msg = xmlStrcat(msg, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002430 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002431 msg = xmlStrcat(msg, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002432 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002433 msg = xmlStrcat(msg, BAD_CAST "union type");
2434
2435 if (xmlSchemaIsGlobalItem(type)) {
2436 xmlChar *str = NULL;
2437 msg = xmlStrcat(msg, BAD_CAST " '");
2438 if (type->builtInType != 0) {
2439 msg = xmlStrcat(msg, BAD_CAST "xs:");
2440 msg = xmlStrcat(msg, type->name);
2441 } else
2442 msg = xmlStrcat(msg,
2443 xmlSchemaFormatQName(&str,
2444 type->targetNamespace, type->name));
2445 msg = xmlStrcat(msg, BAD_CAST "'");
2446 FREE_AND_NULL(str);
2447 }
2448 msg = xmlStrcat(msg, BAD_CAST ".\n");
2449 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2450 XML_ATTRIBUTE_NODE))
2451 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2452 else
2453 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2454 FREE_AND_NULL(msg)
2455}
2456
Daniel Veillardc0826a72004-08-10 14:17:33 +00002457static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002458xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2459 xmlSchemaNodeInfoPtr ni,
2460 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002461{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002462 if (node != NULL) {
2463 if (node->ns != NULL)
2464 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2465 else
2466 return (xmlSchemaFormatQName(str, NULL, node->name));
2467 } else if (ni != NULL)
2468 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2469 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002470}
2471
Daniel Veillardc0826a72004-08-10 14:17:33 +00002472static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002473xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2474 xmlParserErrors error,
2475 xmlSchemaAttrInfoPtr ni,
2476 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002477{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002478 xmlChar *msg = NULL, *str = NULL;
2479
2480 xmlSchemaFormatNodeForError(&msg, actxt, node);
2481 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2482 xmlSchemaErr(actxt, error, node, (const char *) msg,
2483 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2484 NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002485 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002486 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002487}
2488
Daniel Veillardc0826a72004-08-10 14:17:33 +00002489static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002490xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2491 xmlParserErrors error,
2492 xmlNodePtr node,
2493 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002494 const char *message,
2495 int nbval,
2496 int nbneg,
2497 xmlChar **values)
2498{
2499 xmlChar *str = NULL, *msg = NULL;
2500 xmlChar *localName, *nsName;
2501 const xmlChar *cur, *end;
Daniel Veillard6a0baa02005-12-10 11:11:12 +00002502 int i;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002503
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002504 xmlSchemaFormatNodeForError(&msg, actxt, node);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002505 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002506 msg = xmlStrcat(msg, BAD_CAST ".");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002507 /*
2508 * Note that is does not make sense to report that we have a
2509 * wildcard here, since the wildcard might be unfolded into
2510 * multiple transitions.
2511 */
2512 if (nbval + nbneg > 0) {
2513 if (nbval + nbneg > 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002514 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002515 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002516 str = xmlStrdup(BAD_CAST " Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002517 nsName = NULL;
2518
2519 for (i = 0; i < nbval + nbneg; i++) {
2520 cur = values[i];
Daniel Veillard77005e62005-07-19 16:26:18 +00002521 if (cur == NULL)
2522 continue;
2523 if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2524 (cur[3] == ' ')) {
Daniel Veillard77005e62005-07-19 16:26:18 +00002525 cur += 4;
Daniel Veillard6e65e152005-08-09 11:09:52 +00002526 str = xmlStrcat(str, BAD_CAST "##other");
Daniel Veillard77005e62005-07-19 16:26:18 +00002527 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002528 /*
2529 * Get the local name.
2530 */
2531 localName = NULL;
2532
2533 end = cur;
2534 if (*end == '*') {
2535 localName = xmlStrdup(BAD_CAST "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00002536 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002537 } else {
2538 while ((*end != 0) && (*end != '|'))
2539 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002540 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002541 }
2542 if (*end != 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00002543 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002544 /*
2545 * Skip "*|*" if they come with negated expressions, since
2546 * they represent the same negated wildcard.
2547 */
2548 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2549 /*
2550 * Get the namespace name.
2551 */
2552 cur = end;
2553 if (*end == '*') {
2554 nsName = xmlStrdup(BAD_CAST "{*}");
2555 } else {
2556 while (*end != 0)
2557 end++;
2558
2559 if (i >= nbval)
2560 nsName = xmlStrdup(BAD_CAST "{##other:");
2561 else
2562 nsName = xmlStrdup(BAD_CAST "{");
2563
2564 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2565 nsName = xmlStrcat(nsName, BAD_CAST "}");
2566 }
2567 str = xmlStrcat(str, BAD_CAST nsName);
2568 FREE_AND_NULL(nsName)
2569 } else {
2570 FREE_AND_NULL(localName);
2571 continue;
2572 }
2573 }
2574 str = xmlStrcat(str, BAD_CAST localName);
2575 FREE_AND_NULL(localName);
2576
2577 if (i < nbval + nbneg -1)
2578 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00002579 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002580 str = xmlStrcat(str, BAD_CAST " ).\n");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002581 msg = xmlStrcat(msg, BAD_CAST str);
2582 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002583 } else
2584 msg = xmlStrcat(msg, BAD_CAST "\n");
2585 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002586 xmlFree(msg);
2587}
2588
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002589static void
2590xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2591 xmlParserErrors error,
2592 xmlNodePtr node,
2593 const xmlChar *value,
2594 unsigned long length,
2595 xmlSchemaTypePtr type,
2596 xmlSchemaFacetPtr facet,
2597 const char *message,
2598 const xmlChar *str1,
2599 const xmlChar *str2)
2600{
2601 xmlChar *str = NULL, *msg = NULL;
2602 xmlSchemaTypeType facetType;
2603 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2604
2605 xmlSchemaFormatNodeForError(&msg, actxt, node);
2606 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2607 facetType = XML_SCHEMA_FACET_ENUMERATION;
2608 /*
2609 * If enumerations are validated, one must not expect the
2610 * facet to be given.
2611 */
2612 } else
2613 facetType = facet->type;
2614 msg = xmlStrcat(msg, BAD_CAST "[");
2615 msg = xmlStrcat(msg, BAD_CAST "facet '");
2616 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2617 msg = xmlStrcat(msg, BAD_CAST "'] ");
2618 if (message == NULL) {
2619 /*
2620 * Use a default message.
2621 */
2622 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2623 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2624 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2625
2626 char len[25], actLen[25];
2627
2628 /* FIXME, TODO: What is the max expected string length of the
2629 * this value?
2630 */
2631 if (nodeType == XML_ATTRIBUTE_NODE)
2632 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2633 else
2634 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2635
2636 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2637 snprintf(actLen, 24, "%lu", length);
2638
2639 if (facetType == XML_SCHEMA_FACET_LENGTH)
2640 msg = xmlStrcat(msg,
2641 BAD_CAST "this differs from the allowed length of '%s'.\n");
2642 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2643 msg = xmlStrcat(msg,
2644 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2645 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2646 msg = xmlStrcat(msg,
2647 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2648
2649 if (nodeType == XML_ATTRIBUTE_NODE)
2650 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2651 value, (const xmlChar *) actLen, (const xmlChar *) len);
2652 else
2653 xmlSchemaErr(actxt, error, node, (const char *) msg,
2654 (const xmlChar *) actLen, (const xmlChar *) len);
2655
2656 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2657 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2658 "of the set {%s}.\n");
2659 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2660 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2661 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2662 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2663 "by the pattern '%s'.\n");
2664 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2665 facet->value);
2666 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2667 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2668 "minimum value allowed ('%s').\n");
2669 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2670 facet->value);
2671 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2672 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2673 "maximum value allowed ('%s').\n");
2674 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2675 facet->value);
2676 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00002677 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002678 "'%s'.\n");
2679 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2680 facet->value);
2681 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00002682 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002683 "'%s'.\n");
2684 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2685 facet->value);
2686 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2687 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2688 "digits than are allowed ('%s').\n");
2689 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2690 facet->value);
2691 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2692 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2693 "digits than are allowed ('%s').\n");
2694 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2695 facet->value);
2696 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2697 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2698 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2699 } else {
2700 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2701 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2702 }
2703 } else {
2704 msg = xmlStrcat(msg, (const xmlChar *) message);
2705 msg = xmlStrcat(msg, BAD_CAST ".\n");
2706 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2707 }
2708 FREE_AND_NULL(str)
2709 xmlFree(msg);
2710}
2711
2712#define VERROR(err, type, msg) \
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002713 xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002714
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002715#define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002716
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002717#define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2718#define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002719
2720#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2721
2722
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002723/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00002724 * xmlSchemaPMissingAttrErr:
2725 * @ctxt: the schema validation context
2726 * @ownerDes: the designation of the owner
2727 * @ownerName: the name of the owner
2728 * @ownerItem: the owner as a schema object
2729 * @ownerElem: the owner as an element node
2730 * @node: the parent element node of the missing attribute node
2731 * @type: the corresponding type of the attribute node
2732 *
2733 * Reports an illegal attribute.
2734 */
2735static void
2736xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002737 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002738 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002739 xmlNodePtr ownerElem,
2740 const char *name,
2741 const char *message)
2742{
2743 xmlChar *des = NULL;
2744
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002745 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2746
Daniel Veillardc0826a72004-08-10 14:17:33 +00002747 if (message != NULL)
2748 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002749 else
2750 xmlSchemaPErr(ctxt, ownerElem, error,
2751 "%s: The attribute '%s' is required but missing.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002752 BAD_CAST des, BAD_CAST name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002753 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002754}
2755
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002756
Daniel Veillardc0826a72004-08-10 14:17:33 +00002757/**
2758 * xmlSchemaPResCompAttrErr:
2759 * @ctxt: the schema validation context
2760 * @error: the error code
2761 * @ownerDes: the designation of the owner
2762 * @ownerItem: the owner as a schema object
2763 * @ownerElem: the owner as an element node
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002764 * @name: the name of the attribute holding the QName
Daniel Veillardc0826a72004-08-10 14:17:33 +00002765 * @refName: the referenced local name
2766 * @refURI: the referenced namespace URI
2767 * @message: optional message
2768 *
2769 * Used to report QName attribute values that failed to resolve
2770 * to schema components.
2771 */
2772static void
2773xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002774 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002775 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002776 xmlNodePtr ownerElem,
2777 const char *name,
2778 const xmlChar *refName,
2779 const xmlChar *refURI,
2780 xmlSchemaTypeType refType,
2781 const char *refTypeStr)
2782{
2783 xmlChar *des = NULL, *strA = NULL;
2784
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002785 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002786 if (refTypeStr == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002787 refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002788 xmlSchemaPErrExt(ctxt, ownerElem, error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002789 NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002790 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2791 "%s.\n", BAD_CAST des, BAD_CAST name,
2792 xmlSchemaFormatQName(&strA, refURI, refName),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002793 BAD_CAST refTypeStr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002794 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002795 FREE_AND_NULL(strA)
2796}
2797
William M. Brack2f2a6632004-08-20 23:09:47 +00002798/**
2799 * xmlSchemaPCustomAttrErr:
2800 * @ctxt: the schema parser context
2801 * @error: the error code
2802 * @ownerDes: the designation of the owner
2803 * @ownerItem: the owner as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002804 * @attr: the illegal attribute node
William M. Brack2f2a6632004-08-20 23:09:47 +00002805 *
2806 * Reports an illegal attribute during the parse.
2807 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002808static void
2809xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002810 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002811 xmlChar **ownerDes,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002812 xmlSchemaBasicItemPtr ownerItem,
William M. Brack2f2a6632004-08-20 23:09:47 +00002813 xmlAttrPtr attr,
2814 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002815{
2816 xmlChar *des = NULL;
2817
2818 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002819 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002820 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002821 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002822 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002823 } else
2824 des = *ownerDes;
Daniel Veillard14b56432006-03-09 18:41:40 +00002825 if (attr == NULL) {
2826 xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2827 "%s, attribute '%s': %s.\n",
Daniel Veillardaac7c682006-03-10 13:40:16 +00002828 BAD_CAST des, (const xmlChar *) "Unknown",
2829 (const xmlChar *) msg, NULL, NULL);
Daniel Veillard14b56432006-03-09 18:41:40 +00002830 } else {
2831 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2832 "%s, attribute '%s': %s.\n",
2833 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2834 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00002835 if (ownerDes == NULL)
2836 FREE_AND_NULL(des);
2837}
2838
2839/**
2840 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002841 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002842 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002843 * @ownerDes: the designation of the attribute's owner
2844 * @ownerItem: the attribute's owner item
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002845 * @attr: the illegal attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00002846 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002847 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002848 */
2849static void
2850xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002851 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002852 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002853 xmlAttrPtr attr)
2854{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002855 xmlChar *strA = NULL, *strB = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002856
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002857 xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2858 xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2859 "%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2860 xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2861 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002862 FREE_AND_NULL(strA);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002863 FREE_AND_NULL(strB);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002864}
2865
William M. Brack2f2a6632004-08-20 23:09:47 +00002866/**
2867 * xmlSchemaPCustomErr:
2868 * @ctxt: the schema parser context
2869 * @error: the error code
2870 * @itemDes: the designation of the schema item
2871 * @item: the schema item
2872 * @itemElem: the node of the schema item
2873 * @message: the error message
2874 * @str1: an optional param for the error message
2875 * @str2: an optional param for the error message
2876 * @str3: an optional param for the error message
2877 *
2878 * Reports an error during parsing.
2879 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002880static void
2881xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002882 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002883 xmlSchemaBasicItemPtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002884 xmlNodePtr itemElem,
2885 const char *message,
2886 const xmlChar *str1,
2887 const xmlChar *str2,
2888 const xmlChar *str3)
2889{
2890 xmlChar *des = NULL, *msg = NULL;
2891
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002892 xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002893 msg = xmlStrdup(BAD_CAST "%s: ");
2894 msg = xmlStrcat(msg, (const xmlChar *) message);
2895 msg = xmlStrcat(msg, BAD_CAST ".\n");
2896 if ((itemElem == NULL) && (item != NULL))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002897 itemElem = WXS_ITEM_NODE(item);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002898 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002899 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002900 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002901 FREE_AND_NULL(msg);
2902}
2903
William M. Brack2f2a6632004-08-20 23:09:47 +00002904/**
2905 * xmlSchemaPCustomErr:
2906 * @ctxt: the schema parser context
2907 * @error: the error code
2908 * @itemDes: the designation of the schema item
2909 * @item: the schema item
2910 * @itemElem: the node of the schema item
2911 * @message: the error message
2912 * @str1: the optional param for the error message
2913 *
2914 * Reports an error during parsing.
2915 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002916static void
2917xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002918 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002919 xmlSchemaBasicItemPtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002920 xmlNodePtr itemElem,
2921 const char *message,
2922 const xmlChar *str1)
2923{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002924 xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002925 str1, NULL, NULL);
2926}
2927
William M. Brack2f2a6632004-08-20 23:09:47 +00002928/**
2929 * xmlSchemaPAttrUseErr:
2930 * @ctxt: the schema parser context
2931 * @error: the error code
2932 * @itemDes: the designation of the schema type
2933 * @item: the schema type
2934 * @itemElem: the node of the schema type
2935 * @attr: the invalid schema attribute
2936 * @message: the error message
2937 * @str1: the optional param for the error message
2938 *
2939 * Reports an attribute use error during parsing.
2940 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002941static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002942xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002943 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002944 xmlNodePtr node,
2945 xmlSchemaBasicItemPtr ownerItem,
2946 const xmlSchemaAttributeUsePtr attruse,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002947 const char *message,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002948 const xmlChar *str1, const xmlChar *str2,
2949 const xmlChar *str3,const xmlChar *str4)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002950{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002951 xmlChar *str = NULL, *msg = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002952
2953 xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
2954 msg = xmlStrcat(msg, BAD_CAST ", ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002955 msg = xmlStrcat(msg,
2956 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002957 WXS_BASIC_CAST attruse, NULL));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002958 FREE_AND_NULL(str);
2959 msg = xmlStrcat(msg, BAD_CAST ": ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002960 msg = xmlStrcat(msg, (const xmlChar *) message);
2961 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002962 xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
2963 (const char *) msg, str1, str2, str3, str4);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002964 xmlFree(msg);
2965}
2966
William M. Brack2f2a6632004-08-20 23:09:47 +00002967/**
2968 * xmlSchemaPIllegalFacetAtomicErr:
2969 * @ctxt: the schema parser context
2970 * @error: the error code
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002971 * @type: the schema type
2972 * @baseType: the base type of type
William M. Brack2f2a6632004-08-20 23:09:47 +00002973 * @facet: the illegal facet
2974 *
2975 * Reports an illegal facet for atomic simple types.
2976 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002977static void
2978xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002979 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002980 xmlSchemaTypePtr type,
2981 xmlSchemaTypePtr baseType,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002982 xmlSchemaFacetPtr facet)
2983{
2984 xmlChar *des = NULL, *strT = NULL;
2985
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002986 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
2987 xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002988 "%s: The facet '%s' is not allowed on types derived from the "
2989 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002990 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002991 xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002992 NULL, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002993 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002994 FREE_AND_NULL(strT);
2995}
2996
William M. Brack2f2a6632004-08-20 23:09:47 +00002997/**
2998 * xmlSchemaPIllegalFacetListUnionErr:
2999 * @ctxt: the schema parser context
3000 * @error: the error code
3001 * @itemDes: the designation of the schema item involved
3002 * @item: the schema item involved
3003 * @facet: the illegal facet
3004 *
3005 * Reports an illegal facet for <list> and <union>.
3006 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00003007static void
3008xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003009 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003010 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003011 xmlSchemaFacetPtr facet)
3012{
Daniel Veillardb2947172006-03-27 09:45:01 +00003013 xmlChar *des = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003014
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003015 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3016 type->node);
3017 xmlSchemaPErr(ctxt, type->node, error,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003018 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00003019 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003020 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003021}
3022
3023/**
3024 * xmlSchemaPMutualExclAttrErr:
3025 * @ctxt: the schema validation context
3026 * @error: the error code
3027 * @elemDes: the designation of the parent element node
3028 * @attr: the bad attribute node
3029 * @type: the corresponding type of the attribute node
3030 *
3031 * Reports an illegal attribute.
3032 */
3033static void
3034xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3035 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003036 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003037 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003038 const char *name1,
3039 const char *name2)
3040{
3041 xmlChar *des = NULL;
3042
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003043 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003044 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003045 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003046 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003047 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003048}
3049
3050/**
3051 * xmlSchemaPSimpleTypeErr:
3052 * @ctxt: the schema validation context
3053 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00003054 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00003055 * @ownerDes: the designation of the owner
3056 * @ownerItem: the schema object if existent
3057 * @node: the validated node
3058 * @value: the validated value
3059 *
3060 * Reports a simple type validation error.
3061 * TODO: Should this report the value of an element as well?
3062 */
3063static void
3064xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3065 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003066 xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003067 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00003068 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003069 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003070 const xmlChar *value,
3071 const char *message,
3072 const xmlChar *str1,
3073 const xmlChar *str2)
3074{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003075 xmlChar *msg = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003076
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003077 xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003078 if (message == NULL) {
3079 /*
3080 * Use default messages.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003081 */
3082 if (type != NULL) {
3083 if (node->type == XML_ATTRIBUTE_NODE)
3084 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3085 else
3086 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3087 "valid value of ");
3088 if (! xmlSchemaIsGlobalItem(type))
3089 msg = xmlStrcat(msg, BAD_CAST "the local ");
3090 else
3091 msg = xmlStrcat(msg, BAD_CAST "the ");
3092
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003093 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003094 msg = xmlStrcat(msg, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003095 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003096 msg = xmlStrcat(msg, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003097 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003098 msg = xmlStrcat(msg, BAD_CAST "union type");
3099
3100 if (xmlSchemaIsGlobalItem(type)) {
3101 xmlChar *str = NULL;
3102 msg = xmlStrcat(msg, BAD_CAST " '");
3103 if (type->builtInType != 0) {
3104 msg = xmlStrcat(msg, BAD_CAST "xs:");
3105 msg = xmlStrcat(msg, type->name);
3106 } else
3107 msg = xmlStrcat(msg,
3108 xmlSchemaFormatQName(&str,
3109 type->targetNamespace, type->name));
3110 msg = xmlStrcat(msg, BAD_CAST "'.");
3111 FREE_AND_NULL(str);
3112 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003113 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003114 if (node->type == XML_ATTRIBUTE_NODE)
3115 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3116 else
3117 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3118 "valid.");
3119 }
3120 if (expected) {
3121 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3122 msg = xmlStrcat(msg, BAD_CAST expected);
3123 msg = xmlStrcat(msg, BAD_CAST "'.\n");
3124 } else
3125 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00003126 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003127 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3128 else
3129 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3130 } else {
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00003131 msg = xmlStrcat(msg, BAD_CAST message);
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00003132 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003133 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00003134 (const char*) msg, str1, str2, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003135 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003136 /* Cleanup. */
3137 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003138}
3139
William M. Brack2f2a6632004-08-20 23:09:47 +00003140/**
3141 * xmlSchemaPContentErr:
3142 * @ctxt: the schema parser context
3143 * @error: the error code
3144 * @onwerDes: the designation of the holder of the content
3145 * @ownerItem: the owner item of the holder of the content
3146 * @ownerElem: the node of the holder of the content
3147 * @child: the invalid child node
3148 * @message: the optional error message
3149 * @content: the optional string describing the correct content
3150 *
3151 * Reports an error concerning the content of a schema element.
3152 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00003153static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003154xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003155 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003156 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003157 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003158 xmlNodePtr child,
3159 const char *message,
3160 const char *content)
3161{
3162 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003163
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003164 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003165 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003166 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3167 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003168 BAD_CAST des, BAD_CAST message);
3169 else {
3170 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003171 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3172 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003173 BAD_CAST des, BAD_CAST content);
3174 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003175 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3176 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003177 BAD_CAST des, NULL);
3178 }
3179 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003180 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003181}
3182
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003183/************************************************************************
3184 * *
3185 * Streamable error functions *
3186 * *
3187 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00003188
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003189
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003190
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003191
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003192/************************************************************************
3193 * *
3194 * Validation helper functions *
3195 * *
3196 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003197
Daniel Veillardc0826a72004-08-10 14:17:33 +00003198
Daniel Veillard4255d502002-04-16 15:50:10 +00003199/************************************************************************
3200 * *
3201 * Allocation functions *
3202 * *
3203 ************************************************************************/
3204
3205/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003206 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00003207 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00003208 *
3209 * Allocate a new Schema structure.
3210 *
3211 * Returns the newly allocated structure or NULL in case or error
3212 */
3213static xmlSchemaPtr
3214xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3215{
3216 xmlSchemaPtr ret;
3217
3218 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3219 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003220 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003221 return (NULL);
3222 }
3223 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003224 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003225 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003226
3227 return (ret);
3228}
3229
3230/**
3231 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00003232 *
3233 * Allocate a new Facet structure.
3234 *
3235 * Returns the newly allocated structure or NULL in case or error
3236 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003237xmlSchemaFacetPtr
3238xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00003239{
3240 xmlSchemaFacetPtr ret;
3241
3242 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3243 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003244 return (NULL);
3245 }
3246 memset(ret, 0, sizeof(xmlSchemaFacet));
3247
3248 return (ret);
3249}
3250
3251/**
3252 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00003253 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00003254 * @node: a node
3255 *
3256 * Allocate a new annotation structure.
3257 *
3258 * Returns the newly allocated structure or NULL in case or error
3259 */
3260static xmlSchemaAnnotPtr
3261xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3262{
3263 xmlSchemaAnnotPtr ret;
3264
3265 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3266 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003267 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003268 return (NULL);
3269 }
3270 memset(ret, 0, sizeof(xmlSchemaAnnot));
3271 ret->content = node;
3272 return (ret);
3273}
3274
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003275static xmlSchemaItemListPtr
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003276xmlSchemaItemListCreate(void)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003277{
3278 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003279
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003280 ret = xmlMalloc(sizeof(xmlSchemaItemList));
3281 if (ret == NULL) {
3282 xmlSchemaPErrMemory(NULL,
3283 "allocating an item list structure", NULL);
3284 return (NULL);
3285 }
3286 memset(ret, 0, sizeof(xmlSchemaItemList));
3287 return (ret);
3288}
3289
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00003290static void
3291xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3292{
3293 if (list->items != NULL) {
3294 xmlFree(list->items);
3295 list->items = NULL;
3296 }
3297 list->nbItems = 0;
3298 list->sizeItems = 0;
3299}
3300
3301static int
3302xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3303{
3304 if (list->items == NULL) {
3305 list->items = (void **) xmlMalloc(
3306 20 * sizeof(void *));
3307 if (list->items == NULL) {
3308 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3309 return(-1);
3310 }
3311 list->sizeItems = 20;
3312 } else if (list->sizeItems <= list->nbItems) {
3313 list->sizeItems *= 2;
3314 list->items = (void **) xmlRealloc(list->items,
3315 list->sizeItems * sizeof(void *));
3316 if (list->items == NULL) {
3317 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3318 list->sizeItems = 0;
3319 return(-1);
3320 }
3321 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00003322 list->items[list->nbItems++] = item;
3323 return(0);
3324}
3325
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003326static int
3327xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3328 int initialSize,
3329 void *item)
3330{
3331 if (list->items == NULL) {
3332 if (initialSize <= 0)
3333 initialSize = 1;
3334 list->items = (void **) xmlMalloc(
3335 initialSize * sizeof(void *));
3336 if (list->items == NULL) {
3337 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3338 return(-1);
3339 }
3340 list->sizeItems = initialSize;
3341 } else if (list->sizeItems <= list->nbItems) {
3342 list->sizeItems *= 2;
3343 list->items = (void **) xmlRealloc(list->items,
3344 list->sizeItems * sizeof(void *));
3345 if (list->items == NULL) {
3346 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3347 list->sizeItems = 0;
3348 return(-1);
3349 }
3350 }
3351 list->items[list->nbItems++] = item;
3352 return(0);
3353}
3354
3355static int
3356xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3357{
3358 if (list->items == NULL) {
3359 list->items = (void **) xmlMalloc(
3360 20 * sizeof(void *));
3361 if (list->items == NULL) {
3362 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3363 return(-1);
3364 }
3365 list->sizeItems = 20;
3366 } else if (list->sizeItems <= list->nbItems) {
3367 list->sizeItems *= 2;
3368 list->items = (void **) xmlRealloc(list->items,
3369 list->sizeItems * sizeof(void *));
3370 if (list->items == NULL) {
3371 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3372 list->sizeItems = 0;
3373 return(-1);
3374 }
3375 }
3376 /*
3377 * Just append if the index is greater/equal than the item count.
3378 */
3379 if (idx >= list->nbItems) {
3380 list->items[list->nbItems++] = item;
3381 } else {
3382 int i;
3383 for (i = list->nbItems; i > idx; i--)
3384 list->items[i] = list->items[i-1];
3385 list->items[idx] = item;
3386 list->nbItems++;
3387 }
3388 return(0);
3389}
3390
3391#if 0 /* enable if ever needed */
3392static int
3393xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3394 int initialSize,
3395 void *item,
3396 int idx)
3397{
3398 if (list->items == NULL) {
3399 if (initialSize <= 0)
3400 initialSize = 1;
3401 list->items = (void **) xmlMalloc(
3402 initialSize * sizeof(void *));
3403 if (list->items == NULL) {
3404 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3405 return(-1);
3406 }
3407 list->sizeItems = initialSize;
3408 } else if (list->sizeItems <= list->nbItems) {
3409 list->sizeItems *= 2;
3410 list->items = (void **) xmlRealloc(list->items,
3411 list->sizeItems * sizeof(void *));
3412 if (list->items == NULL) {
3413 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3414 list->sizeItems = 0;
3415 return(-1);
3416 }
3417 }
3418 /*
3419 * Just append if the index is greater/equal than the item count.
3420 */
3421 if (idx >= list->nbItems) {
3422 list->items[list->nbItems++] = item;
3423 } else {
3424 int i;
3425 for (i = list->nbItems; i > idx; i--)
3426 list->items[i] = list->items[i-1];
3427 list->items[idx] = item;
3428 list->nbItems++;
3429 }
3430 return(0);
3431}
3432#endif
3433
3434static int
3435xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3436{
3437 int i;
3438 if ((list->items == NULL) || (idx >= list->nbItems)) {
3439 xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3440 "index error.\n");
3441 return(-1);
3442 }
3443
3444 if (list->nbItems == 1) {
3445 /* TODO: Really free the list? */
3446 xmlFree(list->items);
3447 list->items = NULL;
3448 list->nbItems = 0;
3449 list->sizeItems = 0;
3450 } else if (list->nbItems -1 == idx) {
3451 list->nbItems--;
3452 } else {
3453 for (i = idx; i < list->nbItems -1; i++)
3454 list->items[i] = list->items[i+1];
3455 list->nbItems--;
3456 }
3457 return(0);
3458}
3459
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003460/**
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003461 * xmlSchemaItemListFree:
3462 * @annot: a schema type structure
3463 *
3464 * Deallocate a annotation structure
3465 */
3466static void
3467xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3468{
3469 if (list == NULL)
3470 return;
3471 if (list->items != NULL)
3472 xmlFree(list->items);
3473 xmlFree(list);
3474}
3475
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003476static void
3477xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003478{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003479 if (bucket == NULL)
3480 return;
3481 if (bucket->globals != NULL) {
3482 xmlSchemaComponentListFree(bucket->globals);
3483 xmlSchemaItemListFree(bucket->globals);
3484 }
3485 if (bucket->locals != NULL) {
3486 xmlSchemaComponentListFree(bucket->locals);
3487 xmlSchemaItemListFree(bucket->locals);
3488 }
3489 if (bucket->relations != NULL) {
3490 xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3491 do {
3492 prev = cur;
3493 cur = cur->next;
3494 xmlFree(prev);
3495 } while (cur != NULL);
3496 }
3497 if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3498 xmlFreeDoc(bucket->doc);
3499 }
3500 if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003501 if (WXS_IMPBUCKET(bucket)->schema != NULL)
3502 xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003503 }
3504 xmlFree(bucket);
3505}
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003506
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003507static xmlSchemaBucketPtr
3508xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003509 int type, const xmlChar *targetNamespace)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003510{
3511 xmlSchemaBucketPtr ret;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003512 int size;
3513 xmlSchemaPtr mainSchema;
3514
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003515 if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003516 PERROR_INT("xmlSchemaBucketCreate",
3517 "no main schema on constructor");
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003518 return(NULL);
3519 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003520 mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003521 /* Create the schema bucket. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003522 if (WXS_IS_BUCKET_INCREDEF(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003523 size = sizeof(xmlSchemaInclude);
3524 else
3525 size = sizeof(xmlSchemaImport);
3526 ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3527 if (ret == NULL) {
3528 xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3529 return(NULL);
3530 }
3531 memset(ret, 0, size);
3532 ret->targetNamespace = targetNamespace;
3533 ret->type = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003534 ret->globals = xmlSchemaItemListCreate();
3535 if (ret->globals == NULL) {
3536 xmlFree(ret);
3537 return(NULL);
3538 }
3539 ret->locals = xmlSchemaItemListCreate();
3540 if (ret->locals == NULL) {
3541 xmlFree(ret);
3542 return(NULL);
3543 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003544 /*
3545 * The following will assure that only the first bucket is marked as
3546 * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3547 * For each following import buckets an xmlSchema will be created.
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003548 * An xmlSchema will be created for every distinct targetNamespace.
3549 * We assign the targetNamespace to the schemata here.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003550 */
3551 if (! WXS_HAS_BUCKETS(pctxt)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003552 if (WXS_IS_BUCKET_INCREDEF(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003553 PERROR_INT("xmlSchemaBucketCreate",
3554 "first bucket but it's an include or redefine");
3555 xmlSchemaBucketFree(ret);
3556 return(NULL);
3557 }
3558 /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3559 ret->type = XML_SCHEMA_SCHEMA_MAIN;
3560 /* Point to the *main* schema. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003561 WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3562 WXS_IMPBUCKET(ret)->schema = mainSchema;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003563 /*
3564 * Ensure that the main schema gets a targetNamespace.
3565 */
3566 mainSchema->targetNamespace = targetNamespace;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003567 } else {
3568 if (type == XML_SCHEMA_SCHEMA_MAIN) {
3569 PERROR_INT("xmlSchemaBucketCreate",
3570 "main bucket but it's not the first one");
3571 xmlSchemaBucketFree(ret);
3572 return(NULL);
3573 } else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3574 /*
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003575 * Create a schema for imports and assign the
3576 * targetNamespace.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003577 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003578 WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3579 if (WXS_IMPBUCKET(ret)->schema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003580 xmlSchemaBucketFree(ret);
3581 return(NULL);
3582 }
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003583 WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003584 }
3585 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003586 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003587 int res;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003588 /*
3589 * Imports go into the "schemasImports" slot of the main *schema*.
3590 * Note that we create an import entry for the main schema as well; i.e.,
3591 * even if there's only one schema, we'll get an import.
3592 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003593 if (mainSchema->schemasImports == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003594 mainSchema->schemasImports = xmlHashCreateDict(5,
3595 WXS_CONSTRUCTOR(pctxt)->dict);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003596 if (mainSchema->schemasImports == NULL) {
3597 xmlSchemaBucketFree(ret);
3598 return(NULL);
3599 }
3600 }
3601 if (targetNamespace == NULL)
3602 res = xmlHashAddEntry(mainSchema->schemasImports,
3603 XML_SCHEMAS_NO_NAMESPACE, ret);
3604 else
3605 res = xmlHashAddEntry(mainSchema->schemasImports,
3606 targetNamespace, ret);
3607 if (res != 0) {
3608 PERROR_INT("xmlSchemaBucketCreate",
3609 "failed to add the schema bucket to the hash");
3610 xmlSchemaBucketFree(ret);
3611 return(NULL);
3612 }
3613 } else {
3614 /* Set the @ownerImport of an include bucket. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003615 if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3616 WXS_INCBUCKET(ret)->ownerImport =
3617 WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003618 else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003619 WXS_INCBUCKET(ret)->ownerImport =
3620 WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003621
3622 /* Includes got into the "includes" slot of the *main* schema. */
3623 if (mainSchema->includes == NULL) {
3624 mainSchema->includes = xmlSchemaItemListCreate();
3625 if (mainSchema->includes == NULL) {
3626 xmlSchemaBucketFree(ret);
3627 return(NULL);
3628 }
3629 }
3630 xmlSchemaItemListAdd(mainSchema->includes, ret);
3631 }
3632 /*
3633 * Add to list of all buckets; this is used for lookup
3634 * during schema construction time only.
3635 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003636 if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003637 return(NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003638 return(ret);
3639}
3640
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003641static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003642xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003643{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003644 if (*list == NULL) {
3645 *list = xmlSchemaItemListCreate();
3646 if (*list == NULL)
3647 return(-1);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003648 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003649 xmlSchemaItemListAddSize(*list, initialSize, item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003650 return(0);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003651}
3652
3653/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00003654 * xmlSchemaFreeAnnot:
3655 * @annot: a schema type structure
3656 *
3657 * Deallocate a annotation structure
3658 */
3659static void
3660xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3661{
3662 if (annot == NULL)
3663 return;
Kasimier T. Buchcik004b5462005-08-08 12:43:09 +00003664 if (annot->next == NULL) {
3665 xmlFree(annot);
3666 } else {
3667 xmlSchemaAnnotPtr prev;
3668
3669 do {
3670 prev = annot;
3671 annot = annot->next;
3672 xmlFree(prev);
3673 } while (annot != NULL);
3674 }
Daniel Veillardfdc91562002-07-01 21:52:03 +00003675}
3676
3677/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003678 * xmlSchemaFreeNotation:
3679 * @schema: a schema notation structure
3680 *
3681 * Deallocate a Schema Notation structure.
3682 */
3683static void
3684xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3685{
3686 if (nota == NULL)
3687 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003688 xmlFree(nota);
3689}
3690
3691/**
3692 * xmlSchemaFreeAttribute:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003693 * @attr: an attribute declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00003694 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003695 * Deallocates an attribute declaration structure.
Daniel Veillard4255d502002-04-16 15:50:10 +00003696 */
3697static void
3698xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3699{
3700 if (attr == NULL)
3701 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003702 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003703 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003704 if (attr->defVal != NULL)
3705 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003706 xmlFree(attr);
3707}
3708
3709/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003710 * xmlSchemaFreeAttributeUse:
3711 * @use: an attribute use
3712 *
3713 * Deallocates an attribute use structure.
3714 */
3715static void
3716xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3717{
3718 if (use == NULL)
3719 return;
3720 if (use->annot != NULL)
3721 xmlSchemaFreeAnnot(use->annot);
3722 if (use->defVal != NULL)
3723 xmlSchemaFreeValue(use->defVal);
3724 xmlFree(use);
3725}
3726
3727/**
3728 * xmlSchemaFreeAttributeUseProhib:
3729 * @prohib: an attribute use prohibition
3730 *
3731 * Deallocates an attribute use structure.
3732 */
3733static void
3734xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3735{
3736 if (prohib == NULL)
3737 return;
3738 xmlFree(prohib);
3739}
3740
3741/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003742 * xmlSchemaFreeWildcardNsSet:
3743 * set: a schema wildcard namespace
3744 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003745 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00003746 */
3747static void
3748xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3749{
3750 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003751
Daniel Veillard3646d642004-06-02 19:19:14 +00003752 while (set != NULL) {
3753 next = set->next;
3754 xmlFree(set);
3755 set = next;
3756 }
3757}
3758
3759/**
3760 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003761 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00003762 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003763 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00003764 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003765void
Daniel Veillard3646d642004-06-02 19:19:14 +00003766xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3767{
3768 if (wildcard == NULL)
3769 return;
3770 if (wildcard->annot != NULL)
3771 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003772 if (wildcard->nsSet != NULL)
3773 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3774 if (wildcard->negNsSet != NULL)
3775 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00003776 xmlFree(wildcard);
3777}
3778
3779/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003780 * xmlSchemaFreeAttributeGroup:
3781 * @schema: a schema attribute group structure
3782 *
3783 * Deallocate a Schema Attribute Group structure.
3784 */
3785static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003786xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
Daniel Veillard4255d502002-04-16 15:50:10 +00003787{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003788 if (attrGr == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00003789 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003790 if (attrGr->annot != NULL)
3791 xmlSchemaFreeAnnot(attrGr->annot);
3792 if (attrGr->attrUses != NULL)
3793 xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3794 xmlFree(attrGr);
Daniel Veillard3646d642004-06-02 19:19:14 +00003795}
3796
3797/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003798 * xmlSchemaFreeQNameRef:
3799 * @item: a QName reference structure
3800 *
3801 * Deallocatea a QName reference structure.
3802 */
3803static void
3804xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3805{
3806 xmlFree(item);
3807}
3808
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003809/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003810 * xmlSchemaFreeTypeLinkList:
3811 * @alink: a type link
3812 *
3813 * Deallocate a list of types.
3814 */
3815static void
3816xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3817{
3818 xmlSchemaTypeLinkPtr next;
3819
3820 while (link != NULL) {
3821 next = link->next;
3822 xmlFree(link);
3823 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003824 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003825}
3826
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003827static void
3828xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3829{
3830 xmlSchemaIDCStateObjPtr next;
3831 while (sto != NULL) {
3832 next = sto->next;
3833 if (sto->history != NULL)
3834 xmlFree(sto->history);
3835 if (sto->xpathCtxt != NULL)
3836 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3837 xmlFree(sto);
3838 sto = next;
3839 }
3840}
3841
3842/**
3843 * xmlSchemaFreeIDC:
3844 * @idc: a identity-constraint definition
3845 *
3846 * Deallocates an identity-constraint definition.
3847 */
3848static void
3849xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3850{
3851 xmlSchemaIDCSelectPtr cur, prev;
3852
3853 if (idcDef == NULL)
3854 return;
3855 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003856 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003857 /* Selector */
3858 if (idcDef->selector != NULL) {
3859 if (idcDef->selector->xpathComp != NULL)
3860 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3861 xmlFree(idcDef->selector);
3862 }
3863 /* Fields */
3864 if (idcDef->fields != NULL) {
3865 cur = idcDef->fields;
3866 do {
3867 prev = cur;
3868 cur = cur->next;
3869 if (prev->xpathComp != NULL)
3870 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003871 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003872 } while (cur != NULL);
3873 }
3874 xmlFree(idcDef);
3875}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003876
Daniel Veillard01fa6152004-06-29 17:04:39 +00003877/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003878 * xmlSchemaFreeElement:
3879 * @schema: a schema element structure
3880 *
3881 * Deallocate a Schema Element structure.
3882 */
3883static void
3884xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3885{
3886 if (elem == NULL)
3887 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003888 if (elem->annot != NULL)
3889 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003890 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003891 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003892 if (elem->defVal != NULL)
3893 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003894 xmlFree(elem);
3895}
3896
3897/**
3898 * xmlSchemaFreeFacet:
3899 * @facet: a schema facet structure
3900 *
3901 * Deallocate a Schema Facet structure.
3902 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003903void
Daniel Veillard4255d502002-04-16 15:50:10 +00003904xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3905{
3906 if (facet == NULL)
3907 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003908 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003909 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003910 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003911 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003912 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003913 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003914 xmlFree(facet);
3915}
3916
3917/**
3918 * xmlSchemaFreeType:
3919 * @type: a schema type structure
3920 *
3921 * Deallocate a Schema Type structure.
3922 */
3923void
3924xmlSchemaFreeType(xmlSchemaTypePtr type)
3925{
3926 if (type == NULL)
3927 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003928 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003929 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003930 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003931 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003932
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003933 facet = type->facets;
3934 while (facet != NULL) {
3935 next = facet->next;
3936 xmlSchemaFreeFacet(facet);
3937 facet = next;
3938 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003939 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003940 if (type->attrUses != NULL)
3941 xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003942 if (type->memberTypes != NULL)
3943 xmlSchemaFreeTypeLinkList(type->memberTypes);
3944 if (type->facetSet != NULL) {
3945 xmlSchemaFacetLinkPtr next, link;
3946
3947 link = type->facetSet;
3948 do {
3949 next = link->next;
3950 xmlFree(link);
3951 link = next;
3952 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003953 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003954 if (type->contModel != NULL)
3955 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003956 xmlFree(type);
3957}
3958
3959/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003960 * xmlSchemaFreeModelGroupDef:
3961 * @item: a schema model group definition
3962 *
3963 * Deallocates a schema model group definition.
3964 */
3965static void
3966xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3967{
3968 if (item->annot != NULL)
3969 xmlSchemaFreeAnnot(item->annot);
3970 xmlFree(item);
3971}
3972
3973/**
3974 * xmlSchemaFreeModelGroup:
3975 * @item: a schema model group
3976 *
3977 * Deallocates a schema model group structure.
3978 */
3979static void
3980xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3981{
3982 if (item->annot != NULL)
3983 xmlSchemaFreeAnnot(item->annot);
3984 xmlFree(item);
3985}
3986
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003987static void
3988xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
3989{
3990 if ((list == NULL) || (list->nbItems == 0))
3991 return;
3992 {
3993 xmlSchemaTreeItemPtr item;
3994 xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
3995 int i;
3996
3997 for (i = 0; i < list->nbItems; i++) {
3998 item = items[i];
3999 if (item == NULL)
4000 continue;
4001 switch (item->type) {
4002 case XML_SCHEMA_TYPE_SIMPLE:
4003 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004004 xmlSchemaFreeType((xmlSchemaTypePtr) item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004005 break;
4006 case XML_SCHEMA_TYPE_ATTRIBUTE:
4007 xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004008 break;
4009 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4010 xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4011 break;
4012 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4013 xmlSchemaFreeAttributeUseProhib(
4014 (xmlSchemaAttributeUseProhibPtr) item);
4015 break;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004016 case XML_SCHEMA_TYPE_ELEMENT:
4017 xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4018 break;
4019 case XML_SCHEMA_TYPE_PARTICLE:
4020 if (item->annot != NULL)
4021 xmlSchemaFreeAnnot(item->annot);
4022 xmlFree(item);
4023 break;
4024 case XML_SCHEMA_TYPE_SEQUENCE:
4025 case XML_SCHEMA_TYPE_CHOICE:
4026 case XML_SCHEMA_TYPE_ALL:
4027 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4028 break;
4029 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4030 xmlSchemaFreeAttributeGroup(
4031 (xmlSchemaAttributeGroupPtr) item);
4032 break;
4033 case XML_SCHEMA_TYPE_GROUP:
4034 xmlSchemaFreeModelGroupDef(
4035 (xmlSchemaModelGroupDefPtr) item);
4036 break;
4037 case XML_SCHEMA_TYPE_ANY:
4038 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4039 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4040 break;
4041 case XML_SCHEMA_TYPE_IDC_KEY:
4042 case XML_SCHEMA_TYPE_IDC_UNIQUE:
4043 case XML_SCHEMA_TYPE_IDC_KEYREF:
4044 xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4045 break;
4046 case XML_SCHEMA_TYPE_NOTATION:
4047 xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4048 break;
4049 case XML_SCHEMA_EXTRA_QNAMEREF:
4050 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4051 break;
4052 default: {
4053 /* TODO: This should never be hit. */
4054 xmlSchemaPSimpleInternalErr(NULL,
4055 "Internal error: xmlSchemaComponentListFree, "
4056 "unexpected component type '%s'\n",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004057 (const xmlChar *) WXS_ITEM_TYPE_NAME(item));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004058 }
4059 break;
4060 }
4061 }
4062 list->nbItems = 0;
4063 }
4064}
4065
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004066/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004067 * xmlSchemaFree:
4068 * @schema: a schema structure
4069 *
4070 * Deallocate a Schema structure.
4071 */
4072void
4073xmlSchemaFree(xmlSchemaPtr schema)
4074{
4075 if (schema == NULL)
4076 return;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004077 /* @volatiles is not used anymore :-/ */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004078 if (schema->volatiles != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004079 TODO
4080 /*
4081 * Note that those slots are not responsible for freeing
4082 * schema components anymore; this will now be done by
4083 * the schema buckets.
4084 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004085 if (schema->notaDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004086 xmlHashFree(schema->notaDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004087 if (schema->attrDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004088 xmlHashFree(schema->attrDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004089 if (schema->attrgrpDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004090 xmlHashFree(schema->attrgrpDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004091 if (schema->elemDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004092 xmlHashFree(schema->elemDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004093 if (schema->typeDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004094 xmlHashFree(schema->typeDecl, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004095 if (schema->groupDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004096 xmlHashFree(schema->groupDecl, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004097 if (schema->idcDef != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004098 xmlHashFree(schema->idcDef, NULL);
4099
Daniel Veillard1d913862003-11-21 00:28:39 +00004100 if (schema->schemasImports != NULL)
4101 xmlHashFree(schema->schemasImports,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004102 (xmlHashDeallocator) xmlSchemaBucketFree);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004103 if (schema->includes != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004104 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4105 int i;
4106 for (i = 0; i < list->nbItems; i++) {
4107 xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4108 }
4109 xmlSchemaItemListFree(list);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004110 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004111 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004112 xmlSchemaFreeAnnot(schema->annot);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004113 /* Never free the doc here, since this will be done by the buckets. */
4114
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004115 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004116 xmlFree(schema);
4117}
4118
4119/************************************************************************
4120 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00004121 * Debug functions *
4122 * *
4123 ************************************************************************/
4124
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00004125#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004126
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004127static void
4128xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4129
Daniel Veillard4255d502002-04-16 15:50:10 +00004130/**
4131 * xmlSchemaElementDump:
4132 * @elem: an element
4133 * @output: the file output
4134 *
4135 * Dump the element
4136 */
4137static void
4138xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004139 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004140 const xmlChar * namespace ATTRIBUTE_UNUSED,
4141 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00004142{
4143 if (elem == NULL)
4144 return;
4145
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004146
4147 fprintf(output, "Element");
4148 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4149 fprintf(output, " (global)");
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004150 fprintf(output, ": '%s' ", elem->name);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004151 if (namespace != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004152 fprintf(output, "ns '%s'", namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004153 fprintf(output, "\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004154#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004155 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004156 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004157 if (elem->maxOccurs >= UNBOUNDED)
4158 fprintf(output, "max: unbounded\n");
4159 else if (elem->maxOccurs != 1)
4160 fprintf(output, "max: %d\n", elem->maxOccurs);
4161 else
4162 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00004163 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004164#endif
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004165 /*
4166 * Misc other properties.
4167 */
4168 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4169 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4170 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004171 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004172 fprintf(output, " props: ");
4173 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4174 fprintf(output, "[fixed] ");
4175 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4176 fprintf(output, "[default] ");
4177 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4178 fprintf(output, "[abstract] ");
4179 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4180 fprintf(output, "[nillable] ");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004181 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00004182 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004183 /*
4184 * Default/fixed value.
4185 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004186 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004187 fprintf(output, " value: '%s'\n", elem->value);
4188 /*
4189 * Type.
4190 */
4191 if (elem->namedType != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004192 fprintf(output, " type: '%s' ", elem->namedType);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004193 if (elem->namedTypeNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004194 fprintf(output, "ns '%s'\n", elem->namedTypeNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004195 else
4196 fprintf(output, "\n");
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004197 } else if (elem->subtypes != NULL) {
4198 /*
4199 * Dump local types.
4200 */
4201 xmlSchemaTypeDump(elem->subtypes, output);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004202 }
4203 /*
4204 * Substitution group.
4205 */
4206 if (elem->substGroup != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004207 fprintf(output, " substitutionGroup: '%s' ", elem->substGroup);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004208 if (elem->substGroupNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004209 fprintf(output, "ns '%s'\n", elem->substGroupNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004210 else
4211 fprintf(output, "\n");
4212 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004213}
4214
4215/**
4216 * xmlSchemaAnnotDump:
4217 * @output: the file output
4218 * @annot: a annotation
4219 *
4220 * Dump the annotation
4221 */
4222static void
4223xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4224{
4225 xmlChar *content;
4226
4227 if (annot == NULL)
4228 return;
4229
4230 content = xmlNodeGetContent(annot->content);
4231 if (content != NULL) {
4232 fprintf(output, " Annot: %s\n", content);
4233 xmlFree(content);
4234 } else
4235 fprintf(output, " Annot: empty\n");
4236}
4237
4238/**
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004239 * xmlSchemaContentModelDump:
4240 * @particle: the schema particle
4241 * @output: the file output
4242 * @depth: the depth used for intentation
Daniel Veillard4255d502002-04-16 15:50:10 +00004243 *
4244 * Dump a SchemaType structure
4245 */
4246static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004247xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4248{
4249 xmlChar *str = NULL;
4250 xmlSchemaTreeItemPtr term;
4251 char shift[100];
4252 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004253
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004254 if (particle == NULL)
4255 return;
4256 for (i = 0;((i < depth) && (i < 25));i++)
4257 shift[2 * i] = shift[2 * i + 1] = ' ';
4258 shift[2 * i] = shift[2 * i + 1] = 0;
4259 fprintf(output, shift);
4260 if (particle->children == NULL) {
4261 fprintf(output, "MISSING particle term\n");
4262 return;
4263 }
4264 term = particle->children;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004265 if (term == NULL) {
4266 fprintf(output, "(NULL)");
4267 } else {
4268 switch (term->type) {
4269 case XML_SCHEMA_TYPE_ELEMENT:
4270 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4271 ((xmlSchemaElementPtr)term)->targetNamespace,
4272 ((xmlSchemaElementPtr)term)->name));
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004273 FREE_AND_NULL(str);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004274 break;
4275 case XML_SCHEMA_TYPE_SEQUENCE:
4276 fprintf(output, "SEQUENCE");
4277 break;
4278 case XML_SCHEMA_TYPE_CHOICE:
4279 fprintf(output, "CHOICE");
4280 break;
4281 case XML_SCHEMA_TYPE_ALL:
4282 fprintf(output, "ALL");
4283 break;
4284 case XML_SCHEMA_TYPE_ANY:
4285 fprintf(output, "ANY");
4286 break;
4287 default:
4288 fprintf(output, "UNKNOWN\n");
4289 return;
4290 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004291 }
4292 if (particle->minOccurs != 1)
4293 fprintf(output, " min: %d", particle->minOccurs);
4294 if (particle->maxOccurs >= UNBOUNDED)
4295 fprintf(output, " max: unbounded");
4296 else if (particle->maxOccurs != 1)
4297 fprintf(output, " max: %d", particle->maxOccurs);
4298 fprintf(output, "\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004299 if (term &&
4300 ((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4301 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4302 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4303 (term->children != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004304 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4305 output, depth +1);
4306 }
4307 if (particle->next != NULL)
4308 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4309 output, depth);
4310}
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004311
4312/**
4313 * xmlSchemaAttrUsesDump:
4314 * @uses: attribute uses list
4315 * @output: the file output
4316 *
4317 * Dumps a list of attribute use components.
4318 */
4319static void
4320xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4321{
4322 xmlSchemaAttributeUsePtr use;
4323 xmlSchemaAttributeUseProhibPtr prohib;
4324 xmlSchemaQNameRefPtr ref;
4325 const xmlChar *name, *tns;
4326 xmlChar *str = NULL;
4327 int i;
4328
4329 if ((uses == NULL) || (uses->nbItems == 0))
4330 return;
4331
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004332 fprintf(output, " attributes:\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004333 for (i = 0; i < uses->nbItems; i++) {
4334 use = uses->items[i];
4335 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4336 fprintf(output, " [prohibition] ");
4337 prohib = (xmlSchemaAttributeUseProhibPtr) use;
4338 name = prohib->name;
4339 tns = prohib->targetNamespace;
4340 } else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4341 fprintf(output, " [reference] ");
4342 ref = (xmlSchemaQNameRefPtr) use;
4343 name = ref->name;
4344 tns = ref->targetNamespace;
4345 } else {
4346 fprintf(output, " [use] ");
4347 name = WXS_ATTRUSE_DECL_NAME(use);
4348 tns = WXS_ATTRUSE_DECL_TNS(use);
4349 }
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004350 fprintf(output, "'%s'\n",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004351 (const char *) xmlSchemaFormatQName(&str, tns, name));
4352 FREE_AND_NULL(str);
4353 }
4354}
4355
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004356/**
4357 * xmlSchemaTypeDump:
4358 * @output: the file output
4359 * @type: a type structure
4360 *
4361 * Dump a SchemaType structure
4362 */
4363static void
Daniel Veillard4255d502002-04-16 15:50:10 +00004364xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4365{
4366 if (type == NULL) {
4367 fprintf(output, "Type: NULL\n");
4368 return;
4369 }
4370 fprintf(output, "Type: ");
4371 if (type->name != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004372 fprintf(output, "'%s' ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004373 else
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004374 fprintf(output, "(no name) ");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004375 if (type->targetNamespace != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004376 fprintf(output, "ns '%s' ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004377 switch (type->type) {
4378 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004379 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004380 break;
4381 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004382 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004383 break;
4384 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004385 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004386 break;
4387 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004388 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004389 break;
4390 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004391 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004392 break;
4393 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004394 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004395 break;
4396 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004397 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004398 break;
4399 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004400 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004401 break;
4402 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004403 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004404 break;
4405 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004406 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00004407 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004408 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004409 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004410 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004411 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004412 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004413 break;
4414 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004415 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004416 break;
4417 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004418 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004419 break;
4420 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004421 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004422 break;
4423 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004424 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004425 break;
4426 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004427 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004428 break;
4429 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004430 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004431 break;
4432 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004433 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004434 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00004435 }
4436 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004437 if (type->base != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004438 fprintf(output, " base type: '%s'", type->base);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004439 if (type->baseNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004440 fprintf(output, " ns '%s'\n", type->baseNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004441 else
4442 fprintf(output, "\n");
4443 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004444 if (type->attrUses != NULL)
4445 xmlSchemaAttrUsesDump(type->attrUses, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00004446 if (type->annot != NULL)
4447 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004448#ifdef DUMP_CONTENT_MODEL
4449 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4450 (type->subtypes != NULL)) {
4451 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4452 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004453 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004454#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004455}
4456
4457/**
4458 * xmlSchemaDump:
4459 * @output: the file output
4460 * @schema: a schema structure
4461 *
4462 * Dump a Schema structure.
4463 */
4464void
4465xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4466{
Daniel Veillardce682bc2004-11-05 17:22:25 +00004467 if (output == NULL)
4468 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004469 if (schema == NULL) {
4470 fprintf(output, "Schemas: NULL\n");
4471 return;
4472 }
4473 fprintf(output, "Schemas: ");
4474 if (schema->name != NULL)
4475 fprintf(output, "%s, ", schema->name);
4476 else
4477 fprintf(output, "no name, ");
4478 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00004479 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004480 else
4481 fprintf(output, "no target namespace");
4482 fprintf(output, "\n");
4483 if (schema->annot != NULL)
4484 xmlSchemaAnnotDump(output, schema->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00004485 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
4486 output);
4487 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004488 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00004489}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004490
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004491#ifdef DEBUG_IDC_NODE_TABLE
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004492/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004493 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004494 * @vctxt: the WXS validation context
4495 *
4496 * Displays the current IDC table for debug purposes.
4497 */
4498static void
4499xmlSchemaDebugDumpIDCTable(FILE * output,
4500 const xmlChar *namespaceName,
4501 const xmlChar *localName,
4502 xmlSchemaPSVIIDCBindingPtr bind)
4503{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004504 xmlChar *str = NULL;
4505 const xmlChar *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004506 xmlSchemaPSVIIDCNodePtr tab;
4507 xmlSchemaPSVIIDCKeyPtr key;
4508 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004509
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004510 fprintf(output, "IDC: TABLES on '%s'\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004511 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004512 FREE_AND_NULL(str)
4513
4514 if (bind == NULL)
4515 return;
4516 do {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004517 fprintf(output, "IDC: BINDING '%s' (%d)\n",
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004518 xmlSchemaGetComponentQName(&str,
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004519 bind->definition), bind->nbNodes);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004520 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004521 for (i = 0; i < bind->nbNodes; i++) {
4522 tab = bind->nodeTable[i];
4523 fprintf(output, " ( ");
4524 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004525 key = tab->keys[j];
4526 if ((key != NULL) && (key->val != NULL)) {
4527 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004528 if (res >= 0)
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004529 fprintf(output, "'%s' ", value);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004530 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004531 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004532 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004533 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004534 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004535 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004536 else
4537 fprintf(output, "(key missing), ");
4538 }
4539 fprintf(output, ")\n");
4540 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004541 if (bind->dupls && bind->dupls->nbItems) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004542 fprintf(output, "IDC: dupls (%d):\n", bind->dupls->nbItems);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004543 for (i = 0; i < bind->dupls->nbItems; i++) {
4544 tab = bind->dupls->items[i];
4545 fprintf(output, " ( ");
4546 for (j = 0; j < bind->definition->nbFields; j++) {
4547 key = tab->keys[j];
4548 if ((key != NULL) && (key->val != NULL)) {
4549 res = xmlSchemaGetCanonValue(key->val, &value);
4550 if (res >= 0)
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004551 fprintf(output, "'%s' ", value);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004552 else
4553 fprintf(output, "CANON-VALUE-FAILED ");
4554 if (res == 0)
4555 FREE_AND_NULL(value)
4556 } else if (key != NULL)
4557 fprintf(output, "(no val), ");
4558 else
4559 fprintf(output, "(key missing), ");
4560 }
4561 fprintf(output, ")\n");
4562 }
4563 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004564 bind = bind->next;
4565 } while (bind != NULL);
4566}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00004567#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00004568#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00004569
4570/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004571 * *
4572 * Utilities *
4573 * *
4574 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004575
Daniel Veillardc0826a72004-08-10 14:17:33 +00004576/**
4577 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004578 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00004579 * @name: the name of the attribute
4580 *
4581 * Seeks an attribute with a name of @name in
4582 * no namespace.
4583 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004584 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00004585 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004586static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004587xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00004588{
4589 xmlAttrPtr prop;
4590
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004591 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004592 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004593 prop = node->properties;
4594 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004595 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004596 return(prop);
4597 prop = prop->next;
4598 }
4599 return (NULL);
4600}
4601
4602/**
4603 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004604 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00004605 * @uri: the uri
4606 * @name: the name of the attribute
4607 *
4608 * Seeks an attribute with a local name of @name and
4609 * a namespace URI of @uri.
4610 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004611 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00004612 */
4613static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004614xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00004615{
4616 xmlAttrPtr prop;
4617
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004618 if ((node == NULL) || (name == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004619 return(NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004620 prop = node->properties;
4621 while (prop != NULL) {
4622 if ((prop->ns != NULL) &&
4623 xmlStrEqual(prop->name, BAD_CAST name) &&
4624 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00004625 return(prop);
4626 prop = prop->next;
4627 }
4628 return (NULL);
4629}
4630
4631static const xmlChar *
4632xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4633{
4634 xmlChar *val;
4635 const xmlChar *ret;
4636
4637 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004638 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00004639 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00004640 ret = xmlDictLookup(ctxt->dict, val, -1);
4641 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004642 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004643}
4644
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004645static const xmlChar *
4646xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4647{
4648 return((const xmlChar*) xmlNodeGetContent(node));
4649}
4650
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004651/**
4652 * xmlSchemaGetProp:
4653 * @ctxt: the parser context
4654 * @node: the node
4655 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004656 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004657 * Read a attribute value and internalize the string
4658 *
4659 * Returns the string or NULL if not present.
4660 */
4661static const xmlChar *
4662xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4663 const char *name)
4664{
4665 xmlChar *val;
4666 const xmlChar *ret;
4667
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004668 val = xmlGetNoNsProp(node, BAD_CAST name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004669 if (val == NULL)
4670 return(NULL);
4671 ret = xmlDictLookup(ctxt->dict, val, -1);
4672 xmlFree(val);
4673 return(ret);
4674}
4675
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004676/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00004677 * *
4678 * Parsing functions *
4679 * *
4680 ************************************************************************/
4681
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004682#define WXS_FIND_GLOBAL_ITEM(slot) \
4683 if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4684 ret = xmlHashLookup(schema->slot, name); \
4685 if (ret != NULL) goto exit; \
4686 } \
4687 if (xmlHashSize(schema->schemasImports) > 1) { \
4688 xmlSchemaImportPtr import; \
4689 if (nsName == NULL) \
4690 import = xmlHashLookup(schema->schemasImports, \
4691 XML_SCHEMAS_NO_NAMESPACE); \
4692 else \
4693 import = xmlHashLookup(schema->schemasImports, nsName); \
4694 if (import == NULL) \
4695 goto exit; \
4696 ret = xmlHashLookup(import->schema->slot, name); \
4697 }
4698
Daniel Veillard4255d502002-04-16 15:50:10 +00004699/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004700 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004701 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004702 * @name: the element name
4703 * @ns: the element namespace
4704 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004705 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004706 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004707 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004708 */
4709static xmlSchemaElementPtr
4710xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004711 const xmlChar * nsName)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004712{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004713 xmlSchemaElementPtr ret = NULL;
4714
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004715 if ((name == NULL) || (schema == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004716 return(NULL);
4717 if (schema != NULL) {
4718 WXS_FIND_GLOBAL_ITEM(elemDecl)
4719 }
4720exit:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004721#ifdef DEBUG
4722 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004723 if (nsName == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004724 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004725 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004726 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004727 nsName);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004728 }
4729#endif
4730 return (ret);
4731}
4732
4733/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004734 * xmlSchemaGetType:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004735 * @schema: the main schema
4736 * @name: the type's name
4737 * nsName: the type's namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004738 *
4739 * Lookup a type in the schemas or the predefined types
4740 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004741 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00004742 */
4743static xmlSchemaTypePtr
4744xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004745 const xmlChar * nsName)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004746{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004747 xmlSchemaTypePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004748
4749 if (name == NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004750 return (NULL);
4751 /* First try the built-in types. */
4752 if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4753 ret = xmlSchemaGetPredefinedType(name, nsName);
4754 if (ret != NULL)
4755 goto exit;
4756 /*
4757 * Note that we try the parsed schemas as well here
4758 * since one might have parsed the S4S, which contain more
4759 * than the built-in types.
4760 * TODO: Can we optimize this?
4761 */
4762 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004763 if (schema != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004764 WXS_FIND_GLOBAL_ITEM(typeDecl)
4765 }
4766exit:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004767
Daniel Veillard4255d502002-04-16 15:50:10 +00004768#ifdef DEBUG
4769 if (ret == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004770 if (nsName == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004771 fprintf(stderr, "Unable to lookup type %s", name);
4772 else
4773 fprintf(stderr, "Unable to lookup type %s:%s", name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004774 nsName);
Daniel Veillard4255d502002-04-16 15:50:10 +00004775 }
4776#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004777 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004778}
4779
Daniel Veillard3646d642004-06-02 19:19:14 +00004780/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004781 * xmlSchemaGetAttributeDecl:
4782 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004783 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004784 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004785 *
4786 * Lookup a an attribute in the schema or imported schemas
4787 *
4788 * Returns the attribute declaration or NULL if not found.
4789 */
4790static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004791xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004792 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004793{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004794 xmlSchemaAttributePtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004795
4796 if ((name == NULL) || (schema == NULL))
4797 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004798 if (schema != NULL) {
4799 WXS_FIND_GLOBAL_ITEM(attrDecl)
Daniel Veillard3646d642004-06-02 19:19:14 +00004800 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004801exit:
Daniel Veillard3646d642004-06-02 19:19:14 +00004802#ifdef DEBUG
4803 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004804 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004805 fprintf(stderr, "Unable to lookup attribute %s", name);
4806 else
4807 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004808 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004809 }
4810#endif
4811 return (ret);
4812}
4813
4814/**
4815 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004816 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004817 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004818 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004819 *
4820 * Lookup a an attribute group in the schema or imported schemas
4821 *
4822 * Returns the attribute group definition or NULL if not found.
4823 */
4824static xmlSchemaAttributeGroupPtr
4825xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004826 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004827{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004828 xmlSchemaAttributeGroupPtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004829
4830 if ((name == NULL) || (schema == NULL))
4831 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004832 if (schema != NULL) {
4833 WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4834 }
4835exit:
4836 /* TODO:
4837 if ((ret != NULL) && (ret->redef != NULL)) {
4838 * Return the last redefinition. *
4839 ret = ret->redef;
Daniel Veillard3646d642004-06-02 19:19:14 +00004840 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004841 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004842#ifdef DEBUG
4843 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004844 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004845 fprintf(stderr, "Unable to lookup attribute group %s", name);
4846 else
4847 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004848 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004849 }
4850#endif
4851 return (ret);
4852}
4853
4854/**
4855 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004856 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004857 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004858 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004859 *
4860 * Lookup a group in the schema or imported schemas
4861 *
4862 * Returns the group definition or NULL if not found.
4863 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004864static xmlSchemaModelGroupDefPtr
Daniel Veillard3646d642004-06-02 19:19:14 +00004865xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004866 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004867{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004868 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004869
4870 if ((name == NULL) || (schema == NULL))
4871 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004872 if (schema != NULL) {
4873 WXS_FIND_GLOBAL_ITEM(groupDecl)
Daniel Veillard3646d642004-06-02 19:19:14 +00004874 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004875exit:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004876
Daniel Veillard3646d642004-06-02 19:19:14 +00004877#ifdef DEBUG
4878 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004879 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004880 fprintf(stderr, "Unable to lookup group %s", name);
4881 else
4882 fprintf(stderr, "Unable to lookup group %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004883 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004884 }
4885#endif
4886 return (ret);
4887}
4888
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004889static xmlSchemaNotationPtr
4890xmlSchemaGetNotation(xmlSchemaPtr schema,
4891 const xmlChar *name,
4892 const xmlChar *nsName)
4893{
4894 xmlSchemaNotationPtr ret = NULL;
4895
4896 if ((name == NULL) || (schema == NULL))
4897 return (NULL);
4898 if (schema != NULL) {
4899 WXS_FIND_GLOBAL_ITEM(notaDecl)
4900 }
4901exit:
4902 return (ret);
4903}
4904
4905static xmlSchemaIDCPtr
4906xmlSchemaGetIDC(xmlSchemaPtr schema,
4907 const xmlChar *name,
4908 const xmlChar *nsName)
4909{
4910 xmlSchemaIDCPtr ret = NULL;
4911
4912 if ((name == NULL) || (schema == NULL))
4913 return (NULL);
4914 if (schema != NULL) {
4915 WXS_FIND_GLOBAL_ITEM(idcDef)
4916 }
4917exit:
4918 return (ret);
4919}
4920
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004921/**
4922 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004923 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004924 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004925 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004926 *
4927 * Lookup a group in the schema or imported schemas
4928 *
4929 * Returns the group definition or NULL if not found.
4930 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004931static xmlSchemaBasicItemPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004932xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4933 xmlSchemaTypeType itemType,
4934 const xmlChar *name,
4935 const xmlChar *targetNs)
4936{
4937 switch (itemType) {
4938 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004939 return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004940 name, targetNs));
4941 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004942 return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004943 name, targetNs));
4944 default:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004945 TODO
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004946 return (NULL);
4947 }
4948}
4949
Daniel Veillard4255d502002-04-16 15:50:10 +00004950/************************************************************************
4951 * *
4952 * Parsing functions *
4953 * *
4954 ************************************************************************/
4955
4956#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004957 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00004958
4959/**
4960 * xmlSchemaIsBlank:
4961 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004962 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00004963 *
4964 * Check if a string is ignorable
4965 *
4966 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4967 */
4968static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004969xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004970{
Daniel Veillard4255d502002-04-16 15:50:10 +00004971 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004972 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004973 if (len < 0) {
4974 while (*str != 0) {
4975 if (!(IS_BLANK_CH(*str)))
4976 return (0);
4977 str++;
4978 }
4979 } else while ((*str != 0) && (len != 0)) {
4980 if (!(IS_BLANK_CH(*str)))
4981 return (0);
4982 str++;
4983 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00004984 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004985
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004986 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004987}
4988
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004989#define WXS_COMP_NAME(c, t) ((t) (c))->name
4990#define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
4991/*
4992* xmlSchemaFindRedefCompInGraph:
4993* ATTENTION TODO: This uses pointer comp. for strings.
4994*/
4995static xmlSchemaBasicItemPtr
4996xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
4997 xmlSchemaTypeType type,
4998 const xmlChar *name,
4999 const xmlChar *nsName)
5000{
5001 xmlSchemaBasicItemPtr ret;
5002 int i;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005003
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005004 if ((bucket == NULL) || (name == NULL))
5005 return(NULL);
5006 if ((bucket->globals == NULL) ||
5007 (bucket->globals->nbItems == 0))
5008 goto subschemas;
5009 /*
5010 * Search in global components.
5011 */
5012 for (i = 0; i < bucket->globals->nbItems; i++) {
5013 ret = bucket->globals->items[i];
5014 if (ret->type == type) {
5015 switch (type) {
5016 case XML_SCHEMA_TYPE_COMPLEX:
5017 case XML_SCHEMA_TYPE_SIMPLE:
5018 if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5019 (WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5020 nsName))
5021 {
5022 return(ret);
5023 }
5024 break;
5025 case XML_SCHEMA_TYPE_GROUP:
5026 if ((WXS_COMP_NAME(ret,
5027 xmlSchemaModelGroupDefPtr) == name) &&
5028 (WXS_COMP_TNS(ret,
5029 xmlSchemaModelGroupDefPtr) == nsName))
5030 {
5031 return(ret);
5032 }
5033 break;
5034 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5035 if ((WXS_COMP_NAME(ret,
5036 xmlSchemaAttributeGroupPtr) == name) &&
5037 (WXS_COMP_TNS(ret,
5038 xmlSchemaAttributeGroupPtr) == nsName))
5039 {
5040 return(ret);
5041 }
Kasimier T. Buchcik5d2998b2005-11-22 17:36:01 +00005042 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005043 default:
5044 /* Should not be hit. */
5045 return(NULL);
5046 }
5047 }
5048 }
5049subschemas:
5050 /*
5051 * Process imported/included schemas.
5052 */
5053 if (bucket->relations != NULL) {
5054 xmlSchemaSchemaRelationPtr rel = bucket->relations;
5055
5056 /*
5057 * TODO: Marking the bucket will not avoid multiple searches
5058 * in the same schema, but avoids at least circularity.
5059 */
5060 bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5061 do {
5062 if ((rel->bucket != NULL) &&
5063 ((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5064 ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5065 type, name, nsName);
5066 if (ret != NULL)
5067 return(ret);
5068 }
5069 rel = rel->next;
5070 } while (rel != NULL);
5071 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5072 }
5073 return(NULL);
5074}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005075
5076/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005077 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005078 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005079 * @schema: the schema being built
5080 * @name: the item name
5081 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005082 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00005083 * *WARNING* this interface is highly subject to change
5084 *
5085 * Returns the new struture or NULL in case of error
5086 */
5087static xmlSchemaNotationPtr
5088xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005089 const xmlChar *name, const xmlChar *nsName,
5090 xmlNodePtr node ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00005091{
5092 xmlSchemaNotationPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005093
5094 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5095 return (NULL);
5096
Daniel Veillard4255d502002-04-16 15:50:10 +00005097 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5098 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005099 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005100 return (NULL);
5101 }
5102 memset(ret, 0, sizeof(xmlSchemaNotation));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005103 ret->type = XML_SCHEMA_TYPE_NOTATION;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005104 ret->name = name;
5105 ret->targetNamespace = nsName;
5106 /* TODO: do we need the node to be set?
5107 * ret->node = node;*/
5108 WXS_ADD_GLOBAL(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005109 return (ret);
5110}
5111
Daniel Veillard4255d502002-04-16 15:50:10 +00005112/**
5113 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005114 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005115 * @schema: the schema being built
5116 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005117 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005118 *
5119 * Add an XML schema Attrribute declaration
5120 * *WARNING* this interface is highly subject to change
5121 *
5122 * Returns the new struture or NULL in case of error
5123 */
5124static xmlSchemaAttributePtr
5125xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005126 const xmlChar * name, const xmlChar * nsName,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005127 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005128{
5129 xmlSchemaAttributePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005130
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005131 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005132 return (NULL);
5133
5134 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5135 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005136 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005137 return (NULL);
5138 }
5139 memset(ret, 0, sizeof(xmlSchemaAttribute));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005140 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5141 ret->node = node;
5142 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005143 ret->targetNamespace = nsName;
5144
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005145 if (topLevel)
5146 WXS_ADD_GLOBAL(ctxt, ret);
5147 else
5148 WXS_ADD_LOCAL(ctxt, ret);
5149 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005150 return (ret);
5151}
5152
5153/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005154 * xmlSchemaAddAttributeUse:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005155 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005156 * @schema: the schema being built
5157 * @name: the item name
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005158 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005159 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005160 * Add an XML schema Attrribute declaration
5161 * *WARNING* this interface is highly subject to change
5162 *
5163 * Returns the new struture or NULL in case of error
5164 */
5165static xmlSchemaAttributeUsePtr
5166xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5167 xmlNodePtr node)
5168{
5169 xmlSchemaAttributeUsePtr ret = NULL;
5170
5171 if (pctxt == NULL)
5172 return (NULL);
5173
5174 ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5175 if (ret == NULL) {
5176 xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5177 return (NULL);
5178 }
5179 memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5180 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5181 ret->node = node;
5182
5183 WXS_ADD_LOCAL(pctxt, ret);
5184 return (ret);
5185}
5186
5187/*
5188* xmlSchemaAddRedef:
5189*
5190* Adds a redefinition information. This is used at a later stage to:
5191* resolve references to the redefined components and to check constraints.
5192*/
5193static xmlSchemaRedefPtr
5194xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5195 xmlSchemaBucketPtr targetBucket,
5196 void *item,
5197 const xmlChar *refName,
5198 const xmlChar *refTargetNs)
5199{
5200 xmlSchemaRedefPtr ret;
5201
5202 ret = (xmlSchemaRedefPtr)
5203 xmlMalloc(sizeof(xmlSchemaRedef));
5204 if (ret == NULL) {
5205 xmlSchemaPErrMemory(pctxt,
5206 "allocating redefinition info", NULL);
5207 return (NULL);
5208 }
5209 memset(ret, 0, sizeof(xmlSchemaRedef));
5210 ret->item = item;
5211 ret->targetBucket = targetBucket;
5212 ret->refName = refName;
5213 ret->refTargetNs = refTargetNs;
5214 if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5215 WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5216 else
5217 WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5218 WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5219
5220 return (ret);
5221}
5222
5223/**
5224 * xmlSchemaAddAttributeGroupDefinition:
5225 * @ctxt: a schema parser context
5226 * @schema: the schema being built
5227 * @name: the item name
5228 * @nsName: the target namespace
5229 * @node: the corresponding node
5230 *
5231 * Add an XML schema Attrribute Group definition.
Daniel Veillard4255d502002-04-16 15:50:10 +00005232 *
5233 * Returns the new struture or NULL in case of error
5234 */
5235static xmlSchemaAttributeGroupPtr
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005236xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5237 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5238 const xmlChar *name,
5239 const xmlChar *nsName,
5240 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005241{
5242 xmlSchemaAttributeGroupPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005243
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005244 if ((pctxt == NULL) || (name == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005245 return (NULL);
5246
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005247 ret = (xmlSchemaAttributeGroupPtr)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005248 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00005249 if (ret == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005250 xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005251 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005252 }
5253 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005254 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005255 ret->name = name;
5256 ret->targetNamespace = nsName;
5257 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005258
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005259 /* TODO: Remove the flag. */
5260 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5261 if (pctxt->isRedefine) {
5262 pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5263 ret, name, nsName);
5264 if (pctxt->redef == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005265 xmlFree(ret);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005266 return(NULL);
5267 }
5268 pctxt->redefCounter = 0;
5269 }
5270 WXS_ADD_GLOBAL(pctxt, ret);
5271 WXS_ADD_PENDING(pctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005272 return (ret);
5273}
5274
5275/**
5276 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005277 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005278 * @schema: the schema being built
5279 * @name: the type name
5280 * @namespace: the type namespace
5281 *
5282 * Add an XML schema Element declaration
5283 * *WARNING* this interface is highly subject to change
5284 *
5285 * Returns the new struture or NULL in case of error
5286 */
5287static xmlSchemaElementPtr
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005288xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005289 const xmlChar * name, const xmlChar * nsName,
William M. Brack2f2a6632004-08-20 23:09:47 +00005290 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005291{
5292 xmlSchemaElementPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005293
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005294 if ((ctxt == NULL) || (name == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005295 return (NULL);
5296
Daniel Veillard4255d502002-04-16 15:50:10 +00005297 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5298 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005299 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005300 return (NULL);
5301 }
5302 memset(ret, 0, sizeof(xmlSchemaElement));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005303 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5304 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005305 ret->targetNamespace = nsName;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005306 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005307
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005308 if (topLevel)
5309 WXS_ADD_GLOBAL(ctxt, ret);
5310 else
5311 WXS_ADD_LOCAL(ctxt, ret);
5312 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005313 return (ret);
5314}
5315
5316/**
5317 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00005318 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005319 * @schema: the schema being built
5320 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005321 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005322 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005323 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00005324 * *WARNING* this interface is highly subject to change
5325 *
5326 * Returns the new struture or NULL in case of error
5327 */
5328static xmlSchemaTypePtr
5329xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005330 xmlSchemaTypeType type,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00005331 const xmlChar * name, const xmlChar * nsName,
5332 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005333{
5334 xmlSchemaTypePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005335
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005336 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005337 return (NULL);
5338
5339 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5340 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005341 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005342 return (NULL);
5343 }
5344 memset(ret, 0, sizeof(xmlSchemaType));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005345 ret->type = type;
5346 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005347 ret->targetNamespace = nsName;
5348 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005349 if (topLevel) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005350 if (ctxt->isRedefine) {
5351 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5352 ret, name, nsName);
5353 if (ctxt->redef == NULL) {
5354 xmlFree(ret);
5355 return(NULL);
5356 }
5357 ctxt->redefCounter = 0;
5358 }
5359 WXS_ADD_GLOBAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005360 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005361 WXS_ADD_LOCAL(ctxt, ret);
5362 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005363 return (ret);
5364}
5365
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005366static xmlSchemaQNameRefPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005367xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005368 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005369 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005370 const xmlChar *refNs)
5371{
5372 xmlSchemaQNameRefPtr ret;
5373
5374 ret = (xmlSchemaQNameRefPtr)
5375 xmlMalloc(sizeof(xmlSchemaQNameRef));
5376 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005377 xmlSchemaPErrMemory(pctxt,
5378 "allocating QName reference item", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005379 return (NULL);
5380 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005381 ret->node = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005382 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5383 ret->name = refName;
5384 ret->targetNamespace = refNs;
5385 ret->item = NULL;
5386 ret->itemType = refType;
5387 /*
5388 * Store the reference item in the schema.
5389 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005390 WXS_ADD_LOCAL(pctxt, ret);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005391 return (ret);
5392}
5393
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005394static xmlSchemaAttributeUseProhibPtr
5395xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5396{
5397 xmlSchemaAttributeUseProhibPtr ret;
5398
5399 ret = (xmlSchemaAttributeUseProhibPtr)
5400 xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5401 if (ret == NULL) {
5402 xmlSchemaPErrMemory(pctxt,
5403 "allocating attribute use prohibition", NULL);
5404 return (NULL);
5405 }
5406 memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5407 ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5408 WXS_ADD_LOCAL(pctxt, ret);
5409 return (ret);
5410}
5411
5412
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005413/**
5414 * xmlSchemaAddModelGroup:
5415 * @ctxt: a schema parser context
5416 * @schema: the schema being built
5417 * @type: the "compositor" type of the model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005418 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005419 *
5420 * Adds a schema model group
5421 * *WARNING* this interface is highly subject to change
5422 *
5423 * Returns the new struture or NULL in case of error
5424 */
5425static xmlSchemaModelGroupPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005426xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5427 xmlSchemaPtr schema,
5428 xmlSchemaTypeType type,
5429 xmlNodePtr node)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005430{
5431 xmlSchemaModelGroupPtr ret = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005432
5433 if ((ctxt == NULL) || (schema == NULL))
5434 return (NULL);
5435
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005436 ret = (xmlSchemaModelGroupPtr)
5437 xmlMalloc(sizeof(xmlSchemaModelGroup));
5438 if (ret == NULL) {
5439 xmlSchemaPErrMemory(ctxt, "allocating model group component",
5440 NULL);
5441 return (NULL);
5442 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005443 memset(ret, 0, sizeof(xmlSchemaModelGroup));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005444 ret->type = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005445 ret->node = node;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005446 WXS_ADD_LOCAL(ctxt, ret);
5447 if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5448 (type == XML_SCHEMA_TYPE_CHOICE))
5449 WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005450 return (ret);
5451}
5452
5453
5454/**
5455 * xmlSchemaAddParticle:
5456 * @ctxt: a schema parser context
5457 * @schema: the schema being built
5458 * @node: the corresponding node in the schema doc
5459 * @min: the minOccurs
5460 * @max: the maxOccurs
5461 *
5462 * Adds an XML schema particle component.
5463 * *WARNING* this interface is highly subject to change
5464 *
5465 * Returns the new struture or NULL in case of error
5466 */
5467static xmlSchemaParticlePtr
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +00005468xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005469 xmlNodePtr node, int min, int max)
5470{
5471 xmlSchemaParticlePtr ret = NULL;
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +00005472 if (ctxt == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005473 return (NULL);
5474
5475#ifdef DEBUG
5476 fprintf(stderr, "Adding particle component\n");
5477#endif
5478 ret = (xmlSchemaParticlePtr)
5479 xmlMalloc(sizeof(xmlSchemaParticle));
5480 if (ret == NULL) {
5481 xmlSchemaPErrMemory(ctxt, "allocating particle component",
5482 NULL);
5483 return (NULL);
5484 }
5485 ret->type = XML_SCHEMA_TYPE_PARTICLE;
5486 ret->annot = NULL;
5487 ret->node = node;
5488 ret->minOccurs = min;
5489 ret->maxOccurs = max;
5490 ret->next = NULL;
5491 ret->children = NULL;
5492
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005493 WXS_ADD_LOCAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005494 /*
5495 * Note that addition to pending components will be done locally
5496 * to the specific parsing function, since the most particles
5497 * need not to be fixed up (i.e. the reference to be resolved).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005498 * REMOVED: WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005499 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005500 return (ret);
5501}
5502
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005503/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005504 * xmlSchemaAddModelGroupDefinition:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005505 * @ctxt: a schema validation context
5506 * @schema: the schema being built
5507 * @name: the group name
5508 *
5509 * Add an XML schema Group definition
5510 *
5511 * Returns the new struture or NULL in case of error
5512 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005513static xmlSchemaModelGroupDefPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005514xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5515 xmlSchemaPtr schema,
5516 const xmlChar *name,
5517 const xmlChar *nsName,
5518 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005519{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005520 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005521
5522 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5523 return (NULL);
5524
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005525 ret = (xmlSchemaModelGroupDefPtr)
5526 xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005527 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005528 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005529 return (NULL);
5530 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005531 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005532 ret->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005533 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005534 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005535 ret->targetNamespace = nsName;
5536
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005537 if (ctxt->isRedefine) {
5538 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5539 ret, name, nsName);
5540 if (ctxt->redef == NULL) {
5541 xmlFree(ret);
5542 return(NULL);
5543 }
5544 ctxt->redefCounter = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005545 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005546 WXS_ADD_GLOBAL(ctxt, ret);
5547 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005548 return (ret);
5549}
5550
Daniel Veillard3646d642004-06-02 19:19:14 +00005551/**
5552 * xmlSchemaNewWildcardNs:
5553 * @ctxt: a schema validation context
5554 *
5555 * Creates a new wildcard namespace constraint.
5556 *
5557 * Returns the new struture or NULL in case of error
5558 */
5559static xmlSchemaWildcardNsPtr
5560xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5561{
5562 xmlSchemaWildcardNsPtr ret;
5563
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005564 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005565 xmlMalloc(sizeof(xmlSchemaWildcardNs));
5566 if (ret == NULL) {
5567 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005568 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00005569 }
5570 ret->value = NULL;
5571 ret->next = NULL;
5572 return (ret);
5573}
5574
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005575static xmlSchemaIDCPtr
5576xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5577 const xmlChar *name, const xmlChar *nsName,
5578 int category, xmlNodePtr node)
5579{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005580 xmlSchemaIDCPtr ret = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005581
5582 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5583 return (NULL);
5584
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005585 ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5586 if (ret == NULL) {
5587 xmlSchemaPErrMemory(ctxt,
5588 "allocating an identity-constraint definition", NULL);
5589 return (NULL);
5590 }
5591 memset(ret, 0, sizeof(xmlSchemaIDC));
5592 /* The target namespace of the parent element declaration. */
5593 ret->targetNamespace = nsName;
5594 ret->name = name;
5595 ret->type = category;
5596 ret->node = node;
5597
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005598 WXS_ADD_GLOBAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005599 /*
5600 * Only keyrefs need to be fixup up.
5601 */
5602 if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005603 WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005604 return (ret);
5605}
5606
Daniel Veillard3646d642004-06-02 19:19:14 +00005607/**
5608 * xmlSchemaAddWildcard:
5609 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005610 * @schema: a schema
5611 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005612 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005613 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00005614 *
5615 * Returns the new struture or NULL in case of error
5616 */
5617static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005618xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5619 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00005620{
5621 xmlSchemaWildcardPtr ret = NULL;
5622
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005623 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00005624 return (NULL);
5625
5626 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5627 if (ret == NULL) {
5628 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5629 return (NULL);
5630 }
5631 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005632 ret->type = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005633 ret->node = node;
5634 WXS_ADD_LOCAL(ctxt, ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00005635 return (ret);
5636}
5637
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005638static void
5639xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5640{
5641 if (group == NULL)
5642 return;
5643 if (group->members != NULL)
5644 xmlSchemaItemListFree(group->members);
5645 xmlFree(group);
5646}
5647
5648static xmlSchemaSubstGroupPtr
5649xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5650 xmlSchemaElementPtr head)
5651{
5652 xmlSchemaSubstGroupPtr ret;
5653
5654 /* Init subst group hash. */
5655 if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5656 WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5657 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5658 return(NULL);
5659 }
5660 /* Create a new substitution group. */
5661 ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5662 if (ret == NULL) {
5663 xmlSchemaPErrMemory(NULL,
5664 "allocating a substitution group container", NULL);
5665 return(NULL);
5666 }
5667 memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5668 ret->head = head;
5669 /* Create list of members. */
5670 ret->members = xmlSchemaItemListCreate();
5671 if (ret->members == NULL) {
5672 xmlSchemaSubstGroupFree(ret);
5673 return(NULL);
5674 }
5675 /* Add subst group to hash. */
5676 if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5677 head->name, head->targetNamespace, ret) != 0) {
5678 PERROR_INT("xmlSchemaSubstGroupAdd",
5679 "failed to add a new substitution container");
5680 xmlSchemaSubstGroupFree(ret);
5681 return(NULL);
5682 }
5683 return(ret);
5684}
5685
5686static xmlSchemaSubstGroupPtr
5687xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5688 xmlSchemaElementPtr head)
5689{
5690 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5691 return(NULL);
5692 return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5693 head->name, head->targetNamespace));
5694
5695}
5696
5697/**
5698 * xmlSchemaAddElementSubstitutionMember:
5699 * @pctxt: a schema parser context
5700 * @head: the head of the substitution group
5701 * @member: the new member of the substitution group
5702 *
5703 * Allocate a new annotation structure.
5704 *
5705 * Returns the newly allocated structure or NULL in case or error
5706 */
5707static int
5708xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5709 xmlSchemaElementPtr head,
5710 xmlSchemaElementPtr member)
5711{
5712 xmlSchemaSubstGroupPtr substGroup = NULL;
5713
5714 if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5715 return (-1);
5716
5717 substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5718 if (substGroup == NULL)
5719 substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5720 if (substGroup == NULL)
5721 return(-1);
5722 if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5723 return(-1);
5724 return(0);
5725}
5726
Daniel Veillard4255d502002-04-16 15:50:10 +00005727/************************************************************************
5728 * *
5729 * Utilities for parsing *
5730 * *
5731 ************************************************************************/
5732
Daniel Veillard4255d502002-04-16 15:50:10 +00005733/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005734 * xmlSchemaPValAttrNodeQNameValue:
5735 * @ctxt: a schema parser context
5736 * @schema: the schema context
5737 * @ownerDes: the designation of the parent element
5738 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005739 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00005740 * @local: the resulting local part if found, the attribute value otherwise
5741 * @uri: the resulting namespace URI if found
5742 *
5743 * Extracts the local name and the URI of a QName value and validates it.
5744 * This one is intended to be used on attribute values that
5745 * should resolve to schema components.
5746 *
5747 * Returns 0, in case the QName is valid, a positive error code
5748 * if not valid and -1 if an internal error occurs.
5749 */
5750static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005751xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005752 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005753 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005754 xmlAttrPtr attr,
5755 const xmlChar *value,
5756 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005757 const xmlChar **local)
5758{
5759 const xmlChar *pref;
5760 xmlNsPtr ns;
5761 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005762
Daniel Veillardc0826a72004-08-10 14:17:33 +00005763 *uri = NULL;
5764 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005765 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005766 if (ret > 0) {
5767 xmlSchemaPSimpleTypeErr(ctxt,
5768 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5769 ownerItem, (xmlNodePtr) attr,
5770 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5771 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005772 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005773 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005774 } else if (ret < 0)
5775 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005776
5777 if (!strchr((char *) value, ':')) {
Daniel Veillard24505b02005-07-28 23:49:35 +00005778 ns = xmlSearchNs(attr->doc, attr->parent, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005779 if (ns)
5780 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5781 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005782 /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5783 * parser context. */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005784 /*
5785 * This one takes care of included schemas with no
5786 * target namespace.
5787 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005788 *uri = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005789 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005790 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005791 return (0);
5792 }
5793 /*
5794 * At this point xmlSplitQName3 has to return a local name.
5795 */
5796 *local = xmlSplitQName3(value, &len);
5797 *local = xmlDictLookup(ctxt->dict, *local, -1);
5798 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005799 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5800 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005801 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005802 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005803 ownerItem, (xmlNodePtr) attr,
5804 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5805 "The value '%s' of simple type 'xs:QName' has no "
5806 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005807 return (ctxt->err);
5808 } else {
5809 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005810 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005811 return (0);
5812}
5813
5814/**
5815 * xmlSchemaPValAttrNodeQName:
5816 * @ctxt: a schema parser context
5817 * @schema: the schema context
5818 * @ownerDes: the designation of the owner element
5819 * @ownerItem: the owner as a schema object
5820 * @attr: the attribute node
5821 * @local: the resulting local part if found, the attribute value otherwise
5822 * @uri: the resulting namespace URI if found
5823 *
5824 * Extracts and validates the QName of an attribute value.
5825 * This one is intended to be used on attribute values that
5826 * should resolve to schema components.
5827 *
5828 * Returns 0, in case the QName is valid, a positive error code
5829 * if not valid and -1 if an internal error occurs.
5830 */
5831static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005832xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005833 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005834 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005835 xmlAttrPtr attr,
5836 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005837 const xmlChar **local)
5838{
5839 const xmlChar *value;
5840
5841 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005842 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005843 ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005844}
5845
5846/**
5847 * xmlSchemaPValAttrQName:
5848 * @ctxt: a schema parser context
5849 * @schema: the schema context
5850 * @ownerDes: the designation of the parent element
5851 * @ownerItem: the owner as a schema object
5852 * @ownerElem: the parent node of the attribute
5853 * @name: the name of the attribute
5854 * @local: the resulting local part if found, the attribute value otherwise
5855 * @uri: the resulting namespace URI if found
5856 *
5857 * Extracts and validates the QName of an attribute value.
5858 *
5859 * Returns 0, in case the QName is valid, a positive error code
5860 * if not valid and -1 if an internal error occurs.
5861 */
5862static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005863xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5864 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005865 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005866 xmlNodePtr ownerElem,
5867 const char *name,
5868 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005869 const xmlChar **local)
5870{
5871 xmlAttrPtr attr;
5872
5873 attr = xmlSchemaGetPropNode(ownerElem, name);
5874 if (attr == NULL) {
5875 *local = NULL;
5876 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005877 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005878 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005879 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005880 ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005881}
5882
5883/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005884 * xmlSchemaPValAttrID:
5885 * @ctxt: a schema parser context
5886 * @schema: the schema context
5887 * @ownerDes: the designation of the parent element
5888 * @ownerItem: the owner as a schema object
5889 * @ownerElem: the parent node of the attribute
5890 * @name: the name of the attribute
5891 *
5892 * Extracts and validates the ID of an attribute value.
5893 *
5894 * Returns 0, in case the ID is valid, a positive error code
5895 * if not valid and -1 if an internal error occurs.
5896 */
5897static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005898xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005899{
5900 int ret;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005901 const xmlChar *value;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005902
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005903 if (attr == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005904 return(0);
5905 value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5906 ret = xmlValidateNCName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005907 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005908 /*
5909 * NOTE: the IDness might have already be declared in the DTD
5910 */
5911 if (attr->atype != XML_ATTRIBUTE_ID) {
5912 xmlIDPtr res;
5913 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005914
5915 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005916 * TODO: Use xmlSchemaStrip here; it's not exported at this
5917 * moment.
5918 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005919 strip = xmlSchemaCollapseString(value);
5920 if (strip != NULL) {
5921 xmlFree((xmlChar *) value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005922 value = strip;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005923 }
5924 res = xmlAddID(NULL, attr->doc, value, attr);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005925 if (res == NULL) {
5926 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005927 xmlSchemaPSimpleTypeErr(ctxt,
5928 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005929 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005930 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5931 NULL, NULL, "Duplicate value '%s' of simple "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005932 "type 'xs:ID'", value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005933 } else
5934 attr->atype = XML_ATTRIBUTE_ID;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005935 }
5936 } else if (ret > 0) {
5937 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005938 xmlSchemaPSimpleTypeErr(ctxt,
5939 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005940 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005941 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5942 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5943 "not a valid 'xs:NCName'",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005944 value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005945 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005946 if (value != NULL)
5947 xmlFree((xmlChar *)value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005948
5949 return (ret);
5950}
5951
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005952static int
5953xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5954 xmlNodePtr ownerElem,
5955 const xmlChar *name)
5956{
5957 xmlAttrPtr attr;
5958
5959 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5960 if (attr == NULL)
5961 return(0);
5962 return(xmlSchemaPValAttrNodeID(ctxt, attr));
5963
5964}
5965
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005966/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005967 * xmlGetMaxOccurs:
5968 * @ctxt: a schema validation context
5969 * @node: a subtree containing XML Schema informations
5970 *
5971 * Get the maxOccurs property
5972 *
5973 * Returns the default if not found, or the value
5974 */
5975static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005976xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5977 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005978{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005979 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005980 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005981 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005982
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005983 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5984 if (attr == NULL)
5985 return (def);
5986 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005987
5988 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005989 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005990 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005991 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5992 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005993 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005994 val, NULL, NULL, NULL);
5995 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005996 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005997 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005998 }
5999
6000 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00006001 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006002 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006003 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006004 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006005 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6006 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006007 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006008 val, NULL, NULL, NULL);
6009 return (def);
6010 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006011 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006012 ret = ret * 10 + (*cur - '0');
6013 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00006014 }
William M. Brack76e95df2003-10-18 16:20:14 +00006015 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006016 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006017 /*
6018 * TODO: Restrict the maximal value to Integer.
6019 */
6020 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006021 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006022 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6023 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006024 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006025 val, NULL, NULL, NULL);
6026 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006027 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006028 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006029}
6030
6031/**
6032 * xmlGetMinOccurs:
6033 * @ctxt: a schema validation context
6034 * @node: a subtree containing XML Schema informations
6035 *
6036 * Get the minOccurs property
6037 *
6038 * Returns the default if not found, or the value
6039 */
6040static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006041xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006042 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006043{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006044 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00006045 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006046 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006047
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006048 attr = xmlSchemaGetPropNode(node, "minOccurs");
6049 if (attr == NULL)
6050 return (def);
6051 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00006052 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00006053 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006054 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006055 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006056 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006057 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6058 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006059 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006060 val, NULL, NULL, NULL);
6061 return (def);
6062 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006063 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006064 ret = ret * 10 + (*cur - '0');
6065 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00006066 }
William M. Brack76e95df2003-10-18 16:20:14 +00006067 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006068 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006069 /*
6070 * TODO: Restrict the maximal value to Integer.
6071 */
6072 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006073 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006074 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6075 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006076 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006077 val, NULL, NULL, NULL);
6078 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006079 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006080 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006081}
6082
6083/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006084 * xmlSchemaPGetBoolNodeValue:
6085 * @ctxt: a schema validation context
6086 * @ownerDes: owner designation
6087 * @ownerItem: the owner as a schema item
6088 * @node: the node holding the value
6089 *
6090 * Converts a boolean string value into 1 or 0.
6091 *
6092 * Returns 0 or 1.
6093 */
6094static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006095xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006096 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006097 xmlNodePtr node)
6098{
6099 xmlChar *value = NULL;
6100 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006101
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006102 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006103 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006104 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006105 * An instance of a datatype that is defined as ·boolean·
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006106 * can have the following legal literals {true, false, 1, 0}.
6107 */
6108 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6109 res = 1;
6110 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6111 res = 0;
6112 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6113 res = 1;
6114 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006115 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006116 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006117 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006118 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006119 ownerItem, node,
6120 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6121 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006122 NULL, NULL, NULL);
6123 }
6124 if (value != NULL)
6125 xmlFree(value);
6126 return (res);
6127}
6128
6129/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006130 * xmlGetBooleanProp:
6131 * @ctxt: a schema validation context
6132 * @node: a subtree containing XML Schema informations
6133 * @name: the attribute name
6134 * @def: the default value
6135 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006136 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00006137 *
6138 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006139 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00006140 */
6141static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006142xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006143 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006144 const char *name, int def)
6145{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006146 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00006147
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006148 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006149 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006150 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006151 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006152 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006153 * An instance of a datatype that is defined as ·boolean·
Daniel Veillardc0826a72004-08-10 14:17:33 +00006154 * can have the following legal literals {true, false, 1, 0}.
6155 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006156 if (xmlStrEqual(val, BAD_CAST "true"))
6157 def = 1;
6158 else if (xmlStrEqual(val, BAD_CAST "false"))
6159 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006160 else if (xmlStrEqual(val, BAD_CAST "1"))
6161 def = 1;
6162 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006163 def = 0;
6164 else {
6165 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006166 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006167 NULL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006168 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006169 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6170 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006171 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006172 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006173}
6174
6175/************************************************************************
6176 * *
6177 * Shema extraction from an Infoset *
6178 * *
6179 ************************************************************************/
6180static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6181 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006182 xmlNodePtr node,
6183 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006184static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6185 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00006186 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006187 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00006188 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006189static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6190 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00006191 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006192 xmlNodePtr node,
6193 xmlSchemaTypeType parentType);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006194static xmlSchemaBasicItemPtr
6195xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6196 xmlSchemaPtr schema,
6197 xmlNodePtr node,
6198 xmlSchemaItemListPtr uses,
6199 int parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00006200static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6201 xmlSchemaPtr schema,
6202 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00006203static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006204xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6205 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006206
6207/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006208 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006209 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00006210 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00006211 * @ownerDes: the designation of the parent element
6212 * @ownerItem: the schema object owner if existent
6213 * @attr: the schema attribute node being validated
6214 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006215 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00006216 *
6217 * Validates a value against the given built-in type.
6218 * This one is intended to be used internally for validation
6219 * of schema attribute values during parsing of the schema.
6220 *
6221 * Returns 0 if the value is valid, a positive error code
6222 * number otherwise and -1 in case of an internal or API error.
6223 */
6224static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006225xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006226 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006227 xmlAttrPtr attr,
6228 const xmlChar *value,
6229 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00006230{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006231
6232 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006233
6234 /*
6235 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6236 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006237 */
6238 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00006239 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006240 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6241 PERROR_INT("xmlSchemaPValAttrNodeValue",
6242 "the given type is not a built-in type");
6243 return (-1);
6244 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006245 switch (type->builtInType) {
6246 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006247 case XML_SCHEMAS_QNAME:
6248 case XML_SCHEMAS_ANYURI:
6249 case XML_SCHEMAS_TOKEN:
6250 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006251 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6252 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006253 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006254 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006255 PERROR_INT("xmlSchemaPValAttrNodeValue",
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +00006256 "validation using the given type is not supported while "
6257 "parsing a schema");
Daniel Veillard01fa6152004-06-29 17:04:39 +00006258 return (-1);
6259 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006260 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006261 /*
6262 * TODO: Should we use the S4S error codes instead?
6263 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006264 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006265 PERROR_INT("xmlSchemaPValAttrNodeValue",
6266 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006267 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006268 } else if (ret > 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006269 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006270 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6271 else
6272 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6273 xmlSchemaPSimpleTypeErr(pctxt,
6274 ret, ownerItem, (xmlNodePtr) attr,
6275 type, NULL, value, NULL, NULL, NULL);
6276 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006277 return (ret);
6278}
6279
6280/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006281 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006282 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006283 * @ctxt: a schema parser context
6284 * @ownerDes: the designation of the parent element
6285 * @ownerItem: the schema object owner if existent
6286 * @attr: the schema attribute node being validated
6287 * @type: the built-in type to be validated against
6288 * @value: the resulting value if any
6289 *
6290 * Extracts and validates a value against the given built-in type.
6291 * This one is intended to be used internally for validation
6292 * of schema attribute values during parsing of the schema.
6293 *
6294 * Returns 0 if the value is valid, a positive error code
6295 * number otherwise and -1 in case of an internal or API error.
6296 */
6297static int
6298xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006299 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006300 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006301 xmlSchemaTypePtr type,
6302 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006303{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006304 const xmlChar *val;
6305
6306 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006307 return (-1);
6308
Daniel Veillardc0826a72004-08-10 14:17:33 +00006309 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6310 if (value != NULL)
6311 *value = val;
6312
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006313 return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006314 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00006315}
6316
6317/**
6318 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006319 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006320 * @ctxt: a schema parser context
6321 * @node: the element node of the attribute
6322 * @ownerDes: the designation of the parent element
6323 * @ownerItem: the schema object owner if existent
6324 * @ownerElem: the owner element node
6325 * @name: the name of the schema attribute node
6326 * @type: the built-in type to be validated against
6327 * @value: the resulting value if any
6328 *
6329 * Extracts and validates a value against the given built-in type.
6330 * This one is intended to be used internally for validation
6331 * of schema attribute values during parsing of the schema.
6332 *
6333 * Returns 0 if the value is valid, a positive error code
6334 * number otherwise and -1 in case of an internal or API error.
6335 */
6336static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006337xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6338 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006339 xmlNodePtr ownerElem,
6340 const char *name,
6341 xmlSchemaTypePtr type,
6342 const xmlChar **value)
6343{
6344 xmlAttrPtr attr;
6345
6346 if ((ctxt == NULL) || (type == NULL)) {
6347 if (value != NULL)
6348 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006349 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006350 }
6351 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6352 if (value != NULL)
6353 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006354 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006355 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006356 "Internal error: xmlSchemaPValAttr, the given "
6357 "type '%s' is not a built-in type.\n",
6358 type->name, NULL);
6359 return (-1);
6360 }
6361 attr = xmlSchemaGetPropNode(ownerElem, name);
6362 if (attr == NULL) {
6363 if (value != NULL)
6364 *value = NULL;
6365 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006366 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006367 return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006368 type, value));
6369}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006370
6371static int
6372xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006373 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006374 xmlNodePtr node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006375 xmlAttrPtr attr,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006376 const xmlChar *namespaceName)
6377{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006378 /* TODO: Pointer comparison instead? */
6379 if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006380 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006381 if (xmlStrEqual(xmlSchemaNs, namespaceName))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006382 return (0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006383 /*
6384 * Check if the referenced namespace was <import>ed.
6385 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006386 if (WXS_BUCKET(pctxt)->relations != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006387 xmlSchemaSchemaRelationPtr rel;
6388
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006389 rel = WXS_BUCKET(pctxt)->relations;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006390 do {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006391 if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006392 xmlStrEqual(namespaceName, rel->importNamespace))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006393 return (0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006394 rel = rel->next;
6395 } while (rel != NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006396 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006397 /*
6398 * No matching <import>ed namespace found.
6399 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006400 {
6401 xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6402
6403 if (namespaceName == NULL)
6404 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6405 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6406 "References from this schema to components in no "
6407 "namespace are not allowed, since not indicated by an "
6408 "import statement", NULL, NULL);
6409 else
6410 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6411 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6412 "References from this schema to components in the "
6413 "namespace '%s' are not allowed, since not indicated by an "
6414 "import statement", namespaceName, NULL);
6415 }
6416 return (XML_SCHEMAP_SRC_RESOLVE);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006417}
6418
Daniel Veillardc0826a72004-08-10 14:17:33 +00006419/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006420 * xmlSchemaParseLocalAttributes:
Daniel Veillard4255d502002-04-16 15:50:10 +00006421 * @ctxt: a schema validation context
6422 * @schema: the schema being built
6423 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006424 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00006425 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006426 * Parses attribute uses and attribute declarations and
6427 * attribute group references.
Daniel Veillard4255d502002-04-16 15:50:10 +00006428 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006429static int
6430xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6431 xmlNodePtr *child, xmlSchemaItemListPtr *list,
6432 int parentType, int *hasRefs)
Daniel Veillard4255d502002-04-16 15:50:10 +00006433{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006434 void *item;
Daniel Veillard4255d502002-04-16 15:50:10 +00006435
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006436 while ((IS_SCHEMA((*child), "attribute")) ||
6437 (IS_SCHEMA((*child), "attributeGroup"))) {
6438 if (IS_SCHEMA((*child), "attribute")) {
6439 item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6440 *list, parentType);
6441 } else {
6442 item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6443 if ((item != NULL) && (hasRefs != NULL))
6444 *hasRefs = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006445 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006446 if (item != NULL) {
6447 if (*list == NULL) {
6448 /* TODO: Customize grow factor. */
6449 *list = xmlSchemaItemListCreate();
6450 if (*list == NULL)
6451 return(-1);
6452 }
6453 if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6454 return(-1);
6455 }
6456 *child = (*child)->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006457 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006458 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006459}
6460
6461/**
6462 * xmlSchemaParseAnnotation:
6463 * @ctxt: a schema validation context
6464 * @schema: the schema being built
6465 * @node: a subtree containing XML Schema informations
6466 *
6467 * parse a XML schema Attrribute declaration
6468 * *WARNING* this interface is highly subject to change
6469 *
William M. Bracke7091952004-05-11 15:09:58 +00006470 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006471 * 1 in case of success.
6472 */
6473static xmlSchemaAnnotPtr
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00006474xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
Daniel Veillard4255d502002-04-16 15:50:10 +00006475{
6476 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006477 xmlNodePtr child = NULL;
6478 xmlAttrPtr attr;
6479 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00006480
Daniel Veillardc0826a72004-08-10 14:17:33 +00006481 /*
6482 * INFO: S4S completed.
6483 */
6484 /*
6485 * id = ID
6486 * {any attributes with non-schema namespace . . .}>
6487 * Content: (appinfo | documentation)*
6488 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00006489 if ((ctxt == NULL) || (node == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00006490 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006491 if (needed)
6492 ret = xmlSchemaNewAnnot(ctxt, node);
6493 else
6494 ret = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006495 attr = node->properties;
6496 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006497 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006498 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006499 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006500 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006501
6502 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006503 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006504 }
6505 attr = attr->next;
6506 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006507 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006508 /*
6509 * And now for the children...
6510 */
6511 child = node->children;
6512 while (child != NULL) {
6513 if (IS_SCHEMA(child, "appinfo")) {
6514 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006515 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006516 * source = anyURI
6517 * {any attributes with non-schema namespace . . .}>
6518 * Content: ({any})*
6519 */
6520 attr = child->properties;
6521 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006522 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006523 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006524 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006525 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006526
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006527 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006528 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006529 }
6530 attr = attr->next;
6531 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006532 xmlSchemaPValAttr(ctxt, NULL, child, "source",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006533 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006534 child = child->next;
6535 } else if (IS_SCHEMA(child, "documentation")) {
6536 /* TODO: make available the content of "documentation". */
6537 /*
6538 * source = anyURI
6539 * {any attributes with non-schema namespace . . .}>
6540 * Content: ({any})*
6541 */
6542 attr = child->properties;
6543 while (attr != NULL) {
6544 if (attr->ns == NULL) {
6545 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006546 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 } else {
6550 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6551 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
6552 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006553
6554 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006555 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006556 }
6557 }
6558 attr = attr->next;
6559 }
6560 /*
6561 * Attribute "xml:lang".
6562 */
6563 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6564 if (attr != NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006565 xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006566 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006567 child = child->next;
6568 } else {
6569 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006570 xmlSchemaPContentErr(ctxt,
6571 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006572 NULL, node, child, NULL, "(appinfo | documentation)*");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006573 barked = 1;
6574 child = child->next;
6575 }
6576 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006577
Daniel Veillard4255d502002-04-16 15:50:10 +00006578 return (ret);
6579}
6580
6581/**
6582 * xmlSchemaParseFacet:
6583 * @ctxt: a schema validation context
6584 * @schema: the schema being built
6585 * @node: a subtree containing XML Schema informations
6586 *
6587 * parse a XML schema Facet declaration
6588 * *WARNING* this interface is highly subject to change
6589 *
6590 * Returns the new type structure or NULL in case of error
6591 */
6592static xmlSchemaFacetPtr
6593xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006594 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006595{
6596 xmlSchemaFacetPtr facet;
6597 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006598 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00006599
6600 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6601 return (NULL);
6602
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006603 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006604 if (facet == NULL) {
6605 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6606 return (NULL);
6607 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006608 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006609 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00006610 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006611 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6612 "Facet %s has no value\n", node->name, NULL);
6613 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00006614 return (NULL);
6615 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006616 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006617 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006618 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006619 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006620 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006621 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006622 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006623 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006624 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006625 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006626 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006627 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006628 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006629 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006630 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006631 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006632 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006633 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006634 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006635 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006636 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006637 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6638 } else if (IS_SCHEMA(node, "minLength")) {
6639 facet->type = XML_SCHEMA_FACET_MINLENGTH;
6640 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006641 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6642 "Unknown facet type %s\n", node->name, NULL);
6643 xmlSchemaFreeFacet(facet);
6644 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006645 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006646 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006647 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006648 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6649 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6650 const xmlChar *fixed;
6651
6652 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6653 if (fixed != NULL) {
6654 if (xmlStrEqual(fixed, BAD_CAST "true"))
6655 facet->fixed = 1;
6656 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006657 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006658 child = node->children;
6659
6660 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00006661 facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006662 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006663 }
6664 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006665 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6666 "Facet %s has unexpected child content\n",
6667 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006668 }
6669 return (facet);
6670}
6671
6672/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006673 * xmlSchemaParseWildcardNs:
6674 * @ctxt: a schema parser context
6675 * @wildc: the wildcard, already created
6676 * @node: a subtree containing XML Schema informations
6677 *
6678 * Parses the attribute "processContents" and "namespace"
6679 * of a xsd:anyAttribute and xsd:any.
6680 * *WARNING* this interface is highly subject to change
6681 *
6682 * Returns 0 if everything goes fine, a positive error code
6683 * if something is not valid and -1 if an internal error occurs.
6684 */
6685static int
6686xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006687 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006688 xmlSchemaWildcardPtr wildc,
6689 xmlNodePtr node)
6690{
6691 const xmlChar *pc, *ns, *dictnsItem;
6692 int ret = 0;
6693 xmlChar *nsItem;
6694 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6695 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006696
Daniel Veillardc0826a72004-08-10 14:17:33 +00006697 pc = xmlSchemaGetProp(ctxt, node, "processContents");
6698 if ((pc == NULL)
6699 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6700 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6701 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6702 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6703 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6704 wildc->processContents = XML_SCHEMAS_ANY_LAX;
6705 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006706 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006707 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006708 NULL, node,
6709 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006710 NULL, NULL, NULL);
6711 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006712 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006713 }
6714 /*
6715 * Build the namespace constraints.
6716 */
6717 attr = xmlSchemaGetPropNode(node, "namespace");
6718 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006719 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00006720 wildc->any = 1;
6721 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6722 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006723 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006724 return (-1);
6725 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006726 wildc->negNsSet->value = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006727 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006728 const xmlChar *end, *cur;
6729
6730 cur = ns;
6731 do {
6732 while (IS_BLANK_CH(*cur))
6733 cur++;
6734 end = cur;
6735 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6736 end++;
6737 if (end == cur)
6738 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006739 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006740 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6741 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006742 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006743 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006744 NULL, (xmlNodePtr) attr,
6745 NULL,
6746 "((##any | ##other) | List of (xs:anyURI | "
6747 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006748 nsItem, NULL, NULL, NULL);
6749 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6750 } else {
6751 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006752 dictnsItem = ctxt->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006753 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6754 dictnsItem = NULL;
6755 } else {
6756 /*
6757 * Validate the item (anyURI).
6758 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006759 xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006760 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6761 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6762 }
6763 /*
6764 * Avoid dublicate namespaces.
6765 */
6766 tmp = wildc->nsSet;
6767 while (tmp != NULL) {
6768 if (dictnsItem == tmp->value)
6769 break;
6770 tmp = tmp->next;
6771 }
6772 if (tmp == NULL) {
6773 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6774 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006775 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006776 return (-1);
6777 }
6778 tmp->value = dictnsItem;
6779 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006780 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006781 wildc->nsSet = tmp;
6782 else
6783 lastNs->next = tmp;
6784 lastNs = tmp;
6785 }
6786
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006787 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006788 xmlFree(nsItem);
6789 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006790 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006791 }
6792 return (ret);
6793}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006794
6795static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006796xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6797 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006798 xmlNodePtr node,
6799 int minOccurs,
6800 int maxOccurs) {
6801
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006802 if ((maxOccurs == 0) && ( minOccurs == 0))
6803 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006804 if (maxOccurs != UNBOUNDED) {
6805 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006806 * TODO: Maybe we should better not create the particle,
6807 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006808 * content model.
6809 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006810 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006811 * 3.9.6 Schema Component Constraint: Particle Correct
6812 *
6813 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006814 if (maxOccurs < 1) {
6815 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006816 * 2.2 {max occurs} must be greater than or equal to 1.
6817 */
6818 xmlSchemaPCustomAttrErr(ctxt,
6819 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006820 NULL, NULL,
6821 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006822 "The value must be greater than or equal to 1");
6823 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6824 } else if (minOccurs > maxOccurs) {
6825 /*
6826 * 2.1 {min occurs} must not be greater than {max occurs}.
6827 */
6828 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006829 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006830 NULL, NULL,
6831 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006832 "The value must not be greater than the value of 'maxOccurs'");
6833 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6834 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006835 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006836 return (0);
6837}
6838
Daniel Veillardc0826a72004-08-10 14:17:33 +00006839/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006840 * xmlSchemaParseAny:
6841 * @ctxt: a schema validation context
6842 * @schema: the schema being built
6843 * @node: a subtree containing XML Schema informations
6844 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006845 * Parsea a XML schema <any> element. A particle and wildcard
6846 * will be created (except if minOccurs==maxOccurs==0, in this case
6847 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006848 * *WARNING* this interface is highly subject to change
6849 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006850 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006851 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006852static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006853xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6854 xmlNodePtr node)
6855{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006856 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006857 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006858 xmlSchemaWildcardPtr wild;
6859 int min, max;
6860 xmlAttrPtr attr;
6861 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006862
6863 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6864 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006865 /*
6866 * Check for illegal attributes.
6867 */
6868 attr = node->properties;
6869 while (attr != NULL) {
6870 if (attr->ns == NULL) {
6871 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6872 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6873 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6874 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6875 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006876 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006877 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006878 }
6879 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006880 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006881 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006882 }
6883 attr = attr->next;
6884 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006885 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006886 /*
6887 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006888 */
6889 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6890 "(xs:nonNegativeInteger | unbounded)");
6891 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6892 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006893 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6894 /*
6895 * Create & parse the wildcard.
6896 */
6897 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6898 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006899 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006900 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006901 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006902 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006903 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006904 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006905 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00006906 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006907 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006908 }
6909 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006910 xmlSchemaPContentErr(ctxt,
6911 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006912 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006913 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006914 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006915 /*
6916 * No component if minOccurs==maxOccurs==0.
6917 */
6918 if ((min == 0) && (max == 0)) {
6919 /* Don't free the wildcard, since it's already on the list. */
6920 return (NULL);
6921 }
6922 /*
6923 * Create the particle.
6924 */
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +00006925 particle = xmlSchemaAddParticle(ctxt, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006926 if (particle == NULL)
6927 return (NULL);
6928 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006929 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006930
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006931 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006932}
6933
6934/**
6935 * xmlSchemaParseNotation:
6936 * @ctxt: a schema validation context
6937 * @schema: the schema being built
6938 * @node: a subtree containing XML Schema informations
6939 *
6940 * parse a XML schema Notation declaration
6941 *
6942 * Returns the new structure or NULL in case of error
6943 */
6944static xmlSchemaNotationPtr
6945xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006946 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006947{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006948 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006949 xmlSchemaNotationPtr ret;
6950 xmlNodePtr child = NULL;
6951
6952 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6953 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006954 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006955 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006956 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6957 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006958 return (NULL);
6959 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006960 ret = xmlSchemaAddNotation(ctxt, schema, name,
6961 ctxt->targetNamespace, node);
6962 if (ret == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00006963 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006964 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006965
Daniel Veillard4255d502002-04-16 15:50:10 +00006966 child = node->children;
6967 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00006968 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006969 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006970 }
6971 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006972 xmlSchemaPContentErr(ctxt,
6973 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006974 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006975 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006976 }
6977
6978 return (ret);
6979}
6980
6981/**
6982 * xmlSchemaParseAnyAttribute:
6983 * @ctxt: a schema validation context
6984 * @schema: the schema being built
6985 * @node: a subtree containing XML Schema informations
6986 *
6987 * parse a XML schema AnyAttrribute declaration
6988 * *WARNING* this interface is highly subject to change
6989 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006990 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006991 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006992static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006993xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6994 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006995{
Daniel Veillard3646d642004-06-02 19:19:14 +00006996 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006997 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006998 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006999
7000 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7001 return (NULL);
7002
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007003 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7004 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007005 if (ret == NULL) {
7006 return (NULL);
7007 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007008 /*
7009 * Check for illegal attributes.
7010 */
7011 attr = node->properties;
7012 while (attr != NULL) {
7013 if (attr->ns == NULL) {
7014 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7015 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7016 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007017 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007018 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007019 }
7020 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007021 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007022 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007023 }
7024 attr = attr->next;
7025 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007026 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007027 /*
7028 * Parse the namespace list.
7029 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007030 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007031 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007032 /*
7033 * And now for the children...
7034 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007035 child = node->children;
7036 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007037 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007038 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007039 }
7040 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007041 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007042 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007043 NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007044 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007045 }
7046
7047 return (ret);
7048}
7049
7050
7051/**
7052 * xmlSchemaParseAttribute:
7053 * @ctxt: a schema validation context
7054 * @schema: the schema being built
7055 * @node: a subtree containing XML Schema informations
7056 *
7057 * parse a XML schema Attrribute declaration
7058 * *WARNING* this interface is highly subject to change
7059 *
William M. Bracke7091952004-05-11 15:09:58 +00007060 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007061 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007062static xmlSchemaBasicItemPtr
7063xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7064 xmlSchemaPtr schema,
7065 xmlNodePtr node,
7066 xmlSchemaItemListPtr uses,
7067 int parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00007068{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007069 const xmlChar *attrValue, *name = NULL, *ns = NULL;
7070 xmlSchemaAttributeUsePtr use = NULL;
7071 xmlNodePtr child = NULL;
7072 xmlAttrPtr attr;
7073 const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7074 int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7075 int nberrors, hasForm = 0, defValueType = 0;
7076
7077#define WXS_ATTR_DEF_VAL_DEFAULT 1
7078#define WXS_ATTR_DEF_VAL_FIXED 2
7079
7080 /*
7081 * 3.2.3 Constraints on XML Representations of Attribute Declarations
7082 */
7083
7084 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7085 return (NULL);
7086 attr = xmlSchemaGetPropNode(node, "ref");
7087 if (attr != NULL) {
7088 if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7089 NULL, attr, &tmpNs, &tmpName) != 0) {
7090 return (NULL);
7091 }
7092 if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7093 return(NULL);
7094 isRef = 1;
7095 }
7096 nberrors = pctxt->nberrors;
7097 /*
7098 * Check for illegal attributes.
7099 */
7100 attr = node->properties;
7101 while (attr != NULL) {
7102 if (attr->ns == NULL) {
7103 if (isRef) {
7104 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7105 xmlSchemaPValAttrNodeID(pctxt, attr);
7106 goto attr_next;
7107 } else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7108 goto attr_next;
7109 }
7110 } else {
7111 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7112 goto attr_next;
7113 } else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7114 xmlSchemaPValAttrNodeID(pctxt, attr);
7115 goto attr_next;
7116 } else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7117 xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7118 attr, &tmpNs, &tmpName);
7119 goto attr_next;
7120 } else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7121 /*
7122 * Evaluate the target namespace
7123 */
7124 hasForm = 1;
7125 attrValue = xmlSchemaGetNodeContent(pctxt,
7126 (xmlNodePtr) attr);
7127 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7128 ns = pctxt->targetNamespace;
7129 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7130 {
7131 xmlSchemaPSimpleTypeErr(pctxt,
7132 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7133 NULL, (xmlNodePtr) attr,
7134 NULL, "(qualified | unqualified)",
7135 attrValue, NULL, NULL, NULL);
7136 }
7137 goto attr_next;
7138 }
7139 }
7140 if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7141
7142 attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7143 /* TODO: Maybe we need to normalize the value beforehand. */
7144 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7145 occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7146 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7147 occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7148 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7149 occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7150 else {
7151 xmlSchemaPSimpleTypeErr(pctxt,
7152 XML_SCHEMAP_INVALID_ATTR_USE,
7153 NULL, (xmlNodePtr) attr,
7154 NULL, "(optional | prohibited | required)",
7155 attrValue, NULL, NULL, NULL);
7156 }
7157 goto attr_next;
7158 } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7159 /*
7160 * 3.2.3 : 1
7161 * default and fixed must not both be present.
7162 */
7163 if (defValue) {
7164 xmlSchemaPMutualExclAttrErr(pctxt,
7165 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7166 NULL, attr, "default", "fixed");
7167 } else {
7168 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7169 defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7170 }
7171 goto attr_next;
7172 } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7173 /*
7174 * 3.2.3 : 1
7175 * default and fixed must not both be present.
7176 */
7177 if (defValue) {
7178 xmlSchemaPMutualExclAttrErr(pctxt,
7179 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7180 NULL, attr, "default", "fixed");
7181 } else {
7182 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7183 defValueType = WXS_ATTR_DEF_VAL_FIXED;
7184 }
7185 goto attr_next;
7186 }
7187 } else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7188 goto attr_next;
7189
7190 xmlSchemaPIllegalAttrErr(pctxt,
7191 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7192
7193attr_next:
7194 attr = attr->next;
7195 }
7196 /*
7197 * 3.2.3 : 2
7198 * If default and use are both present, use must have
7199 * the actual value optional.
7200 */
7201 if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7202 (occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7203 xmlSchemaPSimpleTypeErr(pctxt,
7204 XML_SCHEMAP_SRC_ATTRIBUTE_2,
7205 NULL, node, NULL,
7206 "(optional | prohibited | required)", NULL,
7207 "The value of the attribute 'use' must be 'optional' "
7208 "if the attribute 'default' is present",
7209 NULL, NULL);
7210 }
7211 /*
7212 * We want correct attributes.
7213 */
7214 if (nberrors != pctxt->nberrors)
7215 return(NULL);
7216 if (! isRef) {
7217 xmlSchemaAttributePtr attrDecl;
7218
7219 /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7220 if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7221 ns = pctxt->targetNamespace;
7222 /*
7223 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7224 * TODO: Move this to the component layer.
7225 */
7226 if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7227 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7228 XML_SCHEMAP_NO_XSI,
7229 node, NULL,
7230 "The target namespace must not match '%s'",
7231 xmlSchemaInstanceNs, NULL);
7232 }
7233 attr = xmlSchemaGetPropNode(node, "name");
7234 if (attr == NULL) {
7235 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7236 NULL, node, "name", NULL);
7237 return (NULL);
7238 }
7239 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7240 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7241 return (NULL);
7242 }
7243 /*
7244 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7245 * TODO: Move this to the component layer.
7246 */
7247 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7248 xmlSchemaPSimpleTypeErr(pctxt,
7249 XML_SCHEMAP_NO_XMLNS,
7250 NULL, (xmlNodePtr) attr,
7251 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7252 "The value of the attribute must not match 'xmlns'",
7253 NULL, NULL);
7254 return (NULL);
7255 }
7256 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7257 goto check_children;
7258 /*
7259 * Create the attribute use component.
7260 */
7261 use = xmlSchemaAddAttributeUse(pctxt, node);
7262 if (use == NULL)
7263 return(NULL);
7264 use->occurs = occurs;
7265 /*
7266 * Create the attribute declaration.
7267 */
7268 attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7269 if (attrDecl == NULL)
7270 return (NULL);
7271 if (tmpName != NULL) {
7272 attrDecl->typeName = tmpName;
7273 attrDecl->typeNs = tmpNs;
7274 }
7275 use->attrDecl = attrDecl;
7276 /*
7277 * Value constraint.
7278 */
7279 if (defValue != NULL) {
7280 attrDecl->defValue = defValue;
7281 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7282 attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7283 }
7284 } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7285 xmlSchemaQNameRefPtr ref;
7286
7287 /*
7288 * Create the attribute use component.
7289 */
7290 use = xmlSchemaAddAttributeUse(pctxt, node);
7291 if (use == NULL)
7292 return(NULL);
7293 /*
7294 * We need to resolve the reference at later stage.
7295 */
7296 WXS_ADD_PENDING(pctxt, use);
7297 use->occurs = occurs;
7298 /*
7299 * Create a QName reference to the attribute declaration.
7300 */
7301 ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7302 tmpName, tmpNs);
7303 if (ref == NULL)
7304 return(NULL);
7305 /*
7306 * Assign the reference. This will be substituted for the
7307 * referenced attribute declaration when the QName is resolved.
7308 */
7309 use->attrDecl = WXS_ATTR_CAST ref;
7310 /*
7311 * Value constraint.
7312 */
7313 if (defValue != NULL)
7314 use->defValue = defValue;
7315 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7316 use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7317 }
7318
7319check_children:
7320 /*
7321 * And now for the children...
7322 */
7323 child = node->children;
7324 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7325 xmlSchemaAttributeUseProhibPtr prohib;
7326
7327 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007328 xmlSchemaParseAnnotation(pctxt, child, 0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007329 child = child->next;
7330 }
7331 if (child != NULL) {
7332 xmlSchemaPContentErr(pctxt,
7333 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7334 NULL, node, child, NULL,
7335 "(annotation?)");
7336 }
7337 /*
7338 * Check for pointlessness of attribute prohibitions.
7339 */
7340 if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7341 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7342 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7343 node, NULL,
7344 "Skipping attribute use prohibition, since it is "
7345 "pointless inside an <attributeGroup>",
7346 NULL, NULL, NULL);
7347 return(NULL);
7348 } else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7349 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7350 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7351 node, NULL,
7352 "Skipping attribute use prohibition, since it is "
7353 "pointless when extending a type",
7354 NULL, NULL, NULL);
7355 return(NULL);
7356 }
7357 if (! isRef) {
7358 tmpName = name;
7359 tmpNs = ns;
7360 }
7361 /*
7362 * Check for duplicate attribute prohibitions.
7363 */
7364 if (uses) {
7365 int i;
7366
7367 for (i = 0; i < uses->nbItems; i++) {
7368 use = uses->items[i];
7369 if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7370 (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7371 (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7372 {
7373 xmlChar *str = NULL;
7374
7375 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7376 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7377 node, NULL,
7378 "Skipping duplicate attribute use prohibition '%s'",
7379 xmlSchemaFormatQName(&str, tmpNs, tmpName),
7380 NULL, NULL);
7381 FREE_AND_NULL(str)
7382 return(NULL);
7383 }
7384 }
7385 }
7386 /*
7387 * Create the attribute prohibition helper component.
7388 */
7389 prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7390 if (prohib == NULL)
7391 return(NULL);
7392 prohib->node = node;
7393 prohib->name = tmpName;
7394 prohib->targetNamespace = tmpNs;
7395 if (isRef) {
7396 /*
7397 * We need at least to resolve to the attribute declaration.
7398 */
7399 WXS_ADD_PENDING(pctxt, prohib);
7400 }
7401 return(WXS_BASIC_CAST prohib);
7402 } else {
7403 if (IS_SCHEMA(child, "annotation")) {
7404 /*
7405 * TODO: Should this go into the attr decl?
7406 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007407 use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007408 child = child->next;
7409 }
7410 if (isRef) {
7411 if (child != NULL) {
7412 if (IS_SCHEMA(child, "simpleType"))
7413 /*
7414 * 3.2.3 : 3.2
7415 * If ref is present, then all of <simpleType>,
7416 * form and type must be absent.
7417 */
7418 xmlSchemaPContentErr(pctxt,
7419 XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7420 NULL, node, child, NULL,
7421 "(annotation?)");
7422 else
7423 xmlSchemaPContentErr(pctxt,
7424 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7425 NULL, node, child, NULL,
7426 "(annotation?)");
7427 }
7428 } else {
7429 if (IS_SCHEMA(child, "simpleType")) {
7430 if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7431 /*
7432 * 3.2.3 : 4
7433 * type and <simpleType> must not both be present.
7434 */
7435 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7436 NULL, node, child,
7437 "The attribute 'type' and the <simpleType> child "
7438 "are mutually exclusive", NULL);
7439 } else
7440 WXS_ATTRUSE_TYPEDEF(use) =
7441 xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7442 child = child->next;
7443 }
7444 if (child != NULL)
7445 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7446 NULL, node, child, NULL,
7447 "(annotation?, simpleType?)");
7448 }
7449 }
7450 return (WXS_BASIC_CAST use);
7451}
7452
7453
7454static xmlSchemaAttributePtr
7455xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7456 xmlSchemaPtr schema,
7457 xmlNodePtr node)
7458{
7459 const xmlChar *attrValue;
Daniel Veillard4255d502002-04-16 15:50:10 +00007460 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007461 xmlNodePtr child = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007462 xmlAttrPtr attr;
William M. Bracke7091952004-05-11 15:09:58 +00007463
7464 /*
7465 * Note that the w3c spec assumes the schema to be validated with schema
7466 * for schemas beforehand.
7467 *
7468 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00007469 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007470 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7471 return (NULL);
7472 /*
7473 * 3.2.3 : 3.1
7474 * One of ref or name must be present, but not both
7475 */
7476 attr = xmlSchemaGetPropNode(node, "name");
7477 if (attr == NULL) {
7478 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7479 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007480 return (NULL);
7481 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007482 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7483 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7484 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007485 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007486 /*
7487 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7488 * TODO: Move this to the component layer.
7489 */
7490 if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7491 xmlSchemaPSimpleTypeErr(pctxt,
7492 XML_SCHEMAP_NO_XMLNS,
7493 NULL, (xmlNodePtr) attr,
7494 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7495 "The value of the attribute must not match 'xmlns'",
7496 NULL, NULL);
7497 return (NULL);
7498 }
7499 /*
7500 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7501 * TODO: Move this to the component layer.
7502 * Or better leave it here and add it to the component layer
7503 * if we have a schema construction API.
7504 */
7505 if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7506 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7507 XML_SCHEMAP_NO_XSI, node, NULL,
7508 "The target namespace must not match '%s'",
7509 xmlSchemaInstanceNs, NULL);
7510 }
7511
7512 ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7513 pctxt->targetNamespace, node, 1);
7514 if (ret == NULL)
7515 return (NULL);
7516 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7517
7518 /*
7519 * Check for illegal attributes.
7520 */
7521 attr = node->properties;
7522 while (attr != NULL) {
7523 if (attr->ns == NULL) {
7524 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7525 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7526 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7527 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7528 (!xmlStrEqual(attr->name, BAD_CAST "type")))
7529 {
7530 xmlSchemaPIllegalAttrErr(pctxt,
7531 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7532 }
7533 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7534 xmlSchemaPIllegalAttrErr(pctxt,
7535 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7536 }
7537 attr = attr->next;
7538 }
7539 xmlSchemaPValAttrQName(pctxt, schema, NULL,
7540 node, "type", &ret->typeNs, &ret->typeName);
7541
7542 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00007543 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007544 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00007545 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007546 ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007547 if (ret->defValue != NULL)
7548 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007549 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007550 * Attribute "default".
7551 */
7552 attr = xmlSchemaGetPropNode(node, "default");
7553 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007554 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007555 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007556 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007557 */
7558 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007559 xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7560 WXS_BASIC_CAST ret, attr, "default", "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007561 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007562 ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007563 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007564 /*
7565 * And now for the children...
7566 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007567 child = node->children;
7568 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007569 ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007570 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007571 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007572 if (IS_SCHEMA(child, "simpleType")) {
7573 if (ret->typeName != NULL) {
7574 /*
7575 * 3.2.3 : 4
7576 * type and <simpleType> must not both be present.
7577 */
7578 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7579 NULL, node, child,
7580 "The attribute 'type' and the <simpleType> child "
7581 "are mutually exclusive", NULL);
7582 } else
7583 ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7584 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007585 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007586 if (child != NULL)
7587 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7588 NULL, node, child, NULL,
7589 "(annotation?, simpleType?)");
7590
Daniel Veillard4255d502002-04-16 15:50:10 +00007591 return (ret);
7592}
7593
7594/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007595 * xmlSchemaParseAttributeGroupRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00007596 * @ctxt: a schema validation context
7597 * @schema: the schema being built
7598 * @node: a subtree containing XML Schema informations
7599 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007600 * Parse an attribute group definition reference.
7601 * Note that a reference to an attribute group does not
7602 * correspond to any component at all.
Daniel Veillard4255d502002-04-16 15:50:10 +00007603 * *WARNING* this interface is highly subject to change
7604 *
7605 * Returns the attribute group or NULL in case of error.
7606 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007607static xmlSchemaQNameRefPtr
7608xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7609 xmlSchemaPtr schema,
7610 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007611{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007612 xmlSchemaQNameRefPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00007613 xmlNodePtr child = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007614 xmlAttrPtr attr;
7615 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007616
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007617 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00007618 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007619
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007620 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007621 if (attr == NULL) {
7622 xmlSchemaPMissingAttrErr(pctxt,
7623 XML_SCHEMAP_S4S_ATTR_MISSING,
7624 NULL, node, "ref", NULL);
7625 return (NULL);
7626 }
7627 xmlSchemaPValAttrNodeQName(pctxt, schema,
7628 NULL, attr, &refNs, &ref);
7629 if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7630 return(NULL);
7631
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007632 /*
7633 * Check for illegal attributes.
7634 */
7635 attr = node->properties;
7636 while (attr != NULL) {
7637 if (attr->ns == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007638 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007639 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007640 {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007641 xmlSchemaPIllegalAttrErr(pctxt,
7642 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007643 }
7644 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007645 xmlSchemaPIllegalAttrErr(pctxt,
7646 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007647 }
7648 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007649 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00007650 /* Attribute ID */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007651 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7652
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007653 /*
7654 * And now for the children...
7655 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007656 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00007657 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007658 /*
7659 * TODO: We do not have a place to store the annotation, do we?
7660 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007661 xmlSchemaParseAnnotation(pctxt, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007662 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007663 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007664 if (child != NULL) {
7665 xmlSchemaPContentErr(pctxt,
7666 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7667 NULL, node, child, NULL,
7668 "(annotation?)");
7669 }
7670
7671 /*
7672 * Handle attribute group redefinitions.
7673 */
7674 if (pctxt->isRedefine && pctxt->redef &&
7675 (pctxt->redef->item->type ==
7676 XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7677 (ref == pctxt->redef->refName) &&
7678 (refNs == pctxt->redef->refTargetNs))
7679 {
7680 /*
7681 * SPEC src-redefine:
7682 * (7.1) "If it has an <attributeGroup> among its contents
7683 * the ·actual value· of whose ref [attribute] is the same
7684 * as the ·actual value· of its own name attribute plus
7685 * target namespace, then it must have exactly one such group."
7686 */
7687 if (pctxt->redefCounter != 0) {
7688 xmlChar *str = NULL;
7689
7690 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7691 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7692 "The redefining attribute group definition "
7693 "'%s' must not contain more than one "
7694 "reference to the redefined definition",
7695 xmlSchemaFormatQName(&str, refNs, ref), NULL);
7696 FREE_AND_NULL(str);
7697 return(NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007698 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007699 pctxt->redefCounter++;
7700 /*
7701 * URGENT TODO: How to ensure that the reference will not be
7702 * handled by the normal component resolution mechanism?
7703 */
7704 ret = xmlSchemaNewQNameRef(pctxt,
7705 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7706 if (ret == NULL)
7707 return(NULL);
7708 ret->node = node;
7709 pctxt->redef->reference = WXS_BASIC_CAST ret;
7710 } else {
7711 /*
7712 * Create a QName-reference helper component. We will substitute this
7713 * component for the attribute uses of the referenced attribute group
7714 * definition.
7715 */
7716 ret = xmlSchemaNewQNameRef(pctxt,
7717 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7718 if (ret == NULL)
7719 return(NULL);
7720 ret->node = node;
7721 /* Add to pending items, to be able to resolve the reference. */
7722 WXS_ADD_PENDING(pctxt, ret);
7723 }
7724 return (ret);
7725}
7726
7727/**
7728 * xmlSchemaParseAttributeGroupDefinition:
7729 * @pctxt: a schema validation context
7730 * @schema: the schema being built
7731 * @node: a subtree containing XML Schema informations
7732 *
7733 * parse a XML schema Attribute Group declaration
7734 * *WARNING* this interface is highly subject to change
7735 *
7736 * Returns the attribute group definition or NULL in case of error.
7737 */
7738static xmlSchemaAttributeGroupPtr
7739xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7740 xmlSchemaPtr schema,
7741 xmlNodePtr node)
7742{
7743 const xmlChar *name;
7744 xmlSchemaAttributeGroupPtr ret;
7745 xmlNodePtr child = NULL;
7746 xmlAttrPtr attr;
7747 int hasRefs = 0;
7748
7749 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7750 return (NULL);
7751
7752 attr = xmlSchemaGetPropNode(node, "name");
7753 if (attr == NULL) {
7754 xmlSchemaPMissingAttrErr(pctxt,
7755 XML_SCHEMAP_S4S_ATTR_MISSING,
7756 NULL, node, "name", NULL);
7757 return (NULL);
7758 }
7759 /*
7760 * The name is crucial, exit if invalid.
7761 */
7762 if (xmlSchemaPValAttrNode(pctxt,
7763 NULL, attr,
7764 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7765 return (NULL);
7766 }
7767 ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7768 name, pctxt->targetNamespace, node);
7769 if (ret == NULL)
7770 return (NULL);
7771 /*
7772 * Check for illegal attributes.
7773 */
7774 attr = node->properties;
7775 while (attr != NULL) {
7776 if (attr->ns == NULL) {
7777 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7778 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7779 {
7780 xmlSchemaPIllegalAttrErr(pctxt,
7781 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7782 }
7783 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7784 xmlSchemaPIllegalAttrErr(pctxt,
7785 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7786 }
7787 attr = attr->next;
7788 }
7789 /* Attribute ID */
7790 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7791 /*
7792 * And now for the children...
7793 */
7794 child = node->children;
7795 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007796 ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007797 child = child->next;
7798 }
7799 /*
7800 * Parse contained attribute decls/refs.
7801 */
7802 if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7803 (xmlSchemaItemListPtr *) &(ret->attrUses),
7804 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7805 return(NULL);
7806 if (hasRefs)
7807 ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7808 /*
7809 * Parse the attribute wildcard.
7810 */
7811 if (IS_SCHEMA(child, "anyAttribute")) {
7812 ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7813 schema, child);
7814 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007815 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007816 if (child != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007817 xmlSchemaPContentErr(pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007818 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007819 NULL, node, child, NULL,
7820 "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007821 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007822 return (ret);
7823}
7824
7825/**
William M. Brack2f2a6632004-08-20 23:09:47 +00007826 * xmlSchemaPValAttrFormDefault:
7827 * @value: the value
7828 * @flags: the flags to be modified
7829 * @flagQualified: the specific flag for "qualified"
7830 *
7831 * Returns 0 if the value is valid, 1 otherwise.
7832 */
7833static int
7834xmlSchemaPValAttrFormDefault(const xmlChar *value,
7835 int *flags,
7836 int flagQualified)
7837{
7838 if (xmlStrEqual(value, BAD_CAST "qualified")) {
7839 if ((*flags & flagQualified) == 0)
7840 *flags |= flagQualified;
7841 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007842 return (1);
7843
William M. Brack2f2a6632004-08-20 23:09:47 +00007844 return (0);
7845}
7846
7847/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00007848 * xmlSchemaPValAttrBlockFinal:
7849 * @value: the value
7850 * @flags: the flags to be modified
7851 * @flagAll: the specific flag for "#all"
7852 * @flagExtension: the specific flag for "extension"
7853 * @flagRestriction: the specific flag for "restriction"
7854 * @flagSubstitution: the specific flag for "substitution"
7855 * @flagList: the specific flag for "list"
7856 * @flagUnion: the specific flag for "union"
7857 *
7858 * Validates the value of the attribute "final" and "block". The value
7859 * is converted into the specified flag values and returned in @flags.
7860 *
7861 * Returns 0 if the value is valid, 1 otherwise.
7862 */
7863
7864static int
7865xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007866 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007867 int flagAll,
7868 int flagExtension,
7869 int flagRestriction,
7870 int flagSubstitution,
7871 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007872 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007873{
7874 int ret = 0;
7875
7876 /*
7877 * TODO: This does not check for dublicate entries.
7878 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007879 if ((flags == NULL) || (value == NULL))
7880 return (-1);
7881 if (value[0] == 0)
7882 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007883 if (xmlStrEqual(value, BAD_CAST "#all")) {
7884 if (flagAll != -1)
7885 *flags |= flagAll;
7886 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007887 if (flagExtension != -1)
7888 *flags |= flagExtension;
7889 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007890 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007891 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007892 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007893 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007894 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007895 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007896 *flags |= flagUnion;
7897 }
7898 } else {
7899 const xmlChar *end, *cur = value;
7900 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007901
Daniel Veillardc0826a72004-08-10 14:17:33 +00007902 do {
7903 while (IS_BLANK_CH(*cur))
7904 cur++;
7905 end = cur;
7906 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7907 end++;
7908 if (end == cur)
7909 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007910 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007911 if (xmlStrEqual(item, BAD_CAST "extension")) {
7912 if (flagExtension != -1) {
7913 if ((*flags & flagExtension) == 0)
7914 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007915 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007916 ret = 1;
7917 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7918 if (flagRestriction != -1) {
7919 if ((*flags & flagRestriction) == 0)
7920 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007921 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007922 ret = 1;
7923 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7924 if (flagSubstitution != -1) {
7925 if ((*flags & flagSubstitution) == 0)
7926 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007927 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007928 ret = 1;
7929 } else if (xmlStrEqual(item, BAD_CAST "list")) {
7930 if (flagList != -1) {
7931 if ((*flags & flagList) == 0)
7932 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007933 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007934 ret = 1;
7935 } else if (xmlStrEqual(item, BAD_CAST "union")) {
7936 if (flagUnion != -1) {
7937 if ((*flags & flagUnion) == 0)
7938 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007939 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007940 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007941 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007942 ret = 1;
7943 if (item != NULL)
7944 xmlFree(item);
7945 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007946 } while ((ret == 0) && (*cur != 0));
7947 }
7948
Daniel Veillardc0826a72004-08-10 14:17:33 +00007949 return (ret);
7950}
7951
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007952static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007953xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007954 xmlSchemaIDCPtr idc,
7955 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007956 xmlAttrPtr attr,
7957 int isField)
7958{
7959 xmlNodePtr node;
7960
7961 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007962 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007963 * Schema Component Constraint: Selector Value OK
7964 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007965 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007966 * in [XPath].
7967 */
7968 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007969 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007970 XML_SCHEMAP_INTERNAL,
7971 "Internal error: xmlSchemaCheckCSelectorXPath, "
7972 "the selector is not specified.\n", NULL, NULL);
7973 return (-1);
7974 }
7975 if (attr == NULL)
7976 node = idc->node;
7977 else
7978 node = (xmlNodePtr) attr;
7979 if (selector->xpath == NULL) {
7980 xmlSchemaPCustomErr(ctxt,
7981 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007982 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007983 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007984 "The XPath expression of the selector is not valid", NULL);
7985 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
7986 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007987 const xmlChar **nsArray = NULL;
7988 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007989 /*
7990 * Compile the XPath expression.
7991 */
7992 /*
7993 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007994 * TODO: Call xmlPatterncompile with different options for selector/
7995 * field.
7996 */
Daniel Veillard14b56432006-03-09 18:41:40 +00007997 if (attr == NULL)
Daniel Veillardaac7c682006-03-10 13:40:16 +00007998 nsList = NULL;
Daniel Veillard14b56432006-03-09 18:41:40 +00007999 else
8000 nsList = xmlGetNsList(attr->doc, attr->parent);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008001 /*
8002 * Build an array of prefixes and namespaces.
8003 */
8004 if (nsList != NULL) {
8005 int i, count = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008006
8007 for (i = 0; nsList[i] != NULL; i++)
8008 count++;
8009
8010 nsArray = (const xmlChar **) xmlMalloc(
8011 (count * 2 + 1) * sizeof(const xmlChar *));
8012 if (nsArray == NULL) {
8013 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8014 NULL);
Kasimier T. Buchcik940ab0c2005-10-19 17:00:53 +00008015 xmlFree(nsList);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008016 return (-1);
8017 }
8018 for (i = 0; i < count; i++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008019 nsArray[2 * i] = nsList[i]->href;
8020 nsArray[2 * i + 1] = nsList[i]->prefix;
8021 }
8022 nsArray[count * 2] = NULL;
8023 xmlFree(nsList);
8024 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008025 /*
8026 * TODO: Differentiate between "selector" and "field".
8027 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008028 if (isField)
8029 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008030 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008031 else
8032 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008033 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008034 if (nsArray != NULL)
8035 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008036
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00008037 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008038 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00008039 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008040 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008041 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008042 "The XPath expression '%s' could not be "
8043 "compiled", selector->xpath);
8044 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008045 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008046 }
8047 return (0);
8048}
8049
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008050#define ADD_ANNOTATION(annot) \
8051 xmlSchemaAnnotPtr cur = item->annot; \
8052 if (item->annot == NULL) { \
8053 item->annot = annot; \
8054 return (annot); \
8055 } \
8056 cur = item->annot; \
8057 if (cur->next != NULL) { \
8058 cur = cur->next; \
8059 } \
8060 cur->next = annot;
8061
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008062/**
8063 * xmlSchemaAssignAnnotation:
8064 * @item: the schema component
8065 * @annot: the annotation
8066 *
8067 * Adds the annotation to the given schema component.
8068 *
8069 * Returns the given annotaion.
8070 */
8071static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008072xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8073 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008074{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008075 if ((annItem == NULL) || (annot == NULL))
8076 return (NULL);
8077 switch (annItem->type) {
8078 case XML_SCHEMA_TYPE_ELEMENT: {
8079 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8080 ADD_ANNOTATION(annot)
8081 }
8082 break;
8083 case XML_SCHEMA_TYPE_ATTRIBUTE: {
8084 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8085 ADD_ANNOTATION(annot)
8086 }
8087 break;
8088 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8089 case XML_SCHEMA_TYPE_ANY: {
8090 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8091 ADD_ANNOTATION(annot)
8092 }
8093 break;
8094 case XML_SCHEMA_TYPE_PARTICLE:
8095 case XML_SCHEMA_TYPE_IDC_KEY:
8096 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008097 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008098 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8099 ADD_ANNOTATION(annot)
8100 }
8101 break;
8102 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8103 xmlSchemaAttributeGroupPtr item =
8104 (xmlSchemaAttributeGroupPtr) annItem;
8105 ADD_ANNOTATION(annot)
8106 }
8107 break;
8108 case XML_SCHEMA_TYPE_NOTATION: {
8109 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8110 ADD_ANNOTATION(annot)
8111 }
8112 break;
8113 case XML_SCHEMA_FACET_MININCLUSIVE:
8114 case XML_SCHEMA_FACET_MINEXCLUSIVE:
8115 case XML_SCHEMA_FACET_MAXINCLUSIVE:
8116 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8117 case XML_SCHEMA_FACET_TOTALDIGITS:
8118 case XML_SCHEMA_FACET_FRACTIONDIGITS:
8119 case XML_SCHEMA_FACET_PATTERN:
8120 case XML_SCHEMA_FACET_ENUMERATION:
8121 case XML_SCHEMA_FACET_WHITESPACE:
8122 case XML_SCHEMA_FACET_LENGTH:
8123 case XML_SCHEMA_FACET_MAXLENGTH:
8124 case XML_SCHEMA_FACET_MINLENGTH: {
8125 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8126 ADD_ANNOTATION(annot)
8127 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008128 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008129 case XML_SCHEMA_TYPE_SIMPLE:
8130 case XML_SCHEMA_TYPE_COMPLEX: {
8131 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8132 ADD_ANNOTATION(annot)
8133 }
8134 break;
8135 case XML_SCHEMA_TYPE_GROUP: {
8136 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8137 ADD_ANNOTATION(annot)
8138 }
8139 break;
8140 case XML_SCHEMA_TYPE_SEQUENCE:
8141 case XML_SCHEMA_TYPE_CHOICE:
8142 case XML_SCHEMA_TYPE_ALL: {
8143 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8144 ADD_ANNOTATION(annot)
8145 }
8146 break;
8147 default:
8148 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008149 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008150 NULL, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008151 "Internal error: xmlSchemaAddAnnotation, "
8152 "The item is not a annotated schema component", NULL);
8153 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008154 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008155 return (annot);
8156}
8157
8158/**
8159 * xmlSchemaParseIDCSelectorAndField:
8160 * @ctxt: a schema validation context
8161 * @schema: the schema being built
8162 * @node: a subtree containing XML Schema informations
8163 *
8164 * Parses a XML Schema identity-contraint definition's
8165 * <selector> and <field> elements.
8166 *
8167 * Returns the parsed identity-constraint definition.
8168 */
8169static xmlSchemaIDCSelectPtr
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008170xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008171 xmlSchemaIDCPtr idc,
8172 xmlNodePtr node,
8173 int isField)
8174{
8175 xmlSchemaIDCSelectPtr item;
8176 xmlNodePtr child = NULL;
8177 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008178
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008179 /*
8180 * Check for illegal attributes.
8181 */
8182 attr = node->properties;
8183 while (attr != NULL) {
8184 if (attr->ns == NULL) {
8185 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8186 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008187 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008188 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008189 }
8190 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008191 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008192 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008193 }
8194 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008195 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008196 /*
8197 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008198 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008199 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8200 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008201 xmlSchemaPErrMemory(ctxt,
8202 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008203 NULL);
8204 return (NULL);
8205 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008206 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008207 /*
8208 * Attribute "xpath" (mandatory).
8209 */
8210 attr = xmlSchemaGetPropNode(node, "xpath");
8211 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008212 xmlSchemaPMissingAttrErr(ctxt,
8213 XML_SCHEMAP_S4S_ATTR_MISSING,
8214 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008215 "name", NULL);
8216 } else {
8217 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8218 /*
8219 * URGENT TODO: "field"s have an other syntax than "selector"s.
8220 */
8221
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008222 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8223 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008224 xmlSchemaPErr(ctxt,
8225 (xmlNodePtr) attr,
8226 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008227 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008228 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008229 NULL, NULL);
8230 }
8231
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008232 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008233 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008234 /*
8235 * And now for the children...
8236 */
8237 child = node->children;
8238 if (IS_SCHEMA(child, "annotation")) {
8239 /*
8240 * Add the annotation to the parent IDC.
8241 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008242 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008243 xmlSchemaParseAnnotation(ctxt, child, 1));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008244 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008245 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008246 if (child != NULL) {
8247 xmlSchemaPContentErr(ctxt,
8248 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008249 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008250 NULL, "(annotation?)");
8251 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008252
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008253 return (item);
8254}
8255
8256/**
8257 * xmlSchemaParseIDC:
8258 * @ctxt: a schema validation context
8259 * @schema: the schema being built
8260 * @node: a subtree containing XML Schema informations
8261 *
8262 * Parses a XML Schema identity-contraint definition.
8263 *
8264 * Returns the parsed identity-constraint definition.
8265 */
8266static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008267xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008268 xmlSchemaPtr schema,
8269 xmlNodePtr node,
8270 xmlSchemaTypeType idcCategory,
8271 const xmlChar *targetNamespace)
8272{
8273 xmlSchemaIDCPtr item = NULL;
8274 xmlNodePtr child = NULL;
8275 xmlAttrPtr attr;
8276 const xmlChar *name = NULL;
8277 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008278
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008279 /*
8280 * Check for illegal attributes.
8281 */
8282 attr = node->properties;
8283 while (attr != NULL) {
8284 if (attr->ns == NULL) {
8285 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8286 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8287 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8288 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008289 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008290 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008291 }
8292 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008293 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008294 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008295 }
8296 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008297 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008298 /*
8299 * Attribute "name" (mandatory).
8300 */
8301 attr = xmlSchemaGetPropNode(node, "name");
8302 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008303 xmlSchemaPMissingAttrErr(ctxt,
8304 XML_SCHEMAP_S4S_ATTR_MISSING,
8305 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008306 "name", NULL);
8307 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008308 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008309 NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008310 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8311 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008312 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008313 /* Create the component. */
8314 item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8315 idcCategory, node);
8316 if (item == NULL)
8317 return(NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008318
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008319 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008320 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8321 /*
8322 * Attribute "refer" (mandatory).
8323 */
8324 attr = xmlSchemaGetPropNode(node, "refer");
8325 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008326 xmlSchemaPMissingAttrErr(ctxt,
8327 XML_SCHEMAP_S4S_ATTR_MISSING,
8328 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008329 "refer", NULL);
8330 } else {
8331 /*
8332 * Create a reference item.
8333 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008334 item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008335 NULL, NULL);
8336 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008337 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008338 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008339 NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008340 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008341 &(item->ref->name));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008342 xmlSchemaCheckReference(ctxt, schema, node, attr,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008343 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008344 }
8345 }
8346 /*
8347 * And now for the children...
8348 */
8349 child = node->children;
8350 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008351 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008352 child = child->next;
8353 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00008354 if (child == NULL) {
8355 xmlSchemaPContentErr(ctxt,
8356 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008357 NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00008358 "A child element is missing",
8359 "(annotation?, (selector, field+))");
8360 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008361 /*
8362 * Child element <selector>.
8363 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008364 if (IS_SCHEMA(child, "selector")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008365 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008366 item, child, 0);
8367 child = child->next;
8368 /*
8369 * Child elements <field>.
8370 */
8371 if (IS_SCHEMA(child, "field")) {
8372 do {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008373 field = xmlSchemaParseIDCSelectorAndField(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008374 item, child, 1);
8375 if (field != NULL) {
8376 field->index = item->nbFields;
8377 item->nbFields++;
8378 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008379 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008380 else
8381 item->fields = field;
8382 lastField = field;
8383 }
8384 child = child->next;
8385 } while (IS_SCHEMA(child, "field"));
8386 } else {
8387 xmlSchemaPContentErr(ctxt,
8388 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008389 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008390 NULL, "(annotation?, (selector, field+))");
8391 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008392 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008393 if (child != NULL) {
8394 xmlSchemaPContentErr(ctxt,
8395 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008396 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008397 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008398 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008399
8400 return (item);
8401}
8402
Daniel Veillardc0826a72004-08-10 14:17:33 +00008403/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008404 * xmlSchemaParseElement:
8405 * @ctxt: a schema validation context
8406 * @schema: the schema being built
8407 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008408 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00008409 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008410 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00008411 * *WARNING* this interface is highly subject to change
8412 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008413 * Returns the element declaration or a particle; NULL in case
8414 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00008415 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008416static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00008417xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008418 xmlNodePtr node, int *isElemRef, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008419{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008420 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008421 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008422 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008423 xmlNodePtr child = NULL;
8424 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008425 int min, max, isRef = 0;
8426 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00008427
8428 /* 3.3.3 Constraints on XML Representations of Element Declarations */
8429 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008430
Daniel Veillard4255d502002-04-16 15:50:10 +00008431 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008432 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008433
8434 if (isElemRef != NULL)
8435 *isElemRef = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008436 /*
8437 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008438 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008439 * robust.
8440 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008441 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008442 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008443 if ((topLevel) || (attr == NULL)) {
8444 if (nameAttr == NULL) {
8445 xmlSchemaPMissingAttrErr(ctxt,
8446 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008447 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008448 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008449 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008450 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00008451 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008452
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008453 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008454 child = node->children;
8455 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008456 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008457 child = child->next;
8458 }
8459 /*
8460 * Skip particle part if a global declaration.
8461 */
8462 if (topLevel)
8463 goto declaration_part;
8464 /*
8465 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008466 */
8467 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8468 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8469 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +00008470 particle = xmlSchemaAddParticle(ctxt, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008471 if (particle == NULL)
8472 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008473
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008474 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8475
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008476 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008477 const xmlChar *refNs = NULL, *ref = NULL;
8478 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008479 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008480 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00008481 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008482 if (isElemRef != NULL)
8483 *isElemRef = 1;
8484
Daniel Veillardc0826a72004-08-10 14:17:33 +00008485 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008486 NULL, attr, &refNs, &ref);
8487 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008488 /*
8489 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00008490 */
8491 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008492 xmlSchemaPMutualExclAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008493 XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008494 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008495 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008496 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008497 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008498 attr = node->properties;
8499 while (attr != NULL) {
8500 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008501 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8502 xmlStrEqual(attr->name, BAD_CAST "name") ||
8503 xmlStrEqual(attr->name, BAD_CAST "id") ||
8504 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8505 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8506 {
8507 attr = attr->next;
8508 continue;
8509 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008510 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008511 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008512 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008513 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008514 "Only the attributes 'minOccurs', 'maxOccurs' and "
8515 "'id' are allowed in addition to 'ref'");
8516 break;
8517 }
8518 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8519 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008520 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008521 }
8522 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008523 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008524 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008525 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008526 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008527 if (child != NULL) {
8528 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008529 NULL, node, child, NULL, "(annotation?)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008530 }
8531 if ((min == 0) && (max == 0))
8532 goto return_null;
8533 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008534 * Create the reference item and attach it to the particle.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008535 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008536 refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008537 ref, refNs);
8538 if (refer == NULL)
8539 goto return_null;
8540 particle->children = (xmlSchemaTreeItemPtr) refer;
8541 particle->annot = annot;
8542 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008543 * Add the particle to pending components, since the reference
8544 * need to be resolved.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008545 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008546 WXS_ADD_PENDING(ctxt, particle);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008547 return ((xmlSchemaBasicItemPtr) particle);
8548 }
8549 /*
8550 * The declaration part ===============================================
8551 */
8552declaration_part:
8553 {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008554 const xmlChar *ns = NULL, *fixed, *name, *attrValue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008555 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8556
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008557 if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008558 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008559 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008560 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008561 * Evaluate the target namespace.
8562 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008563 if (topLevel) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008564 ns = ctxt->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008565 } else {
8566 attr = xmlSchemaGetPropNode(node, "form");
8567 if (attr != NULL) {
8568 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8569 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008570 ns = ctxt->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008571 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008572 xmlSchemaPSimpleTypeErr(ctxt,
8573 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8574 NULL, (xmlNodePtr) attr,
8575 NULL, "(qualified | unqualified)",
8576 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008577 }
8578 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008579 ns = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008580 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008581 decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008582 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008583 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00008584 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008585 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008586 * Check for illegal attributes.
8587 */
William M. Bracke7091952004-05-11 15:09:58 +00008588 attr = node->properties;
8589 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008590 if (attr->ns == NULL) {
8591 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8592 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008593 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008594 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008595 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008596 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008597 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8598 {
8599 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008600 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008601 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008602 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008603 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008604 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008605 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008606 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008607 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8608 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008609 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8610
8611 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008612 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008613 }
8614 }
8615 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008616
Daniel Veillardc0826a72004-08-10 14:17:33 +00008617 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008618 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Bracke7091952004-05-11 15:09:58 +00008619 }
8620 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008621 }
William M. Bracke7091952004-05-11 15:09:58 +00008622 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008623 * Extract/validate attributes.
8624 */
8625 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008626 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008627 * Process top attributes of global element declarations here.
8628 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008629 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8630 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008631 xmlSchemaPValAttrQName(ctxt, schema,
8632 NULL, node, "substitutionGroup",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008633 &(decl->substGroupNs), &(decl->substGroup));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008634 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008635 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008636 /*
8637 * Attribute "final".
8638 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008639 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008640 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008641 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8642 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8643 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8644 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008645 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008646 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8647 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00008648 -1,
8649 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8650 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008651 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008652 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008653 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008654 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008655 attrValue, NULL, NULL, NULL);
8656 }
8657 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008658 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008659 /*
8660 * Attribute "block".
8661 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008662 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008663 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00008664 /*
8665 * Apply default "block" values.
8666 */
8667 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8668 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8669 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8670 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8671 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8672 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008673 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008674 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8675 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00008676 -1,
8677 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008678 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008679 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8680 xmlSchemaPSimpleTypeErr(ctxt,
8681 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008682 NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00008683 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008684 "restriction | substitution))", attrValue,
8685 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008686 }
8687 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008688 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008689 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008690
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008691 attr = xmlSchemaGetPropNode(node, "type");
8692 if (attr != NULL) {
8693 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008694 NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008695 &(decl->namedTypeNs), &(decl->namedType));
8696 xmlSchemaCheckReference(ctxt, schema, node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008697 attr, decl->namedTypeNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008698 }
8699 decl->value = xmlSchemaGetProp(ctxt, node, "default");
8700 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008701 if (attr != NULL) {
8702 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008703 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008704 /*
8705 * 3.3.3 : 1
8706 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008707 */
8708 xmlSchemaPMutualExclAttrErr(ctxt,
8709 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008710 NULL, attr, "default", "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008711 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008712 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8713 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008714 }
William M. Bracke7091952004-05-11 15:09:58 +00008715 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008716 /*
8717 * And now for the children...
8718 */
William M. Bracke7091952004-05-11 15:09:58 +00008719 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008720 /*
8721 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00008722 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008723 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00008724 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008725 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008726 xmlSchemaPContentErr(ctxt,
8727 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008728 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008729 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008730 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008731 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008732 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00008733 child = child->next;
8734 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008735 /*
8736 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00008737 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008738 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00008739 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008740 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008741 xmlSchemaPContentErr(ctxt,
8742 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008743 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008744 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008745 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008746 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008747 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00008748 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008749 }
William M. Bracke7091952004-05-11 15:09:58 +00008750 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00008751 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008752 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008753 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008754 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008755 } else if (IS_SCHEMA(child, "key")) {
8756 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008757 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008758 } else if (IS_SCHEMA(child, "keyref")) {
8759 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008760 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008761 }
8762 if (lastIDC != NULL)
8763 lastIDC->next = curIDC;
8764 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008765 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008766 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008767 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00008768 }
8769 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008770 xmlSchemaPContentErr(ctxt,
8771 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008772 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008773 NULL, "(annotation?, ((simpleType | complexType)?, "
8774 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008775 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008776 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008777 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008778 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008779 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00008780 * different layer.
8781 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008782 FREE_AND_NULL(des)
8783 if (topLevel)
8784 return ((xmlSchemaBasicItemPtr) decl);
8785 else {
8786 particle->children = (xmlSchemaTreeItemPtr) decl;
8787 return ((xmlSchemaBasicItemPtr) particle);
8788 }
8789
8790return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008791 FREE_AND_NULL(des);
8792 if (annot != NULL) {
8793 if (particle != NULL)
8794 particle->annot = NULL;
8795 if (decl != NULL)
8796 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008797 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008798 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008799 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008800}
8801
8802/**
8803 * xmlSchemaParseUnion:
8804 * @ctxt: a schema validation context
8805 * @schema: the schema being built
8806 * @node: a subtree containing XML Schema informations
8807 *
8808 * parse a XML schema Union definition
8809 * *WARNING* this interface is highly subject to change
8810 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008811 * Returns -1 in case of internal error, 0 in case of success and a positive
8812 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00008813 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008814static int
Daniel Veillard4255d502002-04-16 15:50:10 +00008815xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008816 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008817{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008818 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008819 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008820 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008821 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008822
8823 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008824 return (-1);
8825 /* Not a component, don't create it. */
8826 type = ctxt->ctxtType;
8827 /*
8828 * Mark the simple type as being of variety "union".
8829 */
8830 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008831 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008832 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8833 * then the ·simple ur-type definition·."
8834 */
8835 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008836 /*
8837 * Check for illegal attributes.
8838 */
8839 attr = node->properties;
8840 while (attr != NULL) {
8841 if (attr->ns == NULL) {
8842 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8843 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008844 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008845 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008846 }
8847 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008848 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008849 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008850 }
8851 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008852 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008853 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008854 /*
8855 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008856 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00008857 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008858 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008859 if (attr != NULL) {
8860 const xmlChar *end;
8861 xmlChar *tmp;
8862 const xmlChar *localName, *nsName;
8863 xmlSchemaTypeLinkPtr link, lastLink = NULL;
8864 xmlSchemaQNameRefPtr ref;
8865
8866 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008867 type->base = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008868 do {
8869 while (IS_BLANK_CH(*cur))
8870 cur++;
8871 end = cur;
8872 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8873 end++;
8874 if (end == cur)
8875 break;
8876 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008877 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008878 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008879 /*
8880 * Create the member type link.
8881 */
8882 link = (xmlSchemaTypeLinkPtr)
8883 xmlMalloc(sizeof(xmlSchemaTypeLink));
8884 if (link == NULL) {
8885 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8886 "allocating a type link", NULL);
8887 return (-1);
8888 }
8889 link->type = NULL;
8890 link->next = NULL;
8891 if (lastLink == NULL)
8892 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008893 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008894 lastLink->next = link;
8895 lastLink = link;
8896 /*
8897 * Create a reference item.
8898 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008899 ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008900 localName, nsName);
8901 if (ref == NULL) {
8902 FREE_AND_NULL(tmp)
8903 return (-1);
8904 }
8905 /*
8906 * Assign the reference to the link, it will be resolved
8907 * later during fixup of the union simple type.
8908 */
8909 link->type = (xmlSchemaTypePtr) ref;
8910 }
8911 FREE_AND_NULL(tmp)
8912 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008913 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008914
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008915 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008916 /*
8917 * And now for the children...
8918 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008919 child = node->children;
8920 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008921 /*
8922 * Add the annotation to the simple type ancestor.
8923 */
8924 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008925 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008926 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008927 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008928 if (IS_SCHEMA(child, "simpleType")) {
8929 xmlSchemaTypePtr subtype, last = NULL;
8930
8931 /*
8932 * Anchor the member types in the "subtypes" field of the
8933 * simple type.
8934 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008935 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008936 subtype = (xmlSchemaTypePtr)
8937 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8938 if (subtype != NULL) {
8939 if (last == NULL) {
8940 type->subtypes = subtype;
8941 last = subtype;
8942 } else {
8943 last->next = subtype;
8944 last = subtype;
8945 }
8946 last->next = NULL;
8947 }
8948 child = child->next;
8949 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008950 }
8951 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008952 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008953 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008954 NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008955 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008956 if ((attr == NULL) && (type->subtypes == NULL)) {
8957 /*
8958 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008959 * Either the memberTypes [attribute] of the <union> element must
8960 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008961 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008962 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008963 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008964 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008965 "Either the attribute 'memberTypes' or "
8966 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008967 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008968 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00008969}
8970
8971/**
8972 * xmlSchemaParseList:
8973 * @ctxt: a schema validation context
8974 * @schema: the schema being built
8975 * @node: a subtree containing XML Schema informations
8976 *
8977 * parse a XML schema List definition
8978 * *WARNING* this interface is highly subject to change
8979 *
William M. Bracke7091952004-05-11 15:09:58 +00008980 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008981 * 1 in case of success.
8982 */
8983static xmlSchemaTypePtr
8984xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008985 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008986{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008987 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008988 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008989 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008990
8991 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8992 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008993 /* Not a component, don't create it. */
8994 type = ctxt->ctxtType;
8995 /*
8996 * Mark the type as being of variety "list".
8997 */
8998 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008999 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009000 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
9001 * then the ·simple ur-type definition·."
9002 */
9003 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00009004 /*
9005 * Check for illegal attributes.
9006 */
9007 attr = node->properties;
9008 while (attr != NULL) {
9009 if (attr->ns == NULL) {
9010 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9011 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009012 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009013 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009014 }
9015 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009016 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009017 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009018 }
9019 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009020 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009021
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009022 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009023
William M. Brack2f2a6632004-08-20 23:09:47 +00009024 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009025 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9026 * fields for holding the reference to the itemType.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009027 *
9028 * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9029 * the "ref" fields.
William M. Brack2f2a6632004-08-20 23:09:47 +00009030 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009031 xmlSchemaPValAttrQName(ctxt, schema, NULL,
9032 node, "itemType", &(type->baseNs), &(type->base));
William M. Brack2f2a6632004-08-20 23:09:47 +00009033 /*
9034 * And now for the children...
9035 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009036 child = node->children;
9037 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009038 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009039 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009040 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009041 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009042 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009043 /*
9044 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009045 * Either the itemType [attribute] or the <simpleType> [child] of
9046 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009047 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009048 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009049 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009050 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009051 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00009052 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009053 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009054 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009055 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009056 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009057 child = child->next;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009058 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009059 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009060 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009061 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009062 "Either the attribute 'itemType' or the <simpleType> child "
9063 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009064 }
9065 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009066 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009067 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009068 NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00009069 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009070 if ((type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009071 (type->subtypes == NULL) &&
9072 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009073 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009074 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009075 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009076 "Either the attribute 'itemType' or the <simpleType> child "
9077 "must be present", NULL);
9078 }
9079 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009080}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009081
Daniel Veillard4255d502002-04-16 15:50:10 +00009082/**
9083 * xmlSchemaParseSimpleType:
9084 * @ctxt: a schema validation context
9085 * @schema: the schema being built
9086 * @node: a subtree containing XML Schema informations
9087 *
9088 * parse a XML schema Simple Type definition
9089 * *WARNING* this interface is highly subject to change
9090 *
William M. Bracke7091952004-05-11 15:09:58 +00009091 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00009092 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00009093 */
9094static xmlSchemaTypePtr
9095xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00009096 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00009097{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009098 xmlSchemaTypePtr type, oldCtxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009099 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009100 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009101 xmlAttrPtr attr;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009102 int hasRestriction = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009103
9104 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9105 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009106
Daniel Veillardc0826a72004-08-10 14:17:33 +00009107 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009108 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009109 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009110 xmlSchemaPMissingAttrErr(ctxt,
9111 XML_SCHEMAP_S4S_ATTR_MISSING,
9112 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009113 "name", NULL);
9114 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009115 } else {
9116 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009117 NULL, attr,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009118 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9119 return (NULL);
9120 /*
9121 * Skip built-in types.
9122 */
9123 if (ctxt->isS4S) {
9124 xmlSchemaTypePtr biType;
9125
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009126 if (ctxt->isRedefine) {
9127 /*
9128 * REDEFINE: Disallow redefinition of built-in-types.
9129 * TODO: It seems that the spec does not say anything
9130 * about this case.
9131 */
9132 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009133 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009134 "Redefinition of built-in simple types is not "
9135 "supported", NULL);
9136 return(NULL);
9137 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009138 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9139 if (biType != NULL)
9140 return (biType);
9141 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009142 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009143 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009144 /*
9145 * TargetNamespace:
9146 * SPEC "The ·actual value· of the targetNamespace [attribute]
9147 * of the <schema> ancestor element information item if present,
9148 * otherwise ·absent·.
9149 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009150 if (topLevel == 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009151#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009152 char buf[40];
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009153#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +00009154 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00009155 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009156 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009157#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009158 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009159 type = xmlSchemaAddType(ctxt, schema,
9160 XML_SCHEMA_TYPE_SIMPLE,
9161 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009162 ctxt->targetNamespace, node, 0);
9163#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009164 type = xmlSchemaAddType(ctxt, schema,
9165 XML_SCHEMA_TYPE_SIMPLE,
9166 NULL, ctxt->targetNamespace, node, 0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009167#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +00009168 if (type == NULL)
9169 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009170 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009171 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009172 /*
9173 * Check for illegal attributes.
9174 */
9175 attr = node->properties;
9176 while (attr != NULL) {
9177 if (attr->ns == NULL) {
9178 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009179 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009180 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009181 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009182 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009183 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009184 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009185 }
9186 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009187 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009188 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009189 /*
9190 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009191 *
9192 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009193 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009194 type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9195 attrValue, ctxt->targetNamespace, node, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009196 if (type == NULL)
9197 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009198 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009199 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009200 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9201 /*
9202 * Check for illegal attributes.
9203 */
9204 attr = node->properties;
9205 while (attr != NULL) {
9206 if (attr->ns == NULL) {
9207 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9208 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009209 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009210 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009211 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009212 }
9213 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009214 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009215 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009216 }
9217 attr = attr->next;
9218 }
9219 /*
9220 * Attribute "final".
9221 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009222 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009223 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009224 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9225 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9226 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9227 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9228 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9229 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009230 } else {
9231 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009232 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9233 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009234 XML_SCHEMAS_TYPE_FINAL_LIST,
9235 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9236
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009237 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009238 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009239 WXS_BASIC_CAST type, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009240 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00009241 attrValue, NULL, NULL, NULL);
9242 }
9243 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009244 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009245 type->targetNamespace = ctxt->targetNamespace;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009246 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009247 /*
9248 * And now for the children...
9249 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009250 oldCtxtType = ctxt->ctxtType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009251
Daniel Veillardc0826a72004-08-10 14:17:33 +00009252 ctxt->ctxtType = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009253
Daniel Veillard4255d502002-04-16 15:50:10 +00009254 child = node->children;
9255 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009256 type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009257 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009258 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009259 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009260 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009261 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009262 "(annotation?, (restriction | list | union))");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009263 } else if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009264 xmlSchemaParseRestriction(ctxt, schema, child,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009265 XML_SCHEMA_TYPE_SIMPLE);
9266 hasRestriction = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009267 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009268 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009269 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009270 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009271 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009272 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009273 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009274 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009275 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009276 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009277 NULL, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009278 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00009279 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009280 /*
9281 * REDEFINE: SPEC src-redefine (5)
9282 * "Within the [children], each <simpleType> must have a
9283 * <restriction> among its [children] ... the ·actual value· of whose
9284 * base [attribute] must be the same as the ·actual value· of its own
9285 * name attribute plus target namespace;"
9286 */
9287 if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9288 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009289 NULL, node, "This is a redefinition, thus the "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009290 "<simpleType> must have a <restriction> child", NULL);
9291 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009292
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009293 ctxt->ctxtType = oldCtxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009294 return (type);
9295}
9296
Daniel Veillard4255d502002-04-16 15:50:10 +00009297/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009298 * xmlSchemaParseModelGroupDefRef:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009299 * @ctxt: the parser context
9300 * @schema: the schema being built
9301 * @node: the node
Daniel Veillard4255d502002-04-16 15:50:10 +00009302 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009303 * Parses a reference to a model group definition.
Daniel Veillard4255d502002-04-16 15:50:10 +00009304 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009305 * We will return a particle component with a qname-component or
9306 * NULL in case of an error.
Daniel Veillard4255d502002-04-16 15:50:10 +00009307 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009308static xmlSchemaTreeItemPtr
9309xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9310 xmlSchemaPtr schema,
9311 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00009312{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009313 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009314 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009315 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009316 const xmlChar *ref = NULL, *refNs = NULL;
9317 int min, max;
9318
9319 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009320 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009321
9322 attr = xmlSchemaGetPropNode(node, "ref");
9323 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009324 xmlSchemaPMissingAttrErr(ctxt,
9325 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009326 NULL, node, "ref", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009327 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009328 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009329 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009330 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009331 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009332 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009333 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009334 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009335 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009336 /*
9337 * Check for illegal attributes.
9338 */
9339 attr = node->properties;
9340 while (attr != NULL) {
9341 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009342 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009343 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9344 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9345 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009346 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009347 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009348 }
9349 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009350 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009351 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009352 }
9353 attr = attr->next;
9354 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009355 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +00009356 item = xmlSchemaAddParticle(ctxt, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009357 if (item == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009358 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009359 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009360 * Create a qname-reference and set as the term; it will be substituted
9361 * for the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009362 */
9363 item->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009364 xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009365 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9366 /*
9367 * And now for the children...
9368 */
9369 child = node->children;
9370 /* TODO: Is annotation even allowed for a model group reference? */
9371 if (IS_SCHEMA(child, "annotation")) {
9372 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009373 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009374 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009375 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009376 child = child->next;
9377 }
9378 if (child != NULL) {
9379 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009380 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009381 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009382 "(annotation?)");
9383 }
9384 /*
9385 * Corresponds to no component at all if minOccurs==maxOccurs==0.
9386 */
9387 if ((min == 0) && (max == 0))
9388 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009389
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009390 return ((xmlSchemaTreeItemPtr) item);
9391}
9392
9393/**
9394 * xmlSchemaParseModelGroupDefinition:
9395 * @ctxt: a schema validation context
9396 * @schema: the schema being built
9397 * @node: a subtree containing XML Schema informations
9398 *
9399 * Parses a XML schema model group definition.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009400 *
9401 * Note that the contraint src-redefine (6.2) can't be applied until
9402 * references have been resolved. So we will do this at the
9403 * component fixup level.
9404 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009405 * *WARNING* this interface is highly subject to change
9406 *
9407 * Returns -1 in case of error, 0 if the declaration is improper and
9408 * 1 in case of success.
9409 */
9410static xmlSchemaModelGroupDefPtr
9411xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9412 xmlSchemaPtr schema,
9413 xmlNodePtr node)
9414{
9415 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009416 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009417 xmlAttrPtr attr;
9418 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00009419
9420 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009421 return (NULL);
9422
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009423 attr = xmlSchemaGetPropNode(node, "name");
9424 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009425 xmlSchemaPMissingAttrErr(ctxt,
9426 XML_SCHEMAP_S4S_ATTR_MISSING,
9427 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009428 "name", NULL);
9429 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009430 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009431 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9432 return (NULL);
9433 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009434 item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9435 ctxt->targetNamespace, node);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009436 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009437 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009438 /*
9439 * Check for illegal attributes.
9440 */
9441 attr = node->properties;
9442 while (attr != NULL) {
9443 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009444 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009445 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009446 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009447 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009448 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009449 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009450 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009451 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009452 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009453 attr = attr->next;
9454 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009455 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009456 /*
9457 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009458 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009459 child = node->children;
9460 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009461 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009462 child = child->next;
9463 }
9464 if (IS_SCHEMA(child, "all")) {
9465 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9466 XML_SCHEMA_TYPE_ALL, 0);
9467 child = child->next;
9468 } else if (IS_SCHEMA(child, "choice")) {
9469 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9470 XML_SCHEMA_TYPE_CHOICE, 0);
9471 child = child->next;
9472 } else if (IS_SCHEMA(child, "sequence")) {
9473 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9474 XML_SCHEMA_TYPE_SEQUENCE, 0);
9475 child = child->next;
9476 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009477
9478
9479
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009480 if (child != NULL) {
9481 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009482 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009483 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009484 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009485 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009486 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009487}
9488
9489/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009490 * xmlSchemaCleanupDoc:
9491 * @ctxt: a schema validation context
9492 * @node: the root of the document.
9493 *
9494 * removes unwanted nodes in a schemas document tree
9495 */
9496static void
9497xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9498{
9499 xmlNodePtr delete, cur;
9500
9501 if ((ctxt == NULL) || (root == NULL)) return;
9502
9503 /*
9504 * Remove all the blank text nodes
9505 */
9506 delete = NULL;
9507 cur = root;
9508 while (cur != NULL) {
9509 if (delete != NULL) {
9510 xmlUnlinkNode(delete);
9511 xmlFreeNode(delete);
9512 delete = NULL;
9513 }
9514 if (cur->type == XML_TEXT_NODE) {
9515 if (IS_BLANK_NODE(cur)) {
9516 if (xmlNodeGetSpacePreserve(cur) != 1) {
9517 delete = cur;
9518 }
9519 }
9520 } else if ((cur->type != XML_ELEMENT_NODE) &&
9521 (cur->type != XML_CDATA_SECTION_NODE)) {
9522 delete = cur;
9523 goto skip_children;
9524 }
9525
9526 /*
9527 * Skip to next node
9528 */
9529 if (cur->children != NULL) {
9530 if ((cur->children->type != XML_ENTITY_DECL) &&
9531 (cur->children->type != XML_ENTITY_REF_NODE) &&
9532 (cur->children->type != XML_ENTITY_NODE)) {
9533 cur = cur->children;
9534 continue;
9535 }
9536 }
9537 skip_children:
9538 if (cur->next != NULL) {
9539 cur = cur->next;
9540 continue;
9541 }
9542
9543 do {
9544 cur = cur->parent;
9545 if (cur == NULL)
9546 break;
9547 if (cur == root) {
9548 cur = NULL;
9549 break;
9550 }
9551 if (cur->next != NULL) {
9552 cur = cur->next;
9553 break;
9554 }
9555 } while (cur != NULL);
9556 }
9557 if (delete != NULL) {
9558 xmlUnlinkNode(delete);
9559 xmlFreeNode(delete);
9560 delete = NULL;
9561 }
9562}
9563
William M. Brack2f2a6632004-08-20 23:09:47 +00009564
William M. Brack2f2a6632004-08-20 23:09:47 +00009565static void
9566xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9567{
9568 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9569 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9570
9571 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9572 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9573
9574 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9575 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9576 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9577 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9578 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9579 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9580 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9581 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9582
9583 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9584 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9585 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9586 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9587 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9588 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9589}
9590
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009591static int
9592xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009593 xmlSchemaPtr schema,
9594 xmlNodePtr node)
9595{
9596 xmlAttrPtr attr;
9597 const xmlChar *val;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009598 int res = 0, oldErrs = ctxt->nberrors;
William M. Brack2f2a6632004-08-20 23:09:47 +00009599
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009600 /*
9601 * Those flags should be moved to the parser context flags,
9602 * since they are not visible at the component level. I.e.
9603 * they are used if processing schema *documents* only.
9604 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009605 res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009606 HFAILURE;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009607
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009608 /*
9609 * Since the version is of type xs:token, we won't bother to
9610 * check it.
9611 */
9612 /* REMOVED:
9613 attr = xmlSchemaGetPropNode(node, "version");
9614 if (attr != NULL) {
9615 res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9616 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9617 HFAILURE;
9618 }
9619 */
9620 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9621 if (attr != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009622 res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009623 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9624 HFAILURE;
9625 if (res != 0) {
9626 ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9627 goto exit;
9628 }
9629 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009630 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009631 if (attr != NULL) {
9632 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009633 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9634 XML_SCHEMAS_QUALIF_ELEM);
9635 HFAILURE;
9636 if (res != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009637 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009638 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009639 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009640 "(qualified | unqualified)", val, NULL, NULL, NULL);
9641 }
9642 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009643 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009644 if (attr != NULL) {
9645 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009646 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9647 XML_SCHEMAS_QUALIF_ATTR);
9648 HFAILURE;
9649 if (res != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009650 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009651 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009652 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009653 "(qualified | unqualified)", val, NULL, NULL, NULL);
9654 }
9655 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009656 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009657 if (attr != NULL) {
9658 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009659 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
William M. Brack2f2a6632004-08-20 23:09:47 +00009660 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9661 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9662 -1,
9663 XML_SCHEMAS_FINAL_DEFAULT_LIST,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009664 XML_SCHEMAS_FINAL_DEFAULT_UNION);
9665 HFAILURE;
9666 if (res != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009667 xmlSchemaPSimpleTypeErr(ctxt,
9668 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009669 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009670 "(#all | List of (extension | restriction | list | union))",
9671 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009672 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009673 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009674 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009675 if (attr != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009676 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9677 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
William M. Brack2f2a6632004-08-20 23:09:47 +00009678 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9679 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009680 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9681 HFAILURE;
9682 if (res != 0) {
9683 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009684 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009685 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009686 "(#all | List of (extension | restriction | substitution))",
9687 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009688 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009689 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009690
9691exit:
9692 if (oldErrs != ctxt->nberrors)
9693 res = ctxt->err;
9694 return(res);
9695exit_failure:
9696 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009697}
9698
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009699/**
9700 * xmlSchemaParseSchemaTopLevel:
9701 * @ctxt: a schema validation context
9702 * @schema: the schemas
9703 * @nodes: the list of top level nodes
9704 *
9705 * Returns the internal XML Schema structure built from the resource or
9706 * NULL in case of error
9707 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009708static int
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009709xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9710 xmlSchemaPtr schema, xmlNodePtr nodes)
9711{
9712 xmlNodePtr child;
9713 xmlSchemaAnnotPtr annot;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009714 int res = 0, oldErrs, tmpOldErrs;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009715
9716 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009717 return(-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009718
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009719 oldErrs = ctxt->nberrors;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009720 child = nodes;
9721 while ((IS_SCHEMA(child, "include")) ||
9722 (IS_SCHEMA(child, "import")) ||
9723 (IS_SCHEMA(child, "redefine")) ||
9724 (IS_SCHEMA(child, "annotation"))) {
9725 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009726 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009727 if (schema->annot == NULL)
9728 schema->annot = annot;
9729 else
9730 xmlSchemaFreeAnnot(annot);
9731 } else if (IS_SCHEMA(child, "import")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009732 tmpOldErrs = ctxt->nberrors;
9733 res = xmlSchemaParseImport(ctxt, schema, child);
9734 HFAILURE;
9735 HSTOP(ctxt);
9736 if (tmpOldErrs != ctxt->nberrors)
9737 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009738 } else if (IS_SCHEMA(child, "include")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009739 tmpOldErrs = ctxt->nberrors;
9740 res = xmlSchemaParseInclude(ctxt, schema, child);
9741 HFAILURE;
9742 HSTOP(ctxt);
9743 if (tmpOldErrs != ctxt->nberrors)
9744 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009745 } else if (IS_SCHEMA(child, "redefine")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009746 tmpOldErrs = ctxt->nberrors;
9747 res = xmlSchemaParseRedefine(ctxt, schema, child);
9748 HFAILURE;
9749 HSTOP(ctxt);
9750 if (tmpOldErrs != ctxt->nberrors)
9751 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009752 }
9753 child = child->next;
9754 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009755 /*
9756 * URGENT TODO: Change the functions to return int results.
9757 * We need especially to catch internal errors.
9758 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009759 while (child != NULL) {
9760 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009761 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009762 child = child->next;
9763 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009764 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009765 child = child->next;
9766 } else if (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009767 xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009768 child = child->next;
9769 } else if (IS_SCHEMA(child, "attribute")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009770 xmlSchemaParseGlobalAttribute(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009771 child = child->next;
9772 } else if (IS_SCHEMA(child, "attributeGroup")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009773 xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009774 child = child->next;
9775 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009776 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009777 child = child->next;
9778 } else if (IS_SCHEMA(child, "notation")) {
9779 xmlSchemaParseNotation(ctxt, schema, child);
9780 child = child->next;
9781 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009782 xmlSchemaPContentErr(ctxt,
9783 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009784 NULL, child->parent, child,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009785 NULL, "((include | import | redefine | annotation)*, "
9786 "(((simpleType | complexType | group | attributeGroup) "
9787 "| element | attribute | notation), annotation*)*)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009788 child = child->next;
9789 }
9790 while (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009791 /*
9792 * TODO: We should add all annotations.
9793 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009794 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009795 if (schema->annot == NULL)
9796 schema->annot = annot;
9797 else
9798 xmlSchemaFreeAnnot(annot);
9799 child = child->next;
9800 }
9801 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009802exit:
Daniel Veillard01fa6152004-06-29 17:04:39 +00009803 ctxt->ctxtType = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009804 if (oldErrs != ctxt->nberrors)
9805 res = ctxt->err;
9806 return(res);
9807exit_failure:
9808 return(-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009809}
9810
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009811static xmlSchemaSchemaRelationPtr
9812xmlSchemaSchemaRelationCreate(void)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009813{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009814 xmlSchemaSchemaRelationPtr ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009815
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009816 ret = (xmlSchemaSchemaRelationPtr)
9817 xmlMalloc(sizeof(xmlSchemaSchemaRelation));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009818 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009819 xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009820 return(NULL);
9821 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009822 memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009823 return(ret);
9824}
9825
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009826#if 0
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009827static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009828xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009829{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009830 xmlFree(rel);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009831}
9832#endif
9833
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009834static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009835xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9836{
9837 xmlSchemaRedefPtr prev;
9838
9839 while (redef != NULL) {
9840 prev = redef;
9841 redef = redef->next;
9842 xmlFree(prev);
9843 }
9844}
9845
9846static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009847xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9848{
9849 /*
9850 * After the construction context has been freed, there will be
9851 * no schema graph available any more. Only the schema buckets
9852 * will stay alive, which are put into the "schemasImports" and
9853 * "includes" slots of the xmlSchema.
9854 */
9855 if (con->buckets != NULL)
9856 xmlSchemaItemListFree(con->buckets);
9857 if (con->pending != NULL)
9858 xmlSchemaItemListFree(con->pending);
9859 if (con->substGroups != NULL)
9860 xmlHashFree(con->substGroups,
9861 (xmlHashDeallocator) xmlSchemaSubstGroupFree);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009862 if (con->redefs != NULL)
9863 xmlSchemaRedefListFree(con->redefs);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009864 if (con->dict != NULL)
9865 xmlDictFree(con->dict);
9866 xmlFree(con);
9867}
9868
9869static xmlSchemaConstructionCtxtPtr
9870xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9871{
9872 xmlSchemaConstructionCtxtPtr ret;
9873
9874 ret = (xmlSchemaConstructionCtxtPtr)
9875 xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9876 if (ret == NULL) {
9877 xmlSchemaPErrMemory(NULL,
9878 "allocating schema construction context", NULL);
9879 return (NULL);
9880 }
9881 memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9882
9883 ret->buckets = xmlSchemaItemListCreate();
9884 if (ret->buckets == NULL) {
9885 xmlSchemaPErrMemory(NULL,
9886 "allocating list of schema buckets", NULL);
9887 xmlFree(ret);
9888 return (NULL);
9889 }
9890 ret->pending = xmlSchemaItemListCreate();
9891 if (ret->pending == NULL) {
9892 xmlSchemaPErrMemory(NULL,
9893 "allocating list of pending global components", NULL);
9894 xmlSchemaConstructionCtxtFree(ret);
9895 return (NULL);
9896 }
9897 ret->dict = dict;
9898 xmlDictReference(dict);
9899 return(ret);
9900}
9901
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009902static xmlSchemaParserCtxtPtr
9903xmlSchemaParserCtxtCreate(void)
9904{
9905 xmlSchemaParserCtxtPtr ret;
9906
9907 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9908 if (ret == NULL) {
9909 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9910 NULL);
9911 return (NULL);
9912 }
9913 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9914 ret->type = XML_SCHEMA_CTXT_PARSER;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009915 ret->attrProhibs = xmlSchemaItemListCreate();
9916 if (ret->attrProhibs == NULL) {
9917 xmlFree(ret);
9918 return(NULL);
9919 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009920 return(ret);
9921}
9922
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009923/**
9924 * xmlSchemaNewParserCtxtUseDict:
9925 * @URL: the location of the schema
9926 * @dict: the dictionary to be used
9927 *
9928 * Create an XML Schemas parse context for that file/resource expected
9929 * to contain an XML Schemas file.
9930 *
9931 * Returns the parser context or NULL in case of error
9932 */
9933static xmlSchemaParserCtxtPtr
9934xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9935{
9936 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009937
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009938 ret = xmlSchemaParserCtxtCreate();
9939 if (ret == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009940 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009941 ret->dict = dict;
9942 xmlDictReference(dict);
9943 if (URL != NULL)
9944 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009945 return (ret);
9946}
9947
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009948static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009949xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
9950{
9951 if (vctxt->pctxt == NULL) {
9952 if (vctxt->schema != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009953 vctxt->pctxt =
9954 xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009955 else
9956 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
9957 if (vctxt->pctxt == NULL) {
9958 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
9959 "failed to create a temp. parser context");
9960 return (-1);
9961 }
9962 /* TODO: Pass user data. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009963 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00009964 vctxt->warning, vctxt->errCtxt);
9965 xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
9966 vctxt->errCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009967 }
9968 return (0);
9969}
9970
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009971/**
9972 * xmlSchemaGetSchemaBucket:
9973 * @pctxt: the schema parser context
9974 * @schemaLocation: the URI of the schema document
9975 *
9976 * Returns a schema bucket if it was already parsed.
9977 *
9978 * Returns a schema bucket if it was already parsed from
9979 * @schemaLocation, NULL otherwise.
9980 */
9981static xmlSchemaBucketPtr
9982xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
9983 const xmlChar *schemaLocation)
9984{
9985 xmlSchemaBucketPtr cur;
9986 xmlSchemaItemListPtr list;
9987
9988 list = pctxt->constructor->buckets;
9989 if (list->nbItems == 0)
9990 return(NULL);
9991 else {
9992 int i;
9993 for (i = 0; i < list->nbItems; i++) {
9994 cur = (xmlSchemaBucketPtr) list->items[i];
9995 /* Pointer comparison! */
9996 if (cur->schemaLocation == schemaLocation)
9997 return(cur);
9998 }
9999 }
10000 return(NULL);
10001}
10002
10003static xmlSchemaBucketPtr
10004xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10005 const xmlChar *schemaLocation,
10006 const xmlChar *targetNamespace)
10007{
10008 xmlSchemaBucketPtr cur;
10009 xmlSchemaItemListPtr list;
10010
10011 list = pctxt->constructor->buckets;
10012 if (list->nbItems == 0)
10013 return(NULL);
10014 else {
10015 int i;
10016 for (i = 0; i < list->nbItems; i++) {
10017 cur = (xmlSchemaBucketPtr) list->items[i];
10018 /* Pointer comparison! */
10019 if ((cur->origTargetNamespace == NULL) &&
10020 (cur->schemaLocation == schemaLocation) &&
10021 (cur->targetNamespace == targetNamespace))
10022 return(cur);
10023 }
10024 }
10025 return(NULL);
10026}
10027
10028
10029#define IS_BAD_SCHEMA_DOC(b) \
10030 (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10031
10032static xmlSchemaBucketPtr
10033xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10034 const xmlChar *targetNamespace,
10035 int imported)
10036{
10037 xmlSchemaBucketPtr cur;
10038 xmlSchemaItemListPtr list;
10039
10040 list = pctxt->constructor->buckets;
10041 if (list->nbItems == 0)
10042 return(NULL);
10043 else {
10044 int i;
10045 for (i = 0; i < list->nbItems; i++) {
10046 cur = (xmlSchemaBucketPtr) list->items[i];
10047 if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10048 (cur->origTargetNamespace == targetNamespace) &&
10049 ((imported && cur->imported) ||
10050 ((!imported) && (!cur->imported))))
10051 return(cur);
10052 }
10053 }
10054 return(NULL);
10055}
10056
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010057static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010058xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10059 xmlSchemaPtr schema,
10060 xmlSchemaBucketPtr bucket)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010061{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010062 int oldFlags;
10063 xmlDocPtr oldDoc;
10064 xmlNodePtr node;
10065 int ret, oldErrs;
10066 xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10067
10068 /*
10069 * Save old values; reset the *main* schema.
10070 * URGENT TODO: This is not good; move the per-document information
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000010071 * to the parser. Get rid of passing the main schema to the
10072 * parsing functions.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010073 */
10074 oldFlags = schema->flags;
10075 oldDoc = schema->doc;
10076 if (schema->flags != 0)
10077 xmlSchemaClearSchemaDefaults(schema);
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000010078 schema->doc = bucket->doc;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010079 pctxt->schema = schema;
10080 /*
10081 * Keep the current target namespace on the parser *not* on the
10082 * main schema.
10083 */
10084 pctxt->targetNamespace = bucket->targetNamespace;
10085 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010086
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010087 if ((bucket->targetNamespace != NULL) &&
10088 xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010089 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010090 * We are parsing the schema for schemas!
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010091 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010092 pctxt->isS4S = 1;
10093 }
10094 /* Mark it as parsed, even if parsing fails. */
10095 bucket->parsed++;
10096 /* Compile the schema doc. */
10097 node = xmlDocGetRootElement(bucket->doc);
10098 ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10099 if (ret != 0)
10100 goto exit;
10101 /* An empty schema; just get out. */
10102 if (node->children == NULL)
10103 goto exit;
10104 oldErrs = pctxt->nberrors;
10105 ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10106 if (ret != 0)
10107 goto exit;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010108 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010109 * TODO: Not nice, but I'm not 100% sure we will get always an error
10110 * as a result of the obove functions; so better rely on pctxt->err
10111 * as well.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010112 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010113 if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10114 ret = pctxt->err;
10115 goto exit;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010116 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010117
10118exit:
10119 WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10120 /* Restore schema values. */
10121 schema->doc = oldDoc;
10122 schema->flags = oldFlags;
10123 return(ret);
10124}
10125
10126static int
10127xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10128 xmlSchemaPtr schema,
10129 xmlSchemaBucketPtr bucket)
10130{
10131 xmlSchemaParserCtxtPtr newpctxt;
10132 int res = 0;
10133
10134 if (bucket == NULL)
10135 return(0);
10136 if (bucket->parsed) {
10137 PERROR_INT("xmlSchemaParseNewDoc",
10138 "reparsing a schema doc");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010139 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010140 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010141 if (bucket->doc == NULL) {
10142 PERROR_INT("xmlSchemaParseNewDoc",
10143 "parsing a schema doc, but there's no doc");
10144 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000010145 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010146 if (pctxt->constructor == NULL) {
10147 PERROR_INT("xmlSchemaParseNewDoc",
10148 "no constructor");
10149 return(-1);
10150 }
10151 /* Create and init the temporary parser context. */
10152 newpctxt = xmlSchemaNewParserCtxtUseDict(
10153 (const char *) bucket->schemaLocation, pctxt->dict);
10154 if (newpctxt == NULL)
10155 return(-1);
10156 newpctxt->constructor = pctxt->constructor;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010157 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010158 * TODO: Can we avoid that the parser knows about the main schema?
10159 * It would be better if he knows about the current schema bucket
10160 * only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010161 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010162 newpctxt->schema = schema;
10163 xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000010164 pctxt->errCtxt);
10165 xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10166 pctxt->errCtxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010167 newpctxt->counter = pctxt->counter;
10168
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010169
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010170 res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10171
10172 /* Channel back errors and cleanup the temporary parser context. */
10173 if (res != 0)
10174 pctxt->err = res;
10175 pctxt->nberrors += newpctxt->nberrors;
10176 pctxt->counter = newpctxt->counter;
10177 newpctxt->constructor = NULL;
10178 /* Free the parser context. */
10179 xmlSchemaFreeParserCtxt(newpctxt);
10180 return(res);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010181}
William M. Brack2f2a6632004-08-20 23:09:47 +000010182
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010183static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010184xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10185 xmlSchemaSchemaRelationPtr rel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010186{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010187 xmlSchemaSchemaRelationPtr cur = bucket->relations;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010188
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010189 if (cur == NULL) {
10190 bucket->relations = rel;
10191 return;
10192 }
10193 while (cur->next != NULL)
10194 cur = cur->next;
10195 cur->next = rel;
10196}
10197
10198
10199static const xmlChar *
10200xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10201 xmlNodePtr ctxtNode)
10202{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010203 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010204 * Build an absolue location URI.
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010205 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010206 if (location != NULL) {
10207 if (ctxtNode == NULL)
10208 return(location);
10209 else {
10210 xmlChar *base, *URI;
10211 const xmlChar *ret = NULL;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010212
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010213 base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10214 if (base == NULL) {
10215 URI = xmlBuildURI(location, ctxtNode->doc->URL);
10216 } else {
10217 URI = xmlBuildURI(location, base);
10218 xmlFree(base);
10219 }
10220 if (URI != NULL) {
10221 ret = xmlDictLookup(dict, URI, -1);
10222 xmlFree(URI);
10223 return(ret);
10224 }
10225 }
10226 }
10227 return(NULL);
10228}
10229
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010230
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010231
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010232/**
10233 * xmlSchemaAddSchemaDoc:
10234 * @pctxt: a schema validation context
10235 * @schema: the schema being built
10236 * @node: a subtree containing XML Schema informations
10237 *
10238 * Parse an included (and to-be-redefined) XML schema document.
10239 *
10240 * Returns 0 on success, a positive error code on errors and
10241 * -1 in case of an internal or API error.
10242 */
10243
10244static int
10245xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10246 int type, /* import or include or redefine */
10247 const xmlChar *schemaLocation,
10248 xmlDocPtr schemaDoc,
10249 const char *schemaBuffer,
10250 int schemaBufferLen,
10251 xmlNodePtr invokingNode,
10252 const xmlChar *sourceTargetNamespace,
10253 const xmlChar *importNamespace,
10254 xmlSchemaBucketPtr *bucket)
10255{
10256 const xmlChar *targetNamespace = NULL;
10257 xmlSchemaSchemaRelationPtr relation = NULL;
10258 xmlDocPtr doc = NULL;
10259 int res = 0, err = 0, located = 0, preserveDoc = 0;
10260 xmlSchemaBucketPtr bkt = NULL;
10261
10262 if (bucket != NULL)
10263 *bucket = NULL;
10264
10265 switch (type) {
10266 case XML_SCHEMA_SCHEMA_IMPORT:
10267 case XML_SCHEMA_SCHEMA_MAIN:
10268 err = XML_SCHEMAP_SRC_IMPORT;
10269 break;
10270 case XML_SCHEMA_SCHEMA_INCLUDE:
10271 err = XML_SCHEMAP_SRC_INCLUDE;
10272 break;
10273 case XML_SCHEMA_SCHEMA_REDEFINE:
10274 err = XML_SCHEMAP_SRC_REDEFINE;
10275 break;
10276 }
10277
10278
10279 /* Special handling for the main schema:
10280 * skip the location and relation logic and just parse the doc.
10281 * We need just a bucket to be returned in this case.
10282 */
10283 if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10284 goto doc_load;
10285
10286 /* Note that we expect the location to be an absulute URI. */
10287 if (schemaLocation != NULL) {
10288 bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10289 if ((bkt != NULL) &&
10290 (pctxt->constructor->bucket == bkt)) {
10291 /* Report self-imports/inclusions/redefinitions. */
10292
10293 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10294 invokingNode, NULL,
10295 "The schema must not import/include/redefine itself",
10296 NULL, NULL);
10297 goto exit;
10298 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010299 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010300 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010301 * Create a relation for the graph of schemas.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010302 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010303 relation = xmlSchemaSchemaRelationCreate();
10304 if (relation == NULL)
10305 return(-1);
10306 xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10307 relation);
10308 relation->type = type;
10309
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010310 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010311 * Save the namespace import information.
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010312 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010313 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010314 relation->importNamespace = importNamespace;
10315 if (schemaLocation == NULL) {
10316 /*
10317 * No location; this is just an import of the namespace.
10318 * Note that we don't assign a bucket to the relation
10319 * in this case.
10320 */
10321 goto exit;
10322 }
10323 targetNamespace = importNamespace;
10324 }
10325
10326 /* Did we already fetch the doc? */
10327 if (bkt != NULL) {
10328 /* TODO: The following nasty cases will produce an error. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010329 if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010330 /* We included/redefined and then try to import a schema. */
10331 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10332 invokingNode, NULL,
10333 "The schema document '%s' cannot be imported, since "
10334 "it was already included or redefined",
10335 schemaLocation, NULL);
10336 goto exit;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010337 } else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010338 /* We imported and then try to include/redefine a schema. */
10339 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10340 invokingNode, NULL,
10341 "The schema document '%s' cannot be included or "
10342 "redefined, since it was already imported",
10343 schemaLocation, NULL);
10344 goto exit;
10345 }
10346 }
10347
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010348 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010349 /*
10350 * Given that the schemaLocation [attribute] is only a hint, it is open
10351 * to applications to ignore all but the first <import> for a given
10352 * namespace, regardless of the ·actual value· of schemaLocation, but
10353 * such a strategy risks missing useful information when new
10354 * schemaLocations are offered.
10355 *
10356 * We will use the first <import> that comes with a location.
10357 * Further <import>s *with* a location, will result in an error.
10358 * TODO: Better would be to just report a warning here, but
10359 * we'll try it this way until someone complains.
10360 *
10361 * Schema Document Location Strategy:
10362 * 3 Based on the namespace name, identify an existing schema document,
10363 * either as a resource which is an XML document or a <schema> element
10364 * information item, in some local schema repository;
10365 * 5 Attempt to resolve the namespace name to locate such a resource.
10366 *
10367 * NOTE: (3) and (5) are not supported.
10368 */
10369 if (bkt != NULL) {
10370 relation->bucket = bkt;
10371 goto exit;
10372 }
10373 bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10374 importNamespace, 1);
10375
10376 if (bkt != NULL) {
10377 relation->bucket = bkt;
10378 if (bkt->schemaLocation == NULL) {
10379 /* First given location of the schema; load the doc. */
10380 bkt->schemaLocation = schemaLocation;
10381 } else {
10382 if (!xmlStrEqual(schemaLocation,
10383 bkt->schemaLocation)) {
10384 /*
10385 * Additional location given; just skip it.
10386 * URGENT TODO: We should report a warning here.
10387 * res = XML_SCHEMAP_SRC_IMPORT;
10388 */
10389 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10390 XML_SCHEMAP_WARN_SKIP_SCHEMA,
10391 invokingNode, NULL,
10392 "Skipping import of schema located at '%s' for the "
10393 "namespace '%s', since this namespace was already "
10394 "imported with the schema located at '%s'",
10395 schemaLocation, importNamespace, bkt->schemaLocation);
10396 }
10397 goto exit;
10398 }
10399 }
10400 /*
10401 * No bucket + first location: load the doc and create a
10402 * bucket.
10403 */
10404 } else {
10405 /* <include> and <redefine> */
10406 if (bkt != NULL) {
10407
10408 if ((bkt->origTargetNamespace == NULL) &&
10409 (bkt->targetNamespace != sourceTargetNamespace)) {
10410 xmlSchemaBucketPtr chamel;
10411
10412 /*
10413 * Chameleon include/redefine: skip loading only if it was
10414 * aleady build for the targetNamespace of the including
10415 * schema.
10416 */
10417 /*
10418 * URGENT TODO: If the schema is a chameleon-include then copy
10419 * the components into the including schema and modify the
10420 * targetNamespace of those components, do nothing otherwise.
10421 * NOTE: This is currently worked-around by compiling the
10422 * chameleon for every destinct including targetNamespace; thus
10423 * not performant at the moment.
10424 * TODO: Check when the namespace in wildcards for chameleons
10425 * needs to be converted: before we built wildcard intersections
10426 * or after.
10427 * Answer: after!
10428 */
10429 chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10430 schemaLocation, sourceTargetNamespace);
10431 if (chamel != NULL) {
10432 /* A fitting chameleon was already parsed; NOP. */
10433 relation->bucket = chamel;
10434 goto exit;
10435 }
10436 /*
10437 * We need to parse the chameleon again for a different
10438 * targetNamespace.
10439 * CHAMELEON TODO: Optimize this by only parsing the
10440 * chameleon once, and then copying the components to
10441 * the new targetNamespace.
10442 */
10443 bkt = NULL;
10444 } else {
10445 relation->bucket = bkt;
10446 goto exit;
10447 }
10448 }
10449 }
10450 if ((bkt != NULL) && (bkt->doc != NULL)) {
10451 PERROR_INT("xmlSchemaAddSchemaDoc",
10452 "trying to load a schema doc, but a doc is already "
10453 "assigned to the schema bucket");
10454 goto exit_failure;
10455 }
10456
10457doc_load:
10458 /*
10459 * Load the document.
10460 */
10461 if (schemaDoc != NULL) {
10462 doc = schemaDoc;
10463 /* Don' free this one, since it was provided by the caller. */
10464 preserveDoc = 1;
10465 /* TODO: Does the context or the doc hold the location? */
10466 if (schemaDoc->URL != NULL)
10467 schemaLocation = xmlDictLookup(pctxt->dict,
10468 schemaDoc->URL, -1);
10469
10470 } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10471 xmlParserCtxtPtr parserCtxt;
10472
10473 parserCtxt = xmlNewParserCtxt();
10474 if (parserCtxt == NULL) {
10475 xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10476 "allocating a parser context", NULL);
10477 goto exit_failure;
10478 }
10479 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10480 /*
10481 * TODO: Do we have to burden the schema parser dict with all
10482 * the content of the schema doc?
10483 */
10484 xmlDictFree(parserCtxt->dict);
10485 parserCtxt->dict = pctxt->dict;
10486 xmlDictReference(parserCtxt->dict);
10487 }
10488 if (schemaLocation != NULL) {
10489 /* Parse from file. */
10490 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10491 NULL, SCHEMAS_PARSE_OPTIONS);
10492 } else if (schemaBuffer != NULL) {
10493 /* Parse from memory buffer. */
10494 doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10495 NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10496 schemaLocation = xmlStrdup(BAD_CAST "in_memory_buffer");
10497 if (doc != NULL)
10498 doc->URL = schemaLocation;
10499 }
10500 /*
10501 * For <import>:
10502 * 2.1 The referent is (a fragment of) a resource which is an
10503 * XML document (see clause 1.1), which in turn corresponds to
10504 * a <schema> element information item in a well-formed information
10505 * set, which in turn corresponds to a valid schema.
10506 * TODO: (2.1) fragments of XML documents are not supported.
10507 *
10508 * 2.2 The referent is a <schema> element information item in
10509 * a well-formed information set, which in turn corresponds
10510 * to a valid schema.
10511 * TODO: (2.2) is not supported.
10512 */
10513 if (doc == NULL) {
10514 xmlErrorPtr lerr;
10515 lerr = xmlGetLastError();
10516 /*
10517 * Check if this a parser error, or if the document could
10518 * just not be located.
10519 * TODO: Try to find specific error codes to react only on
10520 * localisation failures.
10521 */
10522 if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10523 /*
10524 * We assume a parser error here.
10525 */
10526 located = 1;
10527 /* TODO: Error code ?? */
10528 res = XML_SCHEMAP_SRC_IMPORT_2_1;
10529 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10530 invokingNode, NULL,
10531 "Failed to parse the XML resource '%s'",
10532 schemaLocation, NULL);
10533 }
10534 }
10535 xmlFreeParserCtxt(parserCtxt);
10536 if ((doc == NULL) && located)
10537 goto exit_error;
10538 } else {
10539 xmlSchemaPErr(pctxt, NULL,
10540 XML_SCHEMAP_NOTHING_TO_PARSE,
10541 "No information for parsing was provided with the "
10542 "given schema parser context.\n",
10543 NULL, NULL);
10544 goto exit_failure;
10545 }
10546 /*
10547 * Preprocess the document.
10548 */
10549 if (doc != NULL) {
10550 xmlNodePtr docElem = NULL;
10551
10552 located = 1;
10553 docElem = xmlDocGetRootElement(doc);
10554 if (docElem == NULL) {
10555 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10556 invokingNode, NULL,
10557 "The document '%s' has no document element",
10558 schemaLocation, NULL);
10559 xmlFreeDoc(doc);
10560 doc = NULL;
10561 goto exit_error;
10562 }
10563 /*
10564 * Remove all the blank text nodes.
10565 */
10566 xmlSchemaCleanupDoc(pctxt, docElem);
10567 /*
10568 * Check the schema's top level element.
10569 */
10570 if (!IS_SCHEMA(docElem, "schema")) {
10571 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10572 invokingNode, NULL,
10573 "The XML document '%s' is not a schema document",
10574 schemaLocation, NULL);
10575 xmlFreeDoc(doc);
10576 doc = NULL;
10577 goto exit_error;
10578 }
10579 /*
10580 * Note that we don't apply a type check for the
10581 * targetNamespace value here.
10582 */
10583 targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10584 "targetNamespace");
10585 }
10586
10587/* after_doc_loading: */
10588 if ((bkt == NULL) && located) {
10589 /* Only create a bucket if the schema was located. */
10590 bkt = xmlSchemaBucketCreate(pctxt, type,
10591 targetNamespace);
10592 if (bkt == NULL)
10593 goto exit_failure;
10594 }
10595 if (bkt != NULL) {
10596 bkt->schemaLocation = schemaLocation;
10597 bkt->located = located;
10598 if (doc != NULL) {
10599 bkt->doc = doc;
10600 bkt->targetNamespace = targetNamespace;
10601 bkt->origTargetNamespace = targetNamespace;
10602 if (preserveDoc)
10603 bkt->preserveDoc = 1;
10604 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010605 if (WXS_IS_BUCKET_IMPMAIN(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010606 bkt->imported++;
10607 /*
10608 * Add it to the graph of schemas.
10609 */
10610 if (relation != NULL)
10611 relation->bucket = bkt;
10612 }
10613
10614exit:
10615 /*
10616 * Return the bucket explicitely; this is needed for the
10617 * main schema.
10618 */
10619 if (bucket != NULL)
10620 *bucket = bkt;
10621 return (0);
10622
10623exit_error:
10624 if ((doc != NULL) && (! preserveDoc)) {
10625 xmlFreeDoc(doc);
10626 if (bkt != NULL)
10627 bkt->doc = NULL;
10628 }
10629 return(pctxt->err);
10630
10631exit_failure:
10632 if ((doc != NULL) && (! preserveDoc)) {
10633 xmlFreeDoc(doc);
10634 if (bkt != NULL)
10635 bkt->doc = NULL;
10636 }
10637 return (-1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010638}
10639
William M. Brack2f2a6632004-08-20 23:09:47 +000010640/**
10641 * xmlSchemaParseImport:
10642 * @ctxt: a schema validation context
10643 * @schema: the schema being built
10644 * @node: a subtree containing XML Schema informations
10645 *
10646 * parse a XML schema Import definition
10647 * *WARNING* this interface is highly subject to change
10648 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010649 * Returns 0 in case of success, a positive error code if
10650 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +000010651 */
10652static int
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010653xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +000010654 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010655{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010656 xmlNodePtr child;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010657 const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10658 const xmlChar *thisTargetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +000010659 xmlAttrPtr attr;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010660 int ret = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010661 xmlSchemaBucketPtr bucket = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000010662
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010663 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
William M. Brack2f2a6632004-08-20 23:09:47 +000010664 return (-1);
10665
10666 /*
10667 * Check for illegal attributes.
10668 */
10669 attr = node->properties;
10670 while (attr != NULL) {
10671 if (attr->ns == NULL) {
10672 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10673 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10674 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010675 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010676 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010677 }
10678 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010679 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010680 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010681 }
10682 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010683 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010684 /*
10685 * Extract and validate attributes.
10686 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010687 if (xmlSchemaPValAttr(pctxt, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010688 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010689 &namespaceName) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010690 xmlSchemaPSimpleTypeErr(pctxt,
10691 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010692 NULL, node,
10693 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010694 NULL, namespaceName, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010695 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010696 }
10697
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010698 if (xmlSchemaPValAttr(pctxt, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010699 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +000010700 &schemaLocation) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010701 xmlSchemaPSimpleTypeErr(pctxt,
10702 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010703 NULL, node,
10704 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010705 NULL, namespaceName, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010706 return (pctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010707 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010708 /*
10709 * And now for the children...
10710 */
10711 child = node->children;
10712 if (IS_SCHEMA(child, "annotation")) {
10713 /*
10714 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010715 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +000010716 */
10717 child = child->next;
10718 }
10719 if (child != NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010720 xmlSchemaPContentErr(pctxt,
10721 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010722 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010723 "(annotation?)");
10724 }
10725 /*
10726 * Apply additional constraints.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010727 *
10728 * Note that it is important to use the original @targetNamespace
10729 * (or none at all), to rule out imports of schemas _with_ a
10730 * @targetNamespace if the importing schema is a chameleon schema
10731 * (with no @targetNamespace).
William M. Brack2f2a6632004-08-20 23:09:47 +000010732 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010733 thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010734 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000010735 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010736 * 1.1 If the namespace [attribute] is present, then its ·actual value·
10737 * must not match the ·actual value· of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +000010738 * targetNamespace [attribute].
10739 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010740 if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010741 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000010742 XML_SCHEMAP_SRC_IMPORT_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010743 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +000010744 "The value of the attribute 'namespace' must not match "
10745 "the target namespace '%s' of the importing schema",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010746 thisTargetNamespace);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010747 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010748 }
10749 } else {
10750 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010751 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +000010752 * <schema> must have a targetNamespace [attribute].
10753 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010754 if (thisTargetNamespace == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010755 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000010756 XML_SCHEMAP_SRC_IMPORT_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010757 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +000010758 "The attribute 'namespace' must be existent if "
10759 "the importing schema has no target namespace",
10760 NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010761 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010762 }
10763 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010764 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000010765 * Locate and acquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +000010766 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010767 if (schemaLocation != NULL)
10768 schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10769 schemaLocation, node);
10770 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010771 schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010772 namespaceName, &bucket);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010773
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010774 if (ret != 0)
10775 return(ret);
10776
10777 /*
10778 * For <import>: "It is *not* an error for the application
10779 * schema reference strategy to fail."
10780 * So just don't parse if no schema document was found.
10781 * Note that we will get no bucket if the schema could not be
10782 * located or if there was no schemaLocation.
10783 */
10784 if ((bucket == NULL) && (schemaLocation != NULL)) {
10785 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10786 XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10787 node, NULL,
10788 "Failed to locate a schema at location '%s'. "
10789 "Skipping the import", schemaLocation, NULL, NULL);
10790 }
10791
10792 if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10793 ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10794 }
10795
10796 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000010797}
10798
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010799static int
10800xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10801 xmlSchemaPtr schema,
10802 xmlNodePtr node,
10803 xmlChar **schemaLocation,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010804 int type)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010805{
10806 xmlAttrPtr attr;
10807
10808 if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10809 (schemaLocation == NULL))
10810 return (-1);
10811
10812 *schemaLocation = NULL;
10813 /*
10814 * Check for illegal attributes.
10815 * Applies for both <include> and <redefine>.
10816 */
10817 attr = node->properties;
10818 while (attr != NULL) {
10819 if (attr->ns == NULL) {
10820 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10821 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10822 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010823 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010824 }
10825 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10826 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010827 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010828 }
10829 attr = attr->next;
10830 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010831 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010832 /*
10833 * Preliminary step, extract the URI-Reference and make an URI
10834 * from the base.
10835 */
10836 /*
10837 * Attribute "schemaLocation" is mandatory.
10838 */
10839 attr = xmlSchemaGetPropNode(node, "schemaLocation");
10840 if (attr != NULL) {
10841 xmlChar *base = NULL;
10842 xmlChar *uri = NULL;
10843
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010844 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010845 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10846 (const xmlChar **) schemaLocation) != 0)
10847 goto exit_error;
10848 base = xmlNodeGetBase(node->doc, node);
10849 if (base == NULL) {
10850 uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10851 } else {
10852 uri = xmlBuildURI(*schemaLocation, base);
10853 xmlFree(base);
10854 }
10855 if (uri == NULL) {
10856 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10857 "could not build an URI from the schemaLocation")
10858 goto exit_failure;
10859 }
10860 (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10861 xmlFree(uri);
10862 } else {
10863 xmlSchemaPMissingAttrErr(pctxt,
10864 XML_SCHEMAP_S4S_ATTR_MISSING,
10865 NULL, node, "schemaLocation", NULL);
10866 goto exit_error;
10867 }
10868 /*
10869 * Report self-inclusion and self-redefinition.
10870 */
10871 if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010872 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010873 xmlSchemaPCustomErr(pctxt,
10874 XML_SCHEMAP_SRC_REDEFINE,
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 redefine itself.",
10877 *schemaLocation);
10878 } else {
10879 xmlSchemaPCustomErr(pctxt,
10880 XML_SCHEMAP_SRC_INCLUDE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010881 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010882 "The schema document '%s' cannot include itself.",
10883 *schemaLocation);
10884 }
10885 goto exit_error;
10886 }
10887
10888 return(0);
10889exit_error:
10890 return(pctxt->err);
10891exit_failure:
10892 return(-1);
10893}
10894
10895static int
10896xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10897 xmlSchemaPtr schema,
10898 xmlNodePtr node,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010899 int type)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010900{
10901 xmlNodePtr child = NULL;
10902 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000010903 int res = 0; /* hasRedefinitions = 0 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010904 int isChameleon = 0, wasChameleon = 0;
10905 xmlSchemaBucketPtr bucket = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010906
10907 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10908 return (-1);
10909
10910 /*
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010911 * Parse attributes. Note that the returned schemaLocation will
10912 * be already converted to an absolute URI.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010913 */
10914 res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010915 node, (xmlChar **) (&schemaLocation), type);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010916 if (res != 0)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010917 return(res);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010918 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010919 * Load and add the schema document.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010920 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010921 res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10922 NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010923 if (res != 0)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010924 return(res);
10925 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010926 * If we get no schema bucket back, then this means that the schema
10927 * document could not be located or was broken XML or was not
10928 * a schema document.
10929 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010930 if ((bucket == NULL) || (bucket->doc == NULL)) {
10931 if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10932 /*
10933 * WARNING for <include>:
10934 * We will raise an error if the schema cannot be located
10935 * for inclusions, since the that was the feedback from the
10936 * schema people. I.e. the following spec piece will *not* be
10937 * satisfied:
10938 * SPEC src-include: "It is not an error for the ·actual value· of the
10939 * schemaLocation [attribute] to fail to resolve it all, in which
10940 * case no corresponding inclusion is performed.
10941 * So do we need a warning report here?"
10942 */
10943 res = XML_SCHEMAP_SRC_INCLUDE;
10944 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10945 node, NULL,
10946 "Failed to load the document '%s' for inclusion",
10947 schemaLocation, NULL);
10948 } else {
10949 /*
10950 * NOTE: This was changed to raise an error even if no redefinitions
10951 * are specified.
10952 *
10953 * SPEC src-redefine (1)
10954 * "If there are any element information items among the [children]
10955 * other than <annotation> then the ·actual value· of the
10956 * schemaLocation [attribute] must successfully resolve."
10957 * TODO: Ask the WG if a the location has always to resolve
10958 * here as well!
10959 */
10960 res = XML_SCHEMAP_SRC_REDEFINE;
10961 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10962 node, NULL,
10963 "Failed to load the document '%s' for redefinition",
10964 schemaLocation, NULL);
10965 }
10966 } else {
10967 /*
10968 * Check targetNamespace sanity before parsing the new schema.
10969 * TODO: Note that we won't check further content if the
10970 * targetNamespace was bad.
10971 */
10972 if (bucket->origTargetNamespace != NULL) {
10973 /*
10974 * SPEC src-include (2.1)
10975 * "SII has a targetNamespace [attribute], and its ·actual
10976 * value· is identical to the ·actual value· of the targetNamespace
10977 * [attribute] of SIIÂ’ (which must have such an [attribute])."
10978 */
10979 if (pctxt->targetNamespace == NULL) {
10980 xmlSchemaCustomErr(ACTXT_CAST pctxt,
10981 XML_SCHEMAP_SRC_INCLUDE,
10982 node, NULL,
10983 "The target namespace of the included/redefined schema "
10984 "'%s' has to be absent, since the including/redefining "
10985 "schema has no target namespace",
10986 schemaLocation, NULL);
10987 goto exit_error;
10988 } else if (!xmlStrEqual(bucket->origTargetNamespace,
10989 pctxt->targetNamespace)) {
10990 /* TODO: Change error function. */
10991 xmlSchemaPCustomErrExt(pctxt,
10992 XML_SCHEMAP_SRC_INCLUDE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010993 NULL, node,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010994 "The target namespace '%s' of the included/redefined "
10995 "schema '%s' differs from '%s' of the "
10996 "including/redefining schema",
10997 bucket->origTargetNamespace, schemaLocation,
10998 pctxt->targetNamespace);
10999 goto exit_error;
11000 }
11001 } else if (pctxt->targetNamespace != NULL) {
11002 /*
11003 * Chameleons: the original target namespace will
11004 * differ from the resulting namespace.
11005 */
11006 isChameleon = 1;
11007 if (bucket->parsed &&
11008 (bucket->targetNamespace != pctxt->targetNamespace)) {
11009 /*
11010 * This is a sanity check, I dunno yet if this can happen.
11011 */
11012 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
11013 "trying to use an already parsed schema for a "
11014 "different targetNamespace");
11015 return(-1);
11016 }
11017 bucket->targetNamespace = pctxt->targetNamespace;
11018 }
11019 }
11020 /*
11021 * Parse the schema.
11022 */
11023 if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11024 if (isChameleon) {
11025 /* TODO: Get rid of this flag on the schema itself. */
11026 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11027 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11028 } else
11029 wasChameleon = 1;
11030 }
11031 xmlSchemaParseNewDoc(pctxt, schema, bucket);
11032 /* Restore chameleon flag. */
11033 if (isChameleon && (!wasChameleon))
11034 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11035 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011036 /*
11037 * And now for the children...
11038 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011039 child = node->children;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011040 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011041 /*
11042 * Parse (simpleType | complexType | group | attributeGroup))*
11043 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011044 pctxt->redefined = bucket;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011045 /*
11046 * How to proceed if the redefined schema was not located?
11047 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011048 pctxt->isRedefine = 1;
11049 while (IS_SCHEMA(child, "annotation") ||
11050 IS_SCHEMA(child, "simpleType") ||
11051 IS_SCHEMA(child, "complexType") ||
11052 IS_SCHEMA(child, "group") ||
11053 IS_SCHEMA(child, "attributeGroup")) {
11054 if (IS_SCHEMA(child, "annotation")) {
11055 /*
11056 * TODO: discard or not?
11057 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011058 } else if (IS_SCHEMA(child, "simpleType")) {
11059 xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11060 } else if (IS_SCHEMA(child, "complexType")) {
11061 xmlSchemaParseComplexType(pctxt, schema, child, 1);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011062 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011063 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011064 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011065 xmlSchemaParseModelGroupDefinition(pctxt,
11066 schema, child);
11067 } else if (IS_SCHEMA(child, "attributeGroup")) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011068 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011069 xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11070 child);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011071 }
11072 child = child->next;
11073 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011074 pctxt->redefined = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011075 pctxt->isRedefine = 0;
11076 } else {
11077 if (IS_SCHEMA(child, "annotation")) {
11078 /*
11079 * TODO: discard or not?
11080 */
11081 child = child->next;
11082 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011083 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011084 if (child != NULL) {
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011085 res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011086 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11087 xmlSchemaPContentErr(pctxt, res,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011088 NULL, node, child, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011089 "(annotation | (simpleType | complexType | group | attributeGroup))*");
11090 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011091 xmlSchemaPContentErr(pctxt, res,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011092 NULL, node, child, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011093 "(annotation?)");
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011094 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011095 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011096 return(res);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011097
11098exit_error:
11099 return(pctxt->err);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011100}
11101
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011102static int
11103xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11104 xmlNodePtr node)
11105{
11106 int res;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011107#ifndef ENABLE_REDEFINE
11108 TODO
11109 return(0);
11110#endif
11111 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11112 XML_SCHEMA_SCHEMA_REDEFINE);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011113 if (res != 0)
11114 return(res);
11115 return(0);
11116}
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011117
11118static int
11119xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11120 xmlNodePtr node)
11121{
11122 int res;
11123
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011124 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11125 XML_SCHEMA_SCHEMA_INCLUDE);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011126 if (res != 0)
11127 return(res);
11128 return(0);
11129}
11130
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011131/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011132 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011133 * @ctxt: a schema validation context
11134 * @schema: the schema being built
11135 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011136 * @type: the "compositor" type
11137 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +000011138 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011139 * parse a XML schema Sequence definition.
11140 * Applies parts of:
11141 * Schema Representation Constraint:
11142 * Redefinition Constraints and Semantics (src-redefine)
11143 * (6.1), (6.1.1), (6.1.2)
11144 *
11145 * Schema Component Constraint:
11146 * All Group Limited (cos-all-limited) (2)
11147 * TODO: Actually this should go to component-level checks,
11148 * but is done here due to performance. Move it to an other layer
11149 * is schema construction via an API is implemented.
11150 *
Daniel Veillard4255d502002-04-16 15:50:10 +000011151 * *WARNING* this interface is highly subject to change
11152 *
William M. Bracke7091952004-05-11 15:09:58 +000011153 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +000011154 * 1 in case of success.
11155 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011156static xmlSchemaTreeItemPtr
11157xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11158 xmlNodePtr node, xmlSchemaTypeType type,
11159 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +000011160{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011161 xmlSchemaModelGroupPtr item;
11162 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011163 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000011164 xmlAttrPtr attr;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011165 int min = 1, max = 1, isElemRef, hasRefs = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000011166
11167 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011168 return (NULL);
11169 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011170 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +000011171 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011172 item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011173 if (item == NULL)
11174 return (NULL);
11175
11176 if (withParticle) {
11177 if (type == XML_SCHEMA_TYPE_ALL) {
11178 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011179 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011180 } else {
11181 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011182 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11183 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11184 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011185 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011186 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11187 /*
11188 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011189 */
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000011190 particle = xmlSchemaAddParticle(ctxt, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011191 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011192 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011193 particle->children = (xmlSchemaTreeItemPtr) item;
11194 /*
11195 * Check for illegal attributes.
11196 */
11197 attr = node->properties;
11198 while (attr != NULL) {
11199 if (attr->ns == NULL) {
11200 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11201 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11202 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011203 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011204 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011205 }
11206 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011207 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011208 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011209 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011210 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000011211 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011212 } else {
11213 /*
11214 * Check for illegal attributes.
11215 */
11216 attr = node->properties;
11217 while (attr != NULL) {
11218 if (attr->ns == NULL) {
11219 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011220 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011221 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011222 }
11223 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011224 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011225 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011226 }
11227 attr = attr->next;
11228 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011229 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011230
William M. Brack2f2a6632004-08-20 23:09:47 +000011231 /*
11232 * Extract and validate attributes.
11233 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011234 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000011235 /*
11236 * And now for the children...
11237 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011238 child = node->children;
11239 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000011240 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011241 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011242 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011243 if (type == XML_SCHEMA_TYPE_ALL) {
11244 xmlSchemaParticlePtr part, last = NULL;
11245
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011246 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011247 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011248 schema, child, &isElemRef, 0);
11249 /*
11250 * SPEC cos-all-limited (2)
11251 * "The {max occurs} of all the particles in the {particles}
11252 * of the ('all') group must be 0 or 1.
11253 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011254 if (part != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011255 if (isElemRef)
11256 hasRefs++;
11257 if (part->minOccurs > 1) {
11258 xmlSchemaPCustomErr(ctxt,
11259 XML_SCHEMAP_COS_ALL_LIMITED,
11260 NULL, child,
11261 "Invalid value for minOccurs (must be 0 or 1)",
11262 NULL);
11263 /* Reset to 1. */
11264 part->minOccurs = 1;
11265 }
11266 if (part->maxOccurs > 1) {
11267 xmlSchemaPCustomErr(ctxt,
11268 XML_SCHEMAP_COS_ALL_LIMITED,
11269 NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011270 "Invalid value for maxOccurs (must be 0 or 1)",
11271 NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011272 /* Reset to 1. */
11273 part->maxOccurs = 1;
11274 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011275 if (last == NULL)
11276 item->children = (xmlSchemaTreeItemPtr) part;
11277 else
11278 last->next = (xmlSchemaTreeItemPtr) part;
11279 last = part;
11280 }
11281 child = child->next;
11282 }
11283 if (child != NULL) {
11284 xmlSchemaPContentErr(ctxt,
11285 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011286 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011287 "(annotation?, (annotation?, element*)");
11288 }
11289 } else {
11290 /* choice + sequence */
11291 xmlSchemaTreeItemPtr part = NULL, last = NULL;
11292
11293 while ((IS_SCHEMA(child, "element")) ||
11294 (IS_SCHEMA(child, "group")) ||
11295 (IS_SCHEMA(child, "any")) ||
11296 (IS_SCHEMA(child, "choice")) ||
11297 (IS_SCHEMA(child, "sequence"))) {
11298
11299 if (IS_SCHEMA(child, "element")) {
11300 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011301 xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11302 if (part && isElemRef)
11303 hasRefs++;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011304 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011305 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011306 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011307 if (part != NULL)
11308 hasRefs++;
11309 /*
11310 * Handle redefinitions.
11311 */
11312 if (ctxt->isRedefine && ctxt->redef &&
11313 (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11314 part && part->children)
11315 {
11316 if ((xmlSchemaGetQNameRefName(part->children) ==
11317 ctxt->redef->refName) &&
11318 (xmlSchemaGetQNameRefTargetNs(part->children) ==
11319 ctxt->redef->refTargetNs))
11320 {
11321 /*
11322 * SPEC src-redefine:
11323 * (6.1) "If it has a <group> among its contents at
11324 * some level the ·actual value· of whose ref
11325 * [attribute] is the same as the ·actual value· of
11326 * its own name attribute plus target namespace, then
11327 * all of the following must be true:"
11328 * (6.1.1) "It must have exactly one such group."
11329 */
11330 if (ctxt->redefCounter != 0) {
11331 xmlChar *str = NULL;
11332
11333 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11334 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11335 "The redefining model group definition "
11336 "'%s' must not contain more than one "
11337 "reference to the redefined definition",
11338 xmlSchemaFormatQName(&str,
11339 ctxt->redef->refTargetNs,
11340 ctxt->redef->refName),
11341 NULL);
11342 FREE_AND_NULL(str)
11343 part = NULL;
11344 } else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11345 ((WXS_PARTICLE(part))->maxOccurs != 1))
11346 {
11347 xmlChar *str = NULL;
11348 /*
11349 * SPEC src-redefine:
11350 * (6.1.2) "The ·actual value· of both that
11351 * group's minOccurs and maxOccurs [attribute]
11352 * must be 1 (or ·absent·).
11353 */
11354 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11355 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11356 "The redefining model group definition "
11357 "'%s' must not contain a reference to the "
11358 "redefined definition with a "
11359 "maxOccurs/minOccurs other than 1",
11360 xmlSchemaFormatQName(&str,
11361 ctxt->redef->refTargetNs,
11362 ctxt->redef->refName),
11363 NULL);
11364 FREE_AND_NULL(str)
11365 part = NULL;
11366 }
11367 ctxt->redef->reference = WXS_BASIC_CAST part;
11368 ctxt->redefCounter++;
11369 }
11370 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011371 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011372 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011373 xmlSchemaParseAny(ctxt, schema, child);
11374 } else if (IS_SCHEMA(child, "choice")) {
11375 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11376 XML_SCHEMA_TYPE_CHOICE, 1);
11377 } else if (IS_SCHEMA(child, "sequence")) {
11378 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11379 XML_SCHEMA_TYPE_SEQUENCE, 1);
11380 }
11381 if (part != NULL) {
11382 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011383 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011384 else
11385 last->next = part;
11386 last = part;
11387 }
11388 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011389 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011390 if (child != NULL) {
11391 xmlSchemaPContentErr(ctxt,
11392 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011393 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011394 "(annotation?, (element | group | choice | sequence | any)*)");
11395 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011396 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011397 if ((max == 0) && (min == 0))
11398 return (NULL);
11399 if (hasRefs) {
11400 /*
11401 * We need to resolve references.
11402 */
11403 WXS_ADD_PENDING(ctxt, item);
11404 }
11405 if (withParticle)
11406 return ((xmlSchemaTreeItemPtr) particle);
11407 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011408 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +000011409}
11410
11411/**
11412 * xmlSchemaParseRestriction:
11413 * @ctxt: a schema validation context
11414 * @schema: the schema being built
11415 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +000011416 *
11417 * parse a XML schema Restriction definition
11418 * *WARNING* this interface is highly subject to change
11419 *
11420 * Returns the type definition or NULL in case of error
11421 */
11422static xmlSchemaTypePtr
11423xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011424 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000011425{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011426 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011427 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000011428 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011429
11430 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11431 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011432 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011433 type = ctxt->ctxtType;
11434 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011435
11436 /*
William M. Brack2f2a6632004-08-20 23:09:47 +000011437 * Check for illegal attributes.
11438 */
11439 attr = node->properties;
11440 while (attr != NULL) {
11441 if (attr->ns == NULL) {
11442 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11443 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011444 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011445 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011446 }
11447 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011448 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011449 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011450 }
11451 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011452 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011453 /*
11454 * Extract and validate attributes.
11455 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011456 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000011457 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011458 * Attribute
William M. Brack2f2a6632004-08-20 23:09:47 +000011459 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011460 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011461 * Extract the base type. The "base" attribute is mandatory if inside
11462 * a complex type or if redefining.
11463 *
11464 * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011465 * among its [children]), the simple type definition which is
11466 * the {content type} of the type definition ·resolved· to by
11467 * the ·actual value· of the base [attribute]"
11468 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011469 if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011470 &(type->baseNs), &(type->base)) == 0)
11471 {
11472 if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11473 xmlSchemaPMissingAttrErr(ctxt,
11474 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011475 NULL, node, "base", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011476 } else if ((ctxt->isRedefine) &&
11477 (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11478 {
11479 if (type->base == NULL) {
11480 xmlSchemaPMissingAttrErr(ctxt,
11481 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011482 NULL, node, "base", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011483 } else if ((! xmlStrEqual(type->base, type->name)) ||
11484 (! xmlStrEqual(type->baseNs, type->targetNamespace)))
11485 {
11486 xmlChar *str1 = NULL, *str2 = NULL;
11487 /*
11488 * REDEFINE: SPEC src-redefine (5)
11489 * "Within the [children], each <simpleType> must have a
11490 * <restriction> among its [children] ... the ·actual value· of
11491 * whose base [attribute] must be the same as the ·actual value·
11492 * of its own name attribute plus target namespace;"
11493 */
11494 xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011495 NULL, node, "This is a redefinition, but the QName "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011496 "value '%s' of the 'base' attribute does not match the "
11497 "type's designation '%s'",
11498 xmlSchemaFormatQName(&str1, type->baseNs, type->base),
Daniel Veillardfef73a52006-03-27 09:38:57 +000011499 xmlSchemaFormatQName(&str2, type->targetNamespace,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011500 type->name), NULL);
11501 FREE_AND_NULL(str1);
11502 FREE_AND_NULL(str2);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011503 /* Avoid confusion and erase the values. */
11504 type->base = NULL;
11505 type->baseNs = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011506 }
11507 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011508 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011509 /*
11510 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011511 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011512 child = node->children;
11513 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011514 /*
11515 * Add the annotation to the simple type ancestor.
11516 */
11517 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000011518 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011519 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011520 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011521 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11522 /*
11523 * Corresponds to <simpleType><restriction><simpleType>.
11524 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011525 if (IS_SCHEMA(child, "simpleType")) {
11526 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011527 /*
William M. Brack2f2a6632004-08-20 23:09:47 +000011528 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011529 * Either the base [attribute] or the simpleType [child] of the
11530 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +000011531 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011532 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000011533 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011534 NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +000011535 "The attribute 'base' and the <simpleType> child are "
11536 "mutually exclusive", NULL);
11537 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011538 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +000011539 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011540 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011541 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011542 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011543 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011544 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011545 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011546 "Either the attribute 'base' or a <simpleType> child "
11547 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000011548 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011549 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11550 /*
11551 * Corresponds to <complexType><complexContent><restriction>...
11552 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011553 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011554 * Model groups <all>, <choice> and <sequence>.
11555 */
11556 if (IS_SCHEMA(child, "all")) {
11557 type->subtypes = (xmlSchemaTypePtr)
11558 xmlSchemaParseModelGroup(ctxt, schema, child,
11559 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011560 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011561 } else if (IS_SCHEMA(child, "choice")) {
11562 type->subtypes = (xmlSchemaTypePtr)
11563 xmlSchemaParseModelGroup(ctxt,
11564 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11565 child = child->next;
11566 } else if (IS_SCHEMA(child, "sequence")) {
11567 type->subtypes = (xmlSchemaTypePtr)
11568 xmlSchemaParseModelGroup(ctxt, schema, child,
11569 XML_SCHEMA_TYPE_SEQUENCE, 1);
11570 child = child->next;
11571 /*
11572 * Model group reference <group>.
11573 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011574 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011575 type->subtypes = (xmlSchemaTypePtr)
11576 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011577 /*
11578 * Note that the reference will be resolved in
11579 * xmlSchemaResolveTypeReferences();
11580 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011581 child = child->next;
11582 }
11583 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011584 /*
11585 * Corresponds to <complexType><simpleContent><restriction>...
11586 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011587 * "1.1 the simple type definition corresponding to the <simpleType>
11588 * among the [children] of <restriction> if there is one;"
11589 */
11590 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011591 /*
11592 * We will store the to-be-restricted simple type in
11593 * type->contentTypeDef *temporarily*.
11594 */
11595 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011596 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011597 if ( type->contentTypeDef == NULL)
11598 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011599 child = child->next;
11600 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011601 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011602
11603 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011604 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011605 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011606 /*
11607 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011608 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011609 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011610
Daniel Veillard01fa6152004-06-29 17:04:39 +000011611 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011612 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011613 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011614 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011615 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11616 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +000011617 * *Single Facet Value*
11618 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011619 while ((IS_SCHEMA(child, "minInclusive")) ||
11620 (IS_SCHEMA(child, "minExclusive")) ||
11621 (IS_SCHEMA(child, "maxInclusive")) ||
11622 (IS_SCHEMA(child, "maxExclusive")) ||
11623 (IS_SCHEMA(child, "totalDigits")) ||
11624 (IS_SCHEMA(child, "fractionDigits")) ||
11625 (IS_SCHEMA(child, "pattern")) ||
11626 (IS_SCHEMA(child, "enumeration")) ||
11627 (IS_SCHEMA(child, "whiteSpace")) ||
11628 (IS_SCHEMA(child, "length")) ||
11629 (IS_SCHEMA(child, "maxLength")) ||
11630 (IS_SCHEMA(child, "minLength"))) {
11631 facet = xmlSchemaParseFacet(ctxt, schema, child);
11632 if (facet != NULL) {
11633 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011634 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011635 else
11636 lastfacet->next = facet;
11637 lastfacet = facet;
11638 lastfacet->next = NULL;
11639 }
11640 child = child->next;
11641 }
11642 /*
11643 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011644 */
11645 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011646 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11647
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011648 facet = type->facets;
11649 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011650 facetLink = (xmlSchemaFacetLinkPtr)
11651 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +000011652 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011653 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011654 xmlFree(facetLink);
11655 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011656 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011657 facetLink->facet = facet;
11658 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011659 if (lastFacetLink == NULL)
11660 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011661 else
11662 lastFacetLink->next = facetLink;
11663 lastFacetLink = facetLink;
11664 facet = facet->next;
11665 } while (facet != NULL);
11666 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011667 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011668 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11669 /*
11670 * Attribute uses/declarations.
11671 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011672 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11673 (xmlSchemaItemListPtr *) &(type->attrUses),
11674 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11675 return(NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011676 /*
11677 * Attribute wildcard.
11678 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011679 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011680 type->attributeWildcard =
11681 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011682 child = child->next;
11683 }
11684 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011685 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011686 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11687 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?, (group | all | choice | sequence)?, "
11691 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011692 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011693 xmlSchemaPContentErr(ctxt,
11694 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011695 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011696 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11697 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11698 "length | minLength | maxLength | enumeration | whiteSpace | "
11699 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11700 } else {
11701 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011702 xmlSchemaPContentErr(ctxt,
11703 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011704 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011705 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11706 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11707 "length | minLength | maxLength | enumeration | whiteSpace | "
11708 "pattern)*))");
11709 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011710 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011711 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011712}
11713
11714/**
11715 * xmlSchemaParseExtension:
11716 * @ctxt: a schema validation context
11717 * @schema: the schema being built
11718 * @node: a subtree containing XML Schema informations
11719 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011720 * Parses an <extension>, which is found inside a
11721 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011722 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000011723 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011724 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000011725 */
11726static xmlSchemaTypePtr
11727xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011728 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000011729{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011730 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011731 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011732 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011733
11734 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11735 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011736 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011737 type = ctxt->ctxtType;
11738 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000011739
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011740 /*
11741 * Check for illegal attributes.
11742 */
11743 attr = node->properties;
11744 while (attr != NULL) {
11745 if (attr->ns == NULL) {
11746 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11747 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011748 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011749 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011750 }
11751 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011752 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011753 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011754 }
11755 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011756 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011757
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011758 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011759
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011760 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011761 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011762 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011763 if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11764 "base", &(type->baseNs), &(type->base)) == 0) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011765 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011766 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011767 XML_SCHEMAP_S4S_ATTR_MISSING,
11768 NULL, node, "base", NULL);
11769 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011770 /*
11771 * And now for the children...
11772 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011773 child = node->children;
11774 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011775 /*
11776 * Add the annotation to the type ancestor.
11777 */
11778 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000011779 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011780 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011781 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011782 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11783 /*
11784 * Corresponds to <complexType><complexContent><extension>... and:
11785 *
11786 * Model groups <all>, <choice>, <sequence> and <group>.
11787 */
11788 if (IS_SCHEMA(child, "all")) {
11789 type->subtypes = (xmlSchemaTypePtr)
11790 xmlSchemaParseModelGroup(ctxt, schema,
11791 child, XML_SCHEMA_TYPE_ALL, 1);
11792 child = child->next;
11793 } else if (IS_SCHEMA(child, "choice")) {
11794 type->subtypes = (xmlSchemaTypePtr)
11795 xmlSchemaParseModelGroup(ctxt, schema,
11796 child, XML_SCHEMA_TYPE_CHOICE, 1);
11797 child = child->next;
11798 } else if (IS_SCHEMA(child, "sequence")) {
11799 type->subtypes = (xmlSchemaTypePtr)
11800 xmlSchemaParseModelGroup(ctxt, schema,
11801 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11802 child = child->next;
11803 } else if (IS_SCHEMA(child, "group")) {
11804 type->subtypes = (xmlSchemaTypePtr)
11805 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011806 /*
11807 * Note that the reference will be resolved in
11808 * xmlSchemaResolveTypeReferences();
11809 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011810 child = child->next;
11811 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011812 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011813 if (child != NULL) {
11814 /*
11815 * Attribute uses/declarations.
11816 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011817 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11818 (xmlSchemaItemListPtr *) &(type->attrUses),
11819 XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11820 return(NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011821 /*
11822 * Attribute wildcard.
11823 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011824 if (IS_SCHEMA(child, "anyAttribute")) {
11825 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011826 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11827 child = child->next;
11828 }
11829 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011830 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011831 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11832 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011833 xmlSchemaPContentErr(ctxt,
11834 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011835 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011836 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011837 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011838 } else {
11839 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011840 xmlSchemaPContentErr(ctxt,
11841 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011842 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011843 "(annotation?, ((attribute | attributeGroup)*, "
11844 "anyAttribute?))");
11845 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011846 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011847 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011848}
11849
11850/**
11851 * xmlSchemaParseSimpleContent:
11852 * @ctxt: a schema validation context
11853 * @schema: the schema being built
11854 * @node: a subtree containing XML Schema informations
11855 *
11856 * parse a XML schema SimpleContent definition
11857 * *WARNING* this interface is highly subject to change
11858 *
11859 * Returns the type definition or NULL in case of error
11860 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011861static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011862xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011863 xmlSchemaPtr schema, xmlNodePtr node,
11864 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000011865{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011866 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011867 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011868 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011869
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011870 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11871 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011872 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011873 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011874 /* Not a component, don't create it. */
11875 type = ctxt->ctxtType;
11876 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11877 /*
11878 * Check for illegal attributes.
11879 */
11880 attr = node->properties;
11881 while (attr != NULL) {
11882 if (attr->ns == NULL) {
11883 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011884 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011885 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011886 }
11887 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011888 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011889 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011890 }
11891 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011892 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011893
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011894 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000011895
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011896 /*
11897 * And now for the children...
11898 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011899 child = node->children;
11900 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011901 /*
11902 * Add the annotation to the complex type ancestor.
11903 */
11904 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000011905 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011906 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011907 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +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. Buchcik764b3d62005-08-12 12:25:23 +000011912 "(annotation?, (restriction | extension))");
11913 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011914 if (child == NULL) {
11915 xmlSchemaPContentErr(ctxt,
11916 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011917 NULL, node, NULL, NULL,
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011918 "(annotation?, (restriction | extension))");
11919 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011920 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011921 xmlSchemaParseRestriction(ctxt, schema, child,
11922 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011923 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011924 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011925 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011926 xmlSchemaParseExtension(ctxt, schema, child,
11927 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011928 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011929 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011930 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011931 if (child != NULL) {
11932 xmlSchemaPContentErr(ctxt,
11933 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011934 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011935 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000011936 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011937 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000011938}
11939
11940/**
11941 * xmlSchemaParseComplexContent:
11942 * @ctxt: a schema validation context
11943 * @schema: the schema being built
11944 * @node: a subtree containing XML Schema informations
11945 *
11946 * parse a XML schema ComplexContent definition
11947 * *WARNING* this interface is highly subject to change
11948 *
11949 * Returns the type definition or NULL in case of error
11950 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011951static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011952xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011953 xmlSchemaPtr schema, xmlNodePtr node,
11954 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000011955{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011956 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011957 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011958 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011959
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011960 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11961 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011962 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011963 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011964 /* Not a component, don't create it. */
11965 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011966 /*
11967 * Check for illegal attributes.
11968 */
11969 attr = node->properties;
11970 while (attr != NULL) {
11971 if (attr->ns == NULL) {
11972 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011973 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011974 {
11975 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011976 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011977 }
11978 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11979 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011980 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011981 }
11982 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011983 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011984
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011985 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011986
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011987 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011988 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011989 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011990 if (xmlGetBooleanProp(ctxt, node, "mixed", 0)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011991 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
11992 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011993 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011994 child = node->children;
11995 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011996 /*
11997 * Add the annotation to the complex type ancestor.
11998 */
11999 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000012000 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012001 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012002 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +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. Buchcik764b3d62005-08-12 12:25:23 +000012007 NULL, "(annotation?, (restriction | extension))");
12008 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012009 if (child == NULL) {
12010 xmlSchemaPContentErr(ctxt,
12011 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012012 NULL, node, NULL,
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012013 NULL, "(annotation?, (restriction | extension))");
12014 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012015 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012016 xmlSchemaParseRestriction(ctxt, schema, child,
12017 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012018 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012019 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012020 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012021 xmlSchemaParseExtension(ctxt, schema, child,
12022 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012023 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012024 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012025 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012026 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012027 xmlSchemaPContentErr(ctxt,
12028 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012029 NULL, node, child,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012030 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000012031 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012032 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000012033}
12034
12035/**
12036 * xmlSchemaParseComplexType:
12037 * @ctxt: a schema validation context
12038 * @schema: the schema being built
12039 * @node: a subtree containing XML Schema informations
12040 *
12041 * parse a XML schema Complex Type definition
12042 * *WARNING* this interface is highly subject to change
12043 *
12044 * Returns the type definition or NULL in case of error
12045 */
12046static xmlSchemaTypePtr
12047xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000012048 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000012049{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012050 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000012051 xmlNodePtr child = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012052 const xmlChar *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012053 xmlAttrPtr attr;
12054 const xmlChar *attrValue;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012055#ifdef ENABLE_NAMED_LOCALS
Daniel Veillard1a380b82004-10-21 16:00:06 +000012056 char buf[40];
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012057#endif
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012058 int final = 0, block = 0, hasRestrictionOrExtension = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000012059
Daniel Veillard4255d502002-04-16 15:50:10 +000012060
12061 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12062 return (NULL);
12063
Daniel Veillard01fa6152004-06-29 17:04:39 +000012064 ctxtType = ctxt->ctxtType;
12065
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012066 if (topLevel) {
12067 attr = xmlSchemaGetPropNode(node, "name");
12068 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012069 xmlSchemaPMissingAttrErr(ctxt,
12070 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012071 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012072 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012073 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12074 return (NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012075 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012076 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012077
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012078 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012079 /*
12080 * Parse as local complex type definition.
12081 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012082#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000012083 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012084 type = xmlSchemaAddType(ctxt, schema,
12085 XML_SCHEMA_TYPE_COMPLEX,
12086 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012087 ctxt->targetNamespace, node, 0);
12088#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012089 type = xmlSchemaAddType(ctxt, schema,
12090 XML_SCHEMA_TYPE_COMPLEX,
12091 NULL, ctxt->targetNamespace, node, 0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012092#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012093 if (type == NULL)
12094 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012095 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012096 type->node = node;
12097 type->type = XML_SCHEMA_TYPE_COMPLEX;
12098 /*
12099 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012100 */
12101 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012102 /*
12103 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012104 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012105 type = xmlSchemaAddType(ctxt, schema,
12106 XML_SCHEMA_TYPE_COMPLEX,
12107 name, ctxt->targetNamespace, node, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012108 if (type == NULL)
12109 return (NULL);
12110 type->node = node;
12111 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012112 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000012113 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012114 type->targetNamespace = ctxt->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012115 /*
12116 * Handle attributes.
12117 */
12118 attr = node->properties;
12119 while (attr != NULL) {
12120 if (attr->ns == NULL) {
12121 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12122 /*
12123 * Attribute "id".
12124 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012125 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012126 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12127 /*
12128 * Attribute "mixed".
12129 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012130 if (xmlSchemaPGetBoolNodeValue(ctxt,
12131 NULL, (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012132 type->flags |= XML_SCHEMAS_TYPE_MIXED;
12133 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012134 /*
12135 * Attributes of global complex type definitions.
12136 */
12137 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12138 /* Pass. */
12139 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12140 /*
12141 * Attribute "abstract".
12142 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012143 if (xmlSchemaPGetBoolNodeValue(ctxt,
12144 NULL, (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012145 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12146 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12147 /*
12148 * Attribute "final".
12149 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012150 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012151 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012152 if (xmlSchemaPValAttrBlockFinal(attrValue,
12153 &(type->flags),
12154 -1,
12155 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12156 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12157 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012158 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012159 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012160 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012161 NULL, (xmlNodePtr) attr, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012162 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012163 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012164 } else
12165 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012166 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12167 /*
12168 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012169 */
12170 attrValue = xmlSchemaGetNodeContent(ctxt,
12171 (xmlNodePtr) attr);
12172 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012173 -1,
12174 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012175 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012176 -1, -1, -1) != 0) {
12177 xmlSchemaPSimpleTypeErr(ctxt,
12178 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012179 NULL, (xmlNodePtr) attr, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012180 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012181 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012182 } else
12183 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012184 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012185 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012186 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012187 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012188 } else {
12189 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012190 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012191 }
12192 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012193 xmlSchemaPIllegalAttrErr(ctxt,
12194 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012195 }
12196 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012197 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012198 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000012199 /*
12200 * Apply default "block" values.
12201 */
12202 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12203 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12204 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12205 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12206 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012207 if (! final) {
12208 /*
12209 * Apply default "block" values.
12210 */
12211 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12212 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12213 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12214 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12215 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012216 /*
12217 * And now for the children...
12218 */
Daniel Veillard4255d502002-04-16 15:50:10 +000012219 child = node->children;
12220 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000012221 type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012222 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012223 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012224 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000012225 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012226 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012227 * <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012228 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012229 * Specifying mixed='true' when the <simpleContent>
12230 * alternative is chosen has no effect
12231 */
William M. Bracke7091952004-05-11 15:09:58 +000012232 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12233 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012234 xmlSchemaParseSimpleContent(ctxt, schema, child,
12235 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012236 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012237 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012238 /*
12239 * <complexType><complexContent>...
12240 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012241 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012242 xmlSchemaParseComplexContent(ctxt, schema, child,
12243 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012244 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012245 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012246 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012247 * E.g <complexType><sequence>... or <complexType><attribute>... etc.
12248 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012249 * SPEC
12250 * "...the third alternative (neither <simpleContent> nor
12251 * <complexContent>) is chosen. This case is understood as shorthand
12252 * for complex content restricting the ·ur-type definition·, and the
12253 * details of the mappings should be modified as necessary.
12254 */
12255 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12256 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012257 /*
12258 * Parse model groups.
12259 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012260 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012261 type->subtypes = (xmlSchemaTypePtr)
12262 xmlSchemaParseModelGroup(ctxt, schema, child,
12263 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012264 child = child->next;
12265 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012266 type->subtypes = (xmlSchemaTypePtr)
12267 xmlSchemaParseModelGroup(ctxt, schema, child,
12268 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012269 child = child->next;
12270 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012271 type->subtypes = (xmlSchemaTypePtr)
12272 xmlSchemaParseModelGroup(ctxt, schema, child,
12273 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012274 child = child->next;
12275 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012276 type->subtypes = (xmlSchemaTypePtr)
12277 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012278 /*
12279 * Note that the reference will be resolved in
12280 * xmlSchemaResolveTypeReferences();
12281 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012282 child = child->next;
12283 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012284 /*
12285 * Parse attribute decls/refs.
12286 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012287 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12288 (xmlSchemaItemListPtr *) &(type->attrUses),
12289 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12290 return(NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012291 /*
12292 * Parse attribute wildcard.
12293 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012294 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012295 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12296 child = child->next;
12297 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012298 }
12299 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012300 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012301 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012302 NULL, node, child,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012303 NULL, "(annotation?, (simpleContent | complexContent | "
12304 "((group | all | choice | sequence)?, ((attribute | "
12305 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000012306 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012307 /*
12308 * REDEFINE: SPEC src-redefine (5)
12309 */
12310 if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12311 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012312 NULL, node, "This is a redefinition, thus the "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012313 "<complexType> must have a <restriction> or <extension> "
12314 "grand-child", NULL);
12315 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012316 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000012317 return (type);
12318}
12319
Daniel Veillard4255d502002-04-16 15:50:10 +000012320/************************************************************************
12321 * *
12322 * Validating using Schemas *
12323 * *
12324 ************************************************************************/
12325
12326/************************************************************************
12327 * *
12328 * Reading/Writing Schemas *
12329 * *
12330 ************************************************************************/
12331
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012332#if 0 /* Will be enabled if it is clear what options are needed. */
12333/**
12334 * xmlSchemaParserCtxtSetOptions:
12335 * @ctxt: a schema parser context
12336 * @options: a combination of xmlSchemaParserOption
12337 *
12338 * Sets the options to be used during the parse.
12339 *
12340 * Returns 0 in case of success, -1 in case of an
12341 * API error.
12342 */
12343static int
12344xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12345 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012346
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012347{
12348 int i;
12349
12350 if (ctxt == NULL)
12351 return (-1);
12352 /*
12353 * WARNING: Change the start value if adding to the
12354 * xmlSchemaParseOption.
12355 */
12356 for (i = 1; i < (int) sizeof(int) * 8; i++) {
12357 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012358 return (-1);
12359 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012360 }
12361 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012362 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012363}
12364
12365/**
12366 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012367 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012368 *
12369 * Returns the option combination of the parser context.
12370 */
12371static int
12372xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012373
12374{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012375 if (ctxt == NULL)
12376 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012377 else
12378 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012379}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012380#endif
12381
Daniel Veillard4255d502002-04-16 15:50:10 +000012382/**
12383 * xmlSchemaNewParserCtxt:
12384 * @URL: the location of the schema
12385 *
12386 * Create an XML Schemas parse context for that file/resource expected
12387 * to contain an XML Schemas file.
12388 *
12389 * Returns the parser context or NULL in case of error
12390 */
12391xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012392xmlSchemaNewParserCtxt(const char *URL)
12393{
Daniel Veillard4255d502002-04-16 15:50:10 +000012394 xmlSchemaParserCtxtPtr ret;
12395
12396 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012397 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000012398
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012399 ret = xmlSchemaParserCtxtCreate();
12400 if (ret == NULL)
12401 return(NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012402 ret->dict = xmlDictCreate();
12403 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012404 return (ret);
12405}
12406
12407/**
Daniel Veillard6045c902002-10-09 21:13:59 +000012408 * xmlSchemaNewMemParserCtxt:
12409 * @buffer: a pointer to a char array containing the schemas
12410 * @size: the size of the array
12411 *
12412 * Create an XML Schemas parse context for that memory buffer expected
12413 * to contain an XML Schemas file.
12414 *
12415 * Returns the parser context or NULL in case of error
12416 */
12417xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012418xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12419{
Daniel Veillard6045c902002-10-09 21:13:59 +000012420 xmlSchemaParserCtxtPtr ret;
12421
12422 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012423 return (NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012424 ret = xmlSchemaParserCtxtCreate();
12425 if (ret == NULL)
12426 return(NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000012427 ret->buffer = buffer;
12428 ret->size = size;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012429 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000012430 return (ret);
12431}
12432
12433/**
Daniel Veillard9d751502003-10-29 13:21:47 +000012434 * xmlSchemaNewDocParserCtxt:
12435 * @doc: a preparsed document tree
12436 *
12437 * Create an XML Schemas parse context for that document.
12438 * NB. The document may be modified during the parsing process.
12439 *
12440 * Returns the parser context or NULL in case of error
12441 */
12442xmlSchemaParserCtxtPtr
12443xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12444{
12445 xmlSchemaParserCtxtPtr ret;
12446
12447 if (doc == NULL)
12448 return (NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012449 ret = xmlSchemaParserCtxtCreate();
12450 if (ret == NULL)
12451 return(NULL);
Daniel Veillard9d751502003-10-29 13:21:47 +000012452 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000012453 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000012454 /* The application has responsibility for the document */
12455 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000012456
12457 return (ret);
12458}
12459
12460/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012461 * xmlSchemaFreeParserCtxt:
12462 * @ctxt: the schema parser context
12463 *
12464 * Free the resources associated to the schema parser context
12465 */
12466void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012467xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12468{
Daniel Veillard4255d502002-04-16 15:50:10 +000012469 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012470 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000012471 if (ctxt->doc != NULL && !ctxt->preserve)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012472 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012473 if (ctxt->vctxt != NULL) {
12474 xmlSchemaFreeValidCtxt(ctxt->vctxt);
12475 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012476 if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12477 xmlSchemaConstructionCtxtFree(ctxt->constructor);
12478 ctxt->constructor = NULL;
12479 ctxt->ownsConstructor = 0;
12480 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012481 if (ctxt->attrProhibs != NULL)
12482 xmlSchemaItemListFree(ctxt->attrProhibs);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012483 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000012484 xmlFree(ctxt);
12485}
12486
12487/************************************************************************
12488 * *
12489 * Building the content models *
12490 * *
12491 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012492
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012493static void
12494xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012495 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012496{
Daniel Veillarda980bef2005-07-18 21:34:03 +000012497 xmlAutomataStatePtr start, tmp;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012498 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012499 xmlSchemaSubstGroupPtr substGroup;
12500 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012501
12502 elemDecl = (xmlSchemaElementPtr) particle->children;
12503 /*
12504 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012505 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012506 start = pctxt->state;
Daniel Veillarda980bef2005-07-18 21:34:03 +000012507 if (end == NULL)
12508 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012509 substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012510 if (substGroup == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012511 xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012512 XML_SCHEMAP_INTERNAL,
12513 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12514 "declaration is marked having a subst. group but none "
12515 "available.\n", elemDecl->name, NULL);
12516 return;
12517 }
Daniel Veillarda980bef2005-07-18 21:34:03 +000012518 if (counter >= 0) {
12519 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012520 * NOTE that we put the declaration in, even if it's abstract.
12521 * However, an error will be raised during *validation* if an element
12522 * information item shall be validated against an abstract element
12523 * declaration.
Daniel Veillarda980bef2005-07-18 21:34:03 +000012524 */
12525 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12526 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12527 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12528 /*
12529 * Add subst. group members.
12530 */
12531 for (i = 0; i < substGroup->members->nbItems; i++) {
12532 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12533 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12534 member->name, member->targetNamespace, member);
12535 }
12536 } else if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012537 /*
12538 * NOTE that we put the declaration in, even if it's abstract,
12539 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012540 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012541 xmlAutomataNewTransition2(pctxt->am,
12542 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012543 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12544 /*
12545 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012546 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012547 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012548 member = (xmlSchemaElementPtr) substGroup->members->items[i];
Daniel Veillarda980bef2005-07-18 21:34:03 +000012549 tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12550 member->name, member->targetNamespace,
12551 1, 1, member);
12552 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012553 }
12554 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012555 xmlAutomataStatePtr hop;
12556 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12557 UNBOUNDED : particle->maxOccurs - 1;
12558 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12559
12560 counter =
12561 xmlAutomataNewCounter(pctxt->am, minOccurs,
12562 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012563 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012564
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012565 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012566 xmlAutomataNewTransition2(pctxt->am,
12567 start, NULL,
12568 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012569 hop);
12570 /*
Daniel Veillarda980bef2005-07-18 21:34:03 +000012571 * Add subst. group members.
12572 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012573 for (i = 0; i < substGroup->members->nbItems; i++) {
12574 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12575 xmlAutomataNewEpsilon(pctxt->am,
12576 xmlAutomataNewTransition2(pctxt->am,
12577 start, NULL,
12578 member->name, member->targetNamespace, member),
12579 hop);
12580 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012581 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12582 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12583 }
12584 if (particle->minOccurs == 0)
12585 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012586 pctxt->state = end;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012587}
12588
12589static void
12590xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12591 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012592{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012593 if (((xmlSchemaElementPtr) particle->children)->flags &
12594 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012595 /*
12596 * Substitution groups.
12597 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000012598 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012599 } else {
12600 xmlSchemaElementPtr elemDecl;
12601 xmlAutomataStatePtr start;
12602
12603 elemDecl = (xmlSchemaElementPtr) particle->children;
12604
12605 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012606 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012607 if (particle->maxOccurs == 1) {
12608 start = ctxt->state;
12609 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012610 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12611 } else if ((particle->maxOccurs >= UNBOUNDED) &&
12612 (particle->minOccurs < 2)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012613 /* Special case. */
Kasimier T. Buchcik7ca5aed2005-12-12 15:13:40 +000012614 start = ctxt->state;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012615 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Kasimier T. Buchcik7ca5aed2005-12-12 15:13:40 +000012616 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12617 ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12618 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012619 } else {
12620 int counter;
12621 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12622 UNBOUNDED : particle->maxOccurs - 1;
12623 int minOccurs = particle->minOccurs < 1 ?
12624 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012625
12626 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012627 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12628 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12629 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12630 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12631 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12632 NULL, counter);
12633 }
12634 if (particle->minOccurs == 0)
12635 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12636 }
12637}
12638
Daniel Veillard4255d502002-04-16 15:50:10 +000012639/**
12640 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000012641 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012642 * @particle: the particle component
12643 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000012644 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012645 * Create the automaton for the {content type} of a complex type.
12646 *
Daniel Veillard4255d502002-04-16 15:50:10 +000012647 */
12648static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012649xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012650 xmlSchemaParticlePtr particle)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012651{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012652 if (particle == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012653 PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012654 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000012655 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012656 if (particle->children == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012657 /*
12658 * Just return in this case. A missing "term" of the particle
12659 * might arise due to an invalid "term" component.
12660 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012661 return;
12662 }
12663
12664 switch (particle->children->type) {
12665 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012666 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012667 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012668 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000012669
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012670 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012671
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012672 start = pctxt->state;
12673 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012674
12675 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012676 if (wild->any == 1) {
12677 /*
12678 * We need to add both transitions:
12679 *
12680 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012681 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012682 pctxt->state =
12683 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012684 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012685 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012686 /*
12687 * 2. the {"*"} for elements in no namespace.
12688 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012689 pctxt->state =
12690 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012691 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012692 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012693
12694 } else if (wild->nsSet != NULL) {
12695 ns = wild->nsSet;
12696 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012697 pctxt->state = start;
12698 pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12699 pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12700 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012701 ns = ns->next;
12702 } while (ns != NULL);
12703
12704 } else if (wild->negNsSet != NULL) {
Daniel Veillard6e65e152005-08-09 11:09:52 +000012705 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12706 start, end, BAD_CAST "*", wild->negNsSet->value,
12707 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012708 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012709 } else {
12710 int counter;
12711 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012712 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012713 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012714 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012715 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012716
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012717 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12718 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012719 if (wild->any == 1) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012720 pctxt->state =
12721 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012722 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012723 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12724 pctxt->state =
12725 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012726 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012727 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012728 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012729 ns = wild->nsSet;
12730 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012731 pctxt->state =
12732 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012733 start, NULL, BAD_CAST "*", ns->value, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012734 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012735 ns = ns->next;
12736 } while (ns != NULL);
12737
12738 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012739 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
Daniel Veillard9efc4762005-07-19 14:33:55 +000012740 start, hop, BAD_CAST "*", wild->negNsSet->value,
12741 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012742 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012743 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12744 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012745 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012746 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012747 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012748 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012749 pctxt->state = end;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012750 break;
12751 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012752 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012753 xmlSchemaBuildContentModelForElement(pctxt, particle);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012754 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012755 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012756 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012757
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012758 /*
12759 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012760 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012761 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012762 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12763 sub = particle->children->children;
12764 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012765 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012766 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012767 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012768 }
12769 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012770 xmlAutomataStatePtr oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012771
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012772 if (particle->maxOccurs >= UNBOUNDED) {
12773 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012774 xmlAutomataStatePtr tmp;
12775 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012776
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012777 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012778 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012779 oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012780
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012781 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012782 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000012783
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012784 sub = particle->children->children;
12785 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012786 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012787 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012788 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012789 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012790 tmp = pctxt->state;
12791 xmlAutomataNewCountedTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012792 oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012793 pctxt->state =
12794 xmlAutomataNewCounterTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012795 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000012796
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012797 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012798 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Daniel Veillardafc05b62005-07-17 06:11:19 +000012799 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012800 oldstate = pctxt->state;
Daniel Veillardafc05b62005-07-17 06:11:19 +000012801
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012802 sub = particle->children->children;
12803 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012804 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012805 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012806 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012807 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012808 xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012809 oldstate);
Daniel Veillardafc05b62005-07-17 06:11:19 +000012810 /*
12811 * epsilon needed to block previous trans from
12812 * being allowed to enter back from another
12813 * construct
12814 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012815 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12816 pctxt->state, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012817 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012818 xmlAutomataNewEpsilon(pctxt->am,
12819 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012820 }
12821 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012822 } else if ((particle->maxOccurs > 1)
12823 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012824 xmlAutomataStatePtr tmp;
12825 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012826
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012827 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012828 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012829 oldstate = pctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000012830
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012831 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012832 particle->minOccurs - 1,
12833 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012834
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012835 sub = particle->children->children;
12836 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012837 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012838 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012839 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012840 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012841 tmp = pctxt->state;
12842 xmlAutomataNewCountedTrans(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012843 tmp, oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012844 pctxt->state =
12845 xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012846 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012847 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012848 xmlAutomataNewEpsilon(pctxt->am,
12849 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012850 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012851 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012852 sub = particle->children->children;
12853 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012854 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012855 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012856 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012857 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012858 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012859 xmlAutomataNewEpsilon(pctxt->am, oldstate,
12860 pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012861 }
12862 }
12863 }
12864 break;
12865 }
12866 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012867 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012868 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000012869
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012870 start = pctxt->state;
12871 end = xmlAutomataNewState(pctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000012872
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012873 /*
12874 * iterate over the subtypes and remerge the end with an
12875 * epsilon transition
12876 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012877 if (particle->maxOccurs == 1) {
12878 sub = particle->children->children;
12879 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012880 pctxt->state = start;
12881 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012882 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012883 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012884 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012885 }
12886 } else {
12887 int counter;
Daniel Veillardafc05b62005-07-17 06:11:19 +000012888 xmlAutomataStatePtr hop, base;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012889 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12890 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012891 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012892 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000012893
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012894 /*
12895 * use a counter to keep track of the number of transtions
12896 * which went through the choice.
12897 */
12898 counter =
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012899 xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12900 hop = xmlAutomataNewState(pctxt->am);
12901 base = xmlAutomataNewState(pctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000012902
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012903 sub = particle->children->children;
12904 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012905 pctxt->state = base;
12906 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012907 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012908 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012909 sub = sub->next;
Daniel Veillarda980bef2005-07-18 21:34:03 +000012910 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012911 xmlAutomataNewEpsilon(pctxt->am, start, base);
12912 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
12913 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012914 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012915 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012916 xmlAutomataNewEpsilon(pctxt->am, start, end);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012917 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012918 pctxt->state = end;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012919 break;
12920 }
12921 case XML_SCHEMA_TYPE_ALL:{
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +000012922 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012923 xmlSchemaParticlePtr sub;
12924 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012925 int lax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012926
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012927 sub = (xmlSchemaParticlePtr) particle->children->children;
12928 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012929 break;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012930 start = pctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012931 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012932 pctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012933
12934 elemDecl = (xmlSchemaElementPtr) sub->children;
12935 if (elemDecl == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012936 PERROR_INT("xmlSchemaBuildAContentModel",
12937 "<element> particle has no term");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012938 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012939 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012940 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012941 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000012942 * {particles} of the group must be 0 or 1; this is
12943 * already ensured during the parse of the content of
12944 * <all>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012945 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000012946 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12947 int counter;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012948
Daniel Veillarda980bef2005-07-18 21:34:03 +000012949 /*
12950 * This is an abstract group, we need to share
12951 * the same counter for all the element transitions
12952 * derived from the group
12953 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012954 counter = xmlAutomataNewCounter(pctxt->am,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012955 sub->minOccurs, sub->maxOccurs);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012956 xmlSchemaBuildContentModelForSubstGroup(pctxt,
12957 sub, counter, pctxt->state);
Daniel Veillarda980bef2005-07-18 21:34:03 +000012958 } else {
12959 if ((sub->minOccurs == 1) &&
12960 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012961 xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
12962 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012963 elemDecl->name,
12964 elemDecl->targetNamespace,
12965 1, 1, elemDecl);
12966 } else if ((sub->minOccurs == 0) &&
12967 (sub->maxOccurs == 1)) {
12968
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012969 xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
12970 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012971 elemDecl->name,
12972 elemDecl->targetNamespace,
12973 0,
12974 1,
12975 elemDecl);
12976 }
12977 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012978 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012979 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012980 lax = particle->minOccurs == 0;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012981 pctxt->state =
12982 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012983 break;
12984 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012985 case XML_SCHEMA_TYPE_GROUP:
12986 /*
12987 * If we hit a model group definition, then this means that
12988 * it was empty, thus was not substituted for the containing
12989 * model group. Just do nothing in this case.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012990 * TODO: But the group should be substituted and not occur at
12991 * all in the content model at this point. Fix this.
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012992 */
12993 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012994 default:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012995 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
12996 "xmlSchemaBuildAContentModel",
12997 "found unexpected term of type '%s' in content model",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012998 WXS_ITEM_TYPE_NAME(particle->children), NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012999 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000013000 }
13001}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013002
Daniel Veillard4255d502002-04-16 15:50:10 +000013003/**
13004 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000013005 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013006 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000013007 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000013008 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013009 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000013010 */
13011static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013012xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013013 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013014{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013015 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13016 (type->contModel != NULL) ||
13017 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13018 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013019 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013020
13021#ifdef DEBUG_CONTENT
13022 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013023 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013024#endif
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013025 ctxt->am = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013026 ctxt->am = xmlNewAutomata();
13027 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013028 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013029 "Cannot create automata for complex type %s\n", type->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013030 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000013031 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000013032 ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013033 /*
13034 * Build the automaton.
13035 */
13036 xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
Daniel Veillard4255d502002-04-16 15:50:10 +000013037 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013038 type->contModel = xmlAutomataCompile(ctxt->am);
13039 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013040 xmlSchemaPCustomErr(ctxt,
13041 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013042 WXS_BASIC_CAST type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013043 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013044 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013045 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013046 XML_SCHEMAP_NOT_DETERMINISTIC,
13047 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013048 WXS_BASIC_CAST type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013049 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000013050 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000013051#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013052 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013053 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013054 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000013055#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000013056 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000013057 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013058 xmlFreeAutomata(ctxt->am);
13059 ctxt->am = NULL;
13060}
13061
13062/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013063 * xmlSchemaResolveElementReferences:
Daniel Veillard4255d502002-04-16 15:50:10 +000013064 * @elem: the schema element context
13065 * @ctxt: the schema parser context
13066 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000013067 * Resolves the references of an element declaration
13068 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013069 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000013070 */
13071static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013072xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13073 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000013074{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013075 if ((ctxt == NULL) || (elemDecl == NULL) ||
13076 ((elemDecl != NULL) &&
13077 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013078 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013079 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013080
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013081 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013082 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013083
13084 /* (type definition) ... otherwise the type definition ·resolved·
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013085 * to by the ·actual value· of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013086 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013087 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013088 elemDecl->namedTypeNs);
13089 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013090 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013091 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013092 WXS_BASIC_CAST elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013093 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013094 XML_SCHEMA_TYPE_BASIC, "type definition");
13095 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013096 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013097 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013098 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013099 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013100
Daniel Veillardc0826a72004-08-10 14:17:33 +000013101 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013102 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013103 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000013104 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013105 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13106 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013107 if (substHead == NULL) {
13108 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013109 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013110 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013111 "substitutionGroup", elemDecl->substGroup,
13112 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013113 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013114 xmlSchemaResolveElementReferences(substHead, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013115 /*
13116 * Set the "substitution group affiliation".
13117 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013118 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013119 WXS_SUBST_HEAD(elemDecl) = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013120 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013121 * The type definitions is set to:
13122 * SPEC "...the {type definition} of the element
13123 * declaration ·resolved· to by the ·actual value·
13124 * of the substitutionGroup [attribute], if present"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013125 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013126 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013127 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013128 }
13129 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013130 /*
13131 * SPEC "The definition of anyType serves as the default type definition
13132 * for element declarations whose XML representation does not specify one."
13133 */
13134 if ((elemDecl->subtypes == NULL) &&
13135 (elemDecl->namedType == NULL) &&
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013136 (elemDecl->substGroup == NULL))
13137 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000013138}
13139
13140/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013141 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000013142 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013143 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000013144 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013145 * Checks and builds the "member type definitions" property of the union
13146 * simple type. This handles part (1), part (2) is done in
13147 * xmlSchemaFinishMemberTypeDefinitionsProperty()
13148 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000013149 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000013150 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013151static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013152xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13153 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000013154{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013155
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013156 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013157 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000013158
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013159 /*
13160 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13161 * define the explicit members as the type definitions ·resolved·
13162 * to by the items in the ·actual value· of the memberTypes [attribute],
13163 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013164 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000013165 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013166 /*
13167 * Resolve references.
13168 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013169 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013170 lastLink = NULL;
13171 while (link != NULL) {
13172 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013173
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013174 name = ((xmlSchemaQNameRefPtr) link->type)->name;
13175 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13176
13177 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013178 if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013179 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013180 WXS_BASIC_CAST type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013181 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13182 /*
13183 * Remove the member type link.
13184 */
13185 if (lastLink == NULL)
13186 type->memberTypes = link->next;
13187 else
13188 lastLink->next = link->next;
13189 newLink = link;
13190 link = link->next;
13191 xmlFree(newLink);
13192 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013193 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013194 lastLink = link;
13195 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013196 }
13197 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013198 /*
13199 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013200 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013201 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013202 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013203 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13204 if (link == NULL) {
13205 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13206 return (-1);
13207 }
13208 link->type = memberType;
13209 link->next = NULL;
13210 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013211 type->memberTypes = link;
13212 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000013213 lastLink->next = link;
13214 lastLink = link;
13215 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013216 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013217 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000013218}
13219
Daniel Veillard4255d502002-04-16 15:50:10 +000013220/**
Daniel Veillard3646d642004-06-02 19:19:14 +000013221 * xmlSchemaIsDerivedFromBuiltInType:
13222 * @ctxt: the schema parser context
13223 * @type: the type definition
13224 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013225 *
Daniel Veillard3646d642004-06-02 19:19:14 +000013226 *
13227 * Returns 1 if the type has the given value type, or
13228 * is derived from such a type.
13229 */
William M. Brack803812b2004-06-03 02:11:24 +000013230static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013231xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000013232{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013233 if (type == NULL)
13234 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013235 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013236 return (0);
13237 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13238 if (type->builtInType == valType)
13239 return(1);
13240 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13241 (type->builtInType == XML_SCHEMAS_ANYTYPE))
13242 return (0);
13243 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard6a0baa02005-12-10 11:11:12 +000013244 }
13245 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000013246}
13247
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013248#if 0
13249/**
13250 * xmlSchemaIsDerivedFromBuiltInType:
13251 * @ctxt: the schema parser context
13252 * @type: the type definition
13253 * @valType: the value type
13254 *
13255 *
13256 * Returns 1 if the type has the given value type, or
13257 * is derived from such a type.
13258 */
13259static int
13260xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13261{
13262 if (type == NULL)
13263 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013264 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013265 return (0);
13266 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13267 if (type->builtInType == valType)
13268 return(1);
13269 return (0);
13270 } else
13271 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13272
13273 return (0);
13274}
13275#endif
13276
13277static xmlSchemaTypePtr
13278xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13279{
13280 if (type == NULL)
13281 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013282 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013283 return (NULL);
13284 if (type->type == XML_SCHEMA_TYPE_BASIC)
Daniel Veillard6a0baa02005-12-10 11:11:12 +000013285 return(type);
13286 return(xmlSchemaQueryBuiltInType(type->subtypes));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013287}
13288
Daniel Veillard3646d642004-06-02 19:19:14 +000013289/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013290 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013291 * @type: the simpleType definition
13292 *
13293 * Returns the primitive type of the given type or
13294 * NULL in case of error.
13295 */
13296static xmlSchemaTypePtr
13297xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13298{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013299
Daniel Veillard01fa6152004-06-29 17:04:39 +000013300 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013301 /*
13302 * Note that anySimpleType is actually not a primitive type
13303 * but we need that here.
13304 */
13305 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13306 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013307 return (type);
13308 type = type->baseType;
13309 }
13310
13311 return (NULL);
13312}
13313
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013314#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013315/**
13316 * xmlSchemaGetBuiltInTypeAncestor:
13317 * @type: the simpleType definition
13318 *
13319 * Returns the primitive type of the given type or
13320 * NULL in case of error.
13321 */
13322static xmlSchemaTypePtr
13323xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13324{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013325 if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013326 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013327 while (type != NULL) {
13328 if (type->type == XML_SCHEMA_TYPE_BASIC)
13329 return (type);
13330 type = type->baseType;
13331 }
13332
13333 return (NULL);
13334}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013335#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013336
Daniel Veillard01fa6152004-06-29 17:04:39 +000013337/**
Daniel Veillard50355f02004-06-08 17:52:16 +000013338 * xmlSchemaCloneWildcardNsConstraints:
13339 * @ctxt: the schema parser context
13340 * @dest: the destination wildcard
13341 * @source: the source wildcard
13342 *
13343 * Clones the namespace constraints of source
13344 * and assignes them to dest.
13345 * Returns -1 on internal error, 0 otherwise.
13346 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013347static int
13348xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013349 xmlSchemaWildcardPtr dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013350 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000013351{
13352 xmlSchemaWildcardNsPtr cur, tmp, last;
13353
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013354 if ((source == NULL) || (dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013355 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013356 dest->any = source->any;
Daniel Veillard3646d642004-06-02 19:19:14 +000013357 cur = source->nsSet;
13358 last = NULL;
13359 while (cur != NULL) {
13360 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13361 if (tmp == NULL)
13362 return(-1);
13363 tmp->value = cur->value;
13364 if (last == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013365 dest->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013366 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013367 last->next = tmp;
13368 last = tmp;
13369 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013370 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013371 if (dest->negNsSet != NULL)
13372 xmlSchemaFreeWildcardNsSet(dest->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000013373 if (source->negNsSet != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013374 dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13375 if (dest->negNsSet == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013376 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013377 dest->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000013378 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013379 dest->negNsSet = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000013380 return(0);
13381}
13382
Daniel Veillard50355f02004-06-08 17:52:16 +000013383/**
13384 * xmlSchemaUnionWildcards:
13385 * @ctxt: the schema parser context
13386 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013387 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013388 *
13389 * Unions the namespace constraints of the given wildcards.
13390 * @completeWild will hold the resulting union.
13391 * Returns a positive error code on failure, -1 in case of an
13392 * internal error, 0 otherwise.
13393 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013394static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013395xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000013396 xmlSchemaWildcardPtr completeWild,
13397 xmlSchemaWildcardPtr curWild)
13398{
13399 xmlSchemaWildcardNsPtr cur, curB, tmp;
13400
13401 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013402 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013403 * value.
13404 */
13405 if ((completeWild->any == curWild->any) &&
13406 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13407 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013408
Daniel Veillard3646d642004-06-02 19:19:14 +000013409 if ((completeWild->negNsSet == NULL) ||
13410 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013411
Daniel Veillard3646d642004-06-02 19:19:14 +000013412 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000013413 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013414
13415 /*
13416 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000013417 */
13418 cur = completeWild->nsSet;
13419 while (cur != NULL) {
13420 found = 0;
13421 curB = curWild->nsSet;
13422 while (curB != NULL) {
13423 if (cur->value == curB->value) {
13424 found = 1;
13425 break;
13426 }
13427 curB = curB->next;
13428 }
13429 if (!found)
13430 break;
13431 cur = cur->next;
13432 }
13433 if (found)
13434 return(0);
13435 } else
13436 return(0);
13437 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013438 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013439 /*
13440 * 2 If either O1 or O2 is any, then any must be the value
13441 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013442 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013443 if (completeWild->any == 0) {
13444 completeWild->any = 1;
13445 if (completeWild->nsSet != NULL) {
13446 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13447 completeWild->nsSet = NULL;
13448 }
13449 if (completeWild->negNsSet != NULL) {
13450 xmlFree(completeWild->negNsSet);
13451 completeWild->negNsSet = NULL;
13452 }
13453 }
Daniel Veillard50355f02004-06-08 17:52:16 +000013454 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013455 }
13456 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013457 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000013458 * then the union of those sets must be the value.
13459 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013460 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013461 int found;
13462 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013463
Daniel Veillard3646d642004-06-02 19:19:14 +000013464 cur = curWild->nsSet;
13465 start = completeWild->nsSet;
13466 while (cur != NULL) {
13467 found = 0;
13468 curB = start;
13469 while (curB != NULL) {
13470 if (cur->value == curB->value) {
13471 found = 1;
13472 break;
13473 }
13474 curB = curB->next;
13475 }
13476 if (!found) {
13477 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013478 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013479 return (-1);
13480 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013481 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000013482 completeWild->nsSet = tmp;
13483 }
13484 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013485 }
13486
Daniel Veillard3646d642004-06-02 19:19:14 +000013487 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013488 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013489 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013490 * 4 If the two are negations of different values (namespace names
Daniel Veillard3646d642004-06-02 19:19:14 +000013491 * or ·absent·), then a pair of not and ·absent· must be the value.
13492 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013493 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013494 (curWild->negNsSet != NULL) &&
13495 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
13496 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000013497
13498 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013499 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013500 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013501 * 5.
13502 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013503 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013504 (completeWild->negNsSet->value != NULL) &&
13505 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013506 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013507 (curWild->negNsSet->value != NULL) &&
13508 (completeWild->nsSet != NULL))) {
13509
13510 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013511
Daniel Veillard3646d642004-06-02 19:19:14 +000013512 if (completeWild->nsSet != NULL) {
13513 cur = completeWild->nsSet;
13514 curB = curWild->negNsSet;
13515 } else {
13516 cur = curWild->nsSet;
13517 curB = completeWild->negNsSet;
13518 }
13519 nsFound = 0;
13520 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013521 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013522 absentFound = 1;
13523 else if (cur->value == curB->value)
13524 nsFound = 1;
13525 if (nsFound && absentFound)
13526 break;
13527 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013528 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013529
13530 if (nsFound && absentFound) {
13531 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013532 * 5.1 If the set S includes both the negated namespace
Daniel Veillard3646d642004-06-02 19:19:14 +000013533 * name and ·absent·, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013534 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013535 completeWild->any = 1;
13536 if (completeWild->nsSet != NULL) {
13537 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13538 completeWild->nsSet = NULL;
13539 }
13540 if (completeWild->negNsSet != NULL) {
13541 xmlFree(completeWild->negNsSet);
13542 completeWild->negNsSet = NULL;
13543 }
13544 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013545 /*
13546 * 5.2 If the set S includes the negated namespace name
13547 * but not ·absent·, then a pair of not and ·absent· must
Daniel Veillard3646d642004-06-02 19:19:14 +000013548 * be the value.
13549 */
13550 if (completeWild->nsSet != NULL) {
13551 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13552 completeWild->nsSet = NULL;
13553 }
13554 if (completeWild->negNsSet == NULL) {
13555 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13556 if (completeWild->negNsSet == NULL)
13557 return (-1);
13558 }
13559 completeWild->negNsSet->value = NULL;
13560 } else if ((!nsFound) && absentFound) {
13561 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013562 * 5.3 If the set S includes ·absent· but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000013563 * namespace name, then the union is not expressible.
13564 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013565 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000013566 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013567 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013568 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000013569 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000013570 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013571 /*
13572 * 5.4 If the set S does not include either the negated namespace
13573 * name or ·absent·, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000013574 * and a namespace name must be the value.
13575 */
13576 if (completeWild->negNsSet == NULL) {
13577 if (completeWild->nsSet != NULL) {
13578 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13579 completeWild->nsSet = NULL;
13580 }
13581 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13582 if (completeWild->negNsSet == NULL)
13583 return (-1);
13584 completeWild->negNsSet->value = curWild->negNsSet->value;
13585 }
13586 }
13587 return (0);
13588 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013589 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013590 * 6.
13591 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013592 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013593 (completeWild->negNsSet->value == NULL) &&
13594 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013595 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013596 (curWild->negNsSet->value == NULL) &&
13597 (completeWild->nsSet != NULL))) {
13598
13599 if (completeWild->nsSet != NULL) {
13600 cur = completeWild->nsSet;
13601 } else {
13602 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013603 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013604 while (cur != NULL) {
13605 if (cur->value == NULL) {
13606 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013607 * 6.1 If the set S includes ·absent·, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013608 * value.
13609 */
13610 completeWild->any = 1;
13611 if (completeWild->nsSet != NULL) {
13612 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13613 completeWild->nsSet = NULL;
13614 }
13615 if (completeWild->negNsSet != NULL) {
13616 xmlFree(completeWild->negNsSet);
13617 completeWild->negNsSet = NULL;
13618 }
13619 return (0);
13620 }
13621 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013622 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013623 if (completeWild->negNsSet == NULL) {
13624 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013625 * 6.2 If the set S does not include ·absent·, then a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000013626 * and ·absent· must be the value.
13627 */
13628 if (completeWild->nsSet != NULL) {
13629 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13630 completeWild->nsSet = NULL;
13631 }
13632 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13633 if (completeWild->negNsSet == NULL)
13634 return (-1);
13635 completeWild->negNsSet->value = NULL;
13636 }
13637 return (0);
13638 }
13639 return (0);
13640
13641}
13642
Daniel Veillard50355f02004-06-08 17:52:16 +000013643/**
13644 * xmlSchemaIntersectWildcards:
13645 * @ctxt: the schema parser context
13646 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013647 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013648 *
13649 * Intersects the namespace constraints of the given wildcards.
13650 * @completeWild will hold the resulting intersection.
13651 * Returns a positive error code on failure, -1 in case of an
13652 * internal error, 0 otherwise.
13653 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013654static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013655xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000013656 xmlSchemaWildcardPtr completeWild,
13657 xmlSchemaWildcardPtr curWild)
13658{
William M. Brack803812b2004-06-03 02:11:24 +000013659 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013660
13661 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013662 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013663 * value.
13664 */
13665 if ((completeWild->any == curWild->any) &&
13666 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13667 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013668
Daniel Veillard3646d642004-06-02 19:19:14 +000013669 if ((completeWild->negNsSet == NULL) ||
13670 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013671
Daniel Veillard3646d642004-06-02 19:19:14 +000013672 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000013673 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013674
13675 /*
13676 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000013677 */
13678 cur = completeWild->nsSet;
13679 while (cur != NULL) {
13680 found = 0;
13681 curB = curWild->nsSet;
13682 while (curB != NULL) {
13683 if (cur->value == curB->value) {
13684 found = 1;
13685 break;
13686 }
13687 curB = curB->next;
13688 }
13689 if (!found)
13690 break;
13691 cur = cur->next;
13692 }
13693 if (found)
13694 return(0);
13695 } else
13696 return(0);
13697 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013698 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013699 /*
13700 * 2 If either O1 or O2 is any, then the other must be the value.
13701 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013702 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013703 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013704 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000013705 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013706 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013707 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013708 * 3 If either O1 or O2 is a pair of not and a value (a namespace
13709 * name or ·absent·) and the other is a set of (namespace names or
13710 * ·absent·), then that set, minus the negated value if it was in
Daniel Veillard3646d642004-06-02 19:19:14 +000013711 * the set, minus ·absent· if it was in the set, must be the value.
13712 */
13713 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13714 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13715 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013716
Daniel Veillard3646d642004-06-02 19:19:14 +000013717 if (completeWild->nsSet == NULL) {
13718 neg = completeWild->negNsSet->value;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013719 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
Daniel Veillard3646d642004-06-02 19:19:14 +000013720 return(-1);
13721 } else
13722 neg = curWild->negNsSet->value;
13723 /*
13724 * Remove absent and negated.
13725 */
13726 prev = NULL;
13727 cur = completeWild->nsSet;
13728 while (cur != NULL) {
13729 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013730 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013731 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013732 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013733 prev->next = cur->next;
13734 xmlFree(cur);
13735 break;
13736 }
13737 prev = cur;
13738 cur = cur->next;
13739 }
13740 if (neg != NULL) {
13741 prev = NULL;
13742 cur = completeWild->nsSet;
13743 while (cur != NULL) {
13744 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013745 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013746 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013747 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013748 prev->next = cur->next;
13749 xmlFree(cur);
13750 break;
13751 }
13752 prev = cur;
13753 cur = cur->next;
13754 }
13755 }
13756
13757 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013758 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013759 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013760 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000013761 * then the intersection of those sets must be the value.
13762 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013763 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013764 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013765
Daniel Veillard3646d642004-06-02 19:19:14 +000013766 cur = completeWild->nsSet;
13767 prev = NULL;
13768 while (cur != NULL) {
13769 found = 0;
13770 curB = curWild->nsSet;
13771 while (curB != NULL) {
13772 if (cur->value == curB->value) {
13773 found = 1;
13774 break;
13775 }
13776 curB = curB->next;
13777 }
13778 if (!found) {
13779 if (prev == NULL)
13780 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013781 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013782 prev->next = cur->next;
13783 tmp = cur->next;
13784 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013785 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013786 continue;
13787 }
13788 prev = cur;
13789 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013790 }
13791
Daniel Veillard3646d642004-06-02 19:19:14 +000013792 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013793 }
13794 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000013795 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013796 */
13797 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013798 (curWild->negNsSet != NULL) &&
13799 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013800 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013801 (curWild->negNsSet->value != NULL)) {
13802
13803 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013804 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013805 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000013806 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013807 }
13808 /*
13809 * 6 If the one is a negation of a namespace name and the other
13810 * is a negation of ·absent·, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000013811 * of a namespace name must be the value.
13812 */
13813 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13814 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013815 (completeWild->negNsSet->value == NULL)) {
13816 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000013817 }
13818 return(0);
13819}
13820
Daniel Veillard50355f02004-06-08 17:52:16 +000013821/**
13822 * xmlSchemaIsWildcardNsConstraintSubset:
13823 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013824 * @sub: the first wildcard
13825 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013826 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013827 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13828 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013829 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013830 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000013831 */
13832static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013833xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13834 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013835{
Daniel Veillard50355f02004-06-08 17:52:16 +000013836 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013837 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000013838 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013839 if (super->any)
13840 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000013841 /*
13842 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
13843 * 2.2 super must be a pair of not and the same value.
13844 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013845 if ((sub->negNsSet != NULL) &&
13846 (super->negNsSet != NULL) &&
13847 (sub->negNsSet->value == sub->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013848 return (0);
13849 /*
13850 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
Daniel Veillard50355f02004-06-08 17:52:16 +000013851 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013852 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013853 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013854 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000013855 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013856 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013857 xmlSchemaWildcardNsPtr cur, curB;
13858 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013859
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013860 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000013861 while (cur != NULL) {
13862 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013863 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000013864 while (curB != NULL) {
13865 if (cur->value == curB->value) {
13866 found = 1;
13867 break;
13868 }
13869 curB = curB->next;
13870 }
13871 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013872 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013873 cur = cur->next;
13874 }
13875 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013876 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013877 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013878 xmlSchemaWildcardNsPtr cur;
13879 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013880 * 3.2.2 super must be a pair of not and a namespace name or
13881 * ·absent· and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000013882 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013883 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013884 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013885 if (cur->value == super->negNsSet->value)
13886 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013887 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013888 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013889 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000013890 }
13891 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013892 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013893}
13894
Daniel Veillard50355f02004-06-08 17:52:16 +000013895static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013896xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013897 int *fixed,
13898 const xmlChar **value,
13899 xmlSchemaValPtr *val)
13900{
13901 *fixed = 0;
13902 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013903 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013904 *val = NULL;
13905
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013906 if (attruse->defValue != NULL) {
13907 *value = attruse->defValue;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000013908 if (val != NULL)
13909 *val = attruse->defVal;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013910 if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013911 *fixed = 1;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013912 return(1);
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000013913 } else if ((attruse->attrDecl != NULL) &&
13914 (attruse->attrDecl->defValue != NULL)) {
13915 *value = attruse->attrDecl->defValue;
13916 if (val != NULL)
13917 *val = attruse->attrDecl->defVal;
13918 if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013919 *fixed = 1;
13920 return(1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013921 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013922 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013923}
Daniel Veillard3646d642004-06-02 19:19:14 +000013924/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013925 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000013926 * @wild: the wildcard
13927 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013928 *
13929 * Validation Rule: Wildcard allows Namespace Name
13930 * (cvc-wildcard-namespace)
13931 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013932 * Returns 0 if the given namespace matches the wildcard,
13933 * 1 otherwise and -1 on API errors.
Daniel Veillard3646d642004-06-02 19:19:14 +000013934 */
13935static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013936xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
13937 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000013938{
13939 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013940 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000013941
13942 if (wild->any)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013943 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013944 else if (wild->nsSet != NULL) {
13945 xmlSchemaWildcardNsPtr cur;
13946
13947 cur = wild->nsSet;
13948 while (cur != NULL) {
13949 if (xmlStrEqual(cur->value, ns))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013950 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013951 cur = cur->next;
13952 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013953 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013954 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013955 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013956
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013957 return(1);
13958}
13959
13960#define XML_SCHEMA_ACTION_DERIVE 0
13961#define XML_SCHEMA_ACTION_REDEFINE 1
13962
13963#define WXS_ACTION_STR(a) \
13964((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
13965
13966/*
13967* Schema Component Constraint:
13968* Derivation Valid (Restriction, Complex)
13969* derivation-ok-restriction (2) - (4)
13970*
13971* ATTENTION:
13972* In XML Schema 1.1 this will be:
13973* Validation Rule:
13974* Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
13975*
13976*/
13977static int
13978xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
13979 int action,
13980 xmlSchemaBasicItemPtr item,
13981 xmlSchemaBasicItemPtr baseItem,
13982 xmlSchemaItemListPtr uses,
13983 xmlSchemaItemListPtr baseUses,
13984 xmlSchemaWildcardPtr wild,
13985 xmlSchemaWildcardPtr baseWild)
13986{
13987 xmlSchemaAttributeUsePtr cur = NULL, bcur;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000013988 int i, j, found; /* err = 0; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013989 const xmlChar *bEffValue;
13990 int effFixed;
13991
13992 if (uses != NULL) {
13993 for (i = 0; i < uses->nbItems; i++) {
13994 cur = uses->items[i];
13995 found = 0;
13996 if (baseUses == NULL)
13997 goto not_found;
13998 for (j = 0; j < baseUses->nbItems; j++) {
13999 bcur = baseUses->items[j];
14000 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14001 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14002 (WXS_ATTRUSE_DECL_TNS(cur) ==
14003 WXS_ATTRUSE_DECL_TNS(bcur)))
14004 {
14005 /*
14006 * (2.1) "If there is an attribute use in the {attribute
14007 * uses} of the {base type definition} (call this B) whose
14008 * {attribute declaration} has the same {name} and {target
14009 * namespace}, then all of the following must be true:"
14010 */
14011 found = 1;
14012
14013 if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14014 (bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14015 {
14016 xmlChar *str = NULL;
14017 /*
14018 * (2.1.1) "one of the following must be true:"
14019 * (2.1.1.1) "B's {required} is false."
14020 * (2.1.1.2) "R's {required} is true."
14021 */
14022 xmlSchemaPAttrUseErr4(pctxt,
14023 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14024 WXS_ITEM_NODE(item), item, cur,
14025 "The 'optional' attribute use is inconsistent "
14026 "with the corresponding 'required' attribute use of "
14027 "the %s %s",
14028 WXS_ACTION_STR(action),
14029 xmlSchemaGetComponentDesignation(&str, baseItem),
14030 NULL, NULL);
14031 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014032 /* err = pctxt->err; */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014033 } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014034 WXS_ATTRUSE_TYPEDEF(cur),
14035 WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14036 {
14037 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14038
14039 /*
14040 * SPEC (2.1.2) "R's {attribute declaration}'s
14041 * {type definition} must be validly derived from
14042 * B's {type definition} given the empty set as
14043 * defined in Type Derivation OK (Simple) (§3.14.6)."
14044 */
14045 xmlSchemaPAttrUseErr4(pctxt,
14046 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14047 WXS_ITEM_NODE(item), item, cur,
14048 "The attribute declaration's %s "
14049 "is not validly derived from "
14050 "the corresponding %s of the "
14051 "attribute declaration in the %s %s",
14052 xmlSchemaGetComponentDesignation(&strA,
14053 WXS_ATTRUSE_TYPEDEF(cur)),
14054 xmlSchemaGetComponentDesignation(&strB,
14055 WXS_ATTRUSE_TYPEDEF(bcur)),
14056 WXS_ACTION_STR(action),
14057 xmlSchemaGetComponentDesignation(&strC, baseItem));
14058 /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14059 FREE_AND_NULL(strA);
14060 FREE_AND_NULL(strB);
14061 FREE_AND_NULL(strC);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014062 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014063 } else {
14064 /*
14065 * 2.1.3 [Definition:] Let the effective value
14066 * constraint of an attribute use be its {value
14067 * constraint}, if present, otherwise its {attribute
14068 * declaration}'s {value constraint} .
14069 */
14070 xmlSchemaGetEffectiveValueConstraint(bcur,
14071 &effFixed, &bEffValue, NULL);
14072 /*
14073 * 2.1.3 ... one of the following must be true
14074 *
14075 * 2.1.3.1 B's ·effective value constraint· is
14076 * ·absent· or default.
14077 */
14078 if ((bEffValue != NULL) &&
14079 (effFixed == 1)) {
14080 const xmlChar *rEffValue = NULL;
14081
14082 xmlSchemaGetEffectiveValueConstraint(bcur,
14083 &effFixed, &rEffValue, NULL);
14084 /*
14085 * 2.1.3.2 R's ·effective value constraint· is
14086 * fixed with the same string as B's.
14087 * MAYBE TODO: Compare the computed values.
14088 * Hmm, it says "same string" so
14089 * string-equality might really be sufficient.
14090 */
14091 if ((effFixed == 0) ||
14092 (! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14093 {
14094 xmlChar *str = NULL;
14095
14096 xmlSchemaPAttrUseErr4(pctxt,
14097 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14098 WXS_ITEM_NODE(item), item, cur,
14099 "The effective value constraint of the "
14100 "attribute use is inconsistent with "
14101 "its correspondent in the %s %s",
14102 WXS_ACTION_STR(action),
14103 xmlSchemaGetComponentDesignation(&str,
14104 baseItem),
14105 NULL, NULL);
14106 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014107 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014108 }
14109 }
14110 }
14111 break;
14112 }
14113 }
14114not_found:
14115 if (!found) {
14116 /*
14117 * (2.2) "otherwise the {base type definition} must have an
14118 * {attribute wildcard} and the {target namespace} of the
14119 * R's {attribute declaration} must be ·valid· with respect
14120 * to that wildcard, as defined in Wildcard allows Namespace
14121 * Name (§3.10.4)."
14122 */
14123 if ((baseWild == NULL) ||
14124 (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14125 (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14126 {
14127 xmlChar *str = NULL;
14128
14129 xmlSchemaPAttrUseErr4(pctxt,
14130 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14131 WXS_ITEM_NODE(item), item, cur,
14132 "Neither a matching attribute use, "
14133 "nor a matching wildcard exists in the %s %s",
14134 WXS_ACTION_STR(action),
14135 xmlSchemaGetComponentDesignation(&str, baseItem),
14136 NULL, NULL);
14137 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014138 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014139 }
14140 }
14141 }
14142 }
14143 /*
14144 * SPEC derivation-ok-restriction (3):
14145 * (3) "For each attribute use in the {attribute uses} of the {base type
14146 * definition} whose {required} is true, there must be an attribute
14147 * use with an {attribute declaration} with the same {name} and
14148 * {target namespace} as its {attribute declaration} in the {attribute
14149 * uses} of the complex type definition itself whose {required} is true.
14150 */
14151 if (baseUses != NULL) {
14152 for (j = 0; j < baseUses->nbItems; j++) {
14153 bcur = baseUses->items[j];
14154 if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14155 continue;
14156 found = 0;
14157 if (uses != NULL) {
14158 for (i = 0; i < uses->nbItems; i++) {
14159 cur = uses->items[i];
14160 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14161 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14162 (WXS_ATTRUSE_DECL_TNS(cur) ==
14163 WXS_ATTRUSE_DECL_TNS(bcur))) {
14164 found = 1;
14165 break;
14166 }
14167 }
14168 }
14169 if (!found) {
14170 xmlChar *strA = NULL, *strB = NULL;
14171
14172 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14173 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14174 NULL, item,
14175 "A matching attribute use for the "
14176 "'required' %s of the %s %s is missing",
14177 xmlSchemaGetComponentDesignation(&strA, bcur),
14178 WXS_ACTION_STR(action),
14179 xmlSchemaGetComponentDesignation(&strB, baseItem),
14180 NULL);
14181 FREE_AND_NULL(strA);
14182 FREE_AND_NULL(strB);
14183 }
14184 }
14185 }
14186 /*
14187 * derivation-ok-restriction (4)
14188 */
14189 if (wild != NULL) {
14190 /*
14191 * (4) "If there is an {attribute wildcard}, all of the
14192 * following must be true:"
14193 */
14194 if (baseWild == NULL) {
14195 xmlChar *str = NULL;
14196
14197 /*
14198 * (4.1) "The {base type definition} must also have one."
14199 */
14200 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14201 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14202 NULL, item,
14203 "The %s has an attribute wildcard, "
14204 "but the %s %s '%s' does not have one",
14205 WXS_ITEM_TYPE_NAME(item),
14206 WXS_ACTION_STR(action),
14207 WXS_ITEM_TYPE_NAME(baseItem),
14208 xmlSchemaGetComponentQName(&str, baseItem));
14209 FREE_AND_NULL(str);
14210 return(pctxt->err);
14211 } else if ((baseWild->any == 0) &&
14212 xmlSchemaCheckCOSNSSubset(wild, baseWild))
14213 {
14214 xmlChar *str = NULL;
14215 /*
14216 * (4.2) "The complex type definition's {attribute wildcard}'s
14217 * {namespace constraint} must be a subset of the {base type
14218 * definition}'s {attribute wildcard}'s {namespace constraint},
14219 * as defined by Wildcard Subset (§3.10.6)."
14220 */
14221 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14222 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14223 NULL, item,
14224 "The attribute wildcard is not a valid "
14225 "subset of the wildcard in the %s %s '%s'",
14226 WXS_ACTION_STR(action),
14227 WXS_ITEM_TYPE_NAME(baseItem),
14228 xmlSchemaGetComponentQName(&str, baseItem),
14229 NULL);
14230 FREE_AND_NULL(str);
14231 return(pctxt->err);
14232 }
14233 /* 4.3 Unless the {base type definition} is the ·ur-type
14234 * definition·, the complex type definition's {attribute
14235 * wildcard}'s {process contents} must be identical to or
14236 * stronger than the {base type definition}'s {attribute
14237 * wildcard}'s {process contents}, where strict is stronger
14238 * than lax is stronger than skip.
14239 */
14240 if ((! WXS_IS_ANYTYPE(baseItem)) &&
14241 (wild->processContents < baseWild->processContents)) {
14242 xmlChar *str = NULL;
14243 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14244 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14245 NULL, baseItem,
14246 "The {process contents} of the attribute wildcard is "
14247 "weaker than the one in the %s %s '%s'",
14248 WXS_ACTION_STR(action),
14249 WXS_ITEM_TYPE_NAME(baseItem),
14250 xmlSchemaGetComponentQName(&str, baseItem),
14251 NULL);
14252 FREE_AND_NULL(str)
14253 return(pctxt->err);
14254 }
14255 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014256 return(0);
14257}
14258
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014259
14260static int
14261xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14262 xmlSchemaBasicItemPtr item,
14263 xmlSchemaWildcardPtr *completeWild,
14264 xmlSchemaItemListPtr list,
14265 xmlSchemaItemListPtr prohibs);
Daniel Veillard3646d642004-06-02 19:19:14 +000014266/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014267 * xmlSchemaFixupTypeAttributeUses:
Daniel Veillard3646d642004-06-02 19:19:14 +000014268 * @ctxt: the schema parser context
14269 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014270 *
Daniel Veillard3646d642004-06-02 19:19:14 +000014271 *
14272 * Builds the wildcard and the attribute uses on the given complex type.
14273 * Returns -1 if an internal error occurs, 0 otherwise.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014274 *
14275 * ATTENTION TODO: Experimantally this uses pointer comparisons for
14276 * strings, so recheck this if we start to hardcode some schemata, since
14277 * they might not be in the same dict.
14278 * NOTE: It is allowed to "extend" the xs:anyType type.
Daniel Veillard3646d642004-06-02 19:19:14 +000014279 */
14280static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014281xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014282 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000014283{
14284 xmlSchemaTypePtr baseType = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014285 xmlSchemaAttributeUsePtr use;
14286 xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000014287
Daniel Veillard01fa6152004-06-29 17:04:39 +000014288 if (type->baseType == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014289 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014290 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014291 return (-1);
14292 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014293 baseType = type->baseType;
14294 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014295 if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014296 return(-1);
14297
14298 uses = type->attrUses;
14299 baseUses = baseType->attrUses;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014300 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014301 * Expand attribute group references. And build the 'complete'
14302 * wildcard, i.e. intersect multiple wildcards.
14303 * Move attribute prohibitions into a separate list.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014304 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014305 if (uses != NULL) {
14306 if (WXS_IS_RESTRICTION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014307 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014308 * This one will transfer all attr. prohibitions
14309 * into pctxt->attrProhibs.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014310 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014311 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14312 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14313 pctxt->attrProhibs) == -1)
14314 {
14315 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14316 "failed to expand attributes");
14317 }
14318 if (pctxt->attrProhibs->nbItems != 0)
14319 prohibs = pctxt->attrProhibs;
14320 } else {
14321 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14322 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14323 NULL) == -1)
14324 {
14325 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14326 "failed to expand attributes");
14327 }
14328 }
14329 }
14330 /*
14331 * Inherit the attribute uses of the base type.
14332 */
14333 if (baseUses != NULL) {
14334 int i, j;
14335 xmlSchemaAttributeUseProhibPtr pro;
14336
14337 if (WXS_IS_RESTRICTION(type)) {
14338 int usesCount;
14339 xmlSchemaAttributeUsePtr tmp;
14340
14341 if (uses != NULL)
14342 usesCount = uses->nbItems;
14343 else
14344 usesCount = 0;
14345
14346 /* Restriction. */
14347 for (i = 0; i < baseUses->nbItems; i++) {
14348 use = baseUses->items[i];
14349 if (prohibs) {
14350 /*
14351 * Filter out prohibited uses.
14352 */
14353 for (j = 0; j < prohibs->nbItems; j++) {
14354 pro = prohibs->items[j];
14355 if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14356 (WXS_ATTRUSE_DECL_TNS(use) ==
14357 pro->targetNamespace))
14358 {
14359 goto inherit_next;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014360 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014361 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014362 }
14363 if (usesCount) {
14364 /*
14365 * Filter out existing uses.
14366 */
14367 for (j = 0; j < usesCount; j++) {
14368 tmp = uses->items[j];
14369 if ((WXS_ATTRUSE_DECL_NAME(use) ==
14370 WXS_ATTRUSE_DECL_NAME(tmp)) &&
14371 (WXS_ATTRUSE_DECL_TNS(use) ==
14372 WXS_ATTRUSE_DECL_TNS(tmp)))
14373 {
14374 goto inherit_next;
14375 }
14376 }
14377 }
14378 if (uses == NULL) {
14379 type->attrUses = xmlSchemaItemListCreate();
14380 if (type->attrUses == NULL)
14381 goto exit_failure;
14382 uses = type->attrUses;
14383 }
14384 xmlSchemaItemListAddSize(uses, 2, use);
14385inherit_next: {}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014386 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014387 } else {
14388 /* Extension. */
14389 for (i = 0; i < baseUses->nbItems; i++) {
14390 use = baseUses->items[i];
14391 if (uses == NULL) {
14392 type->attrUses = xmlSchemaItemListCreate();
14393 if (type->attrUses == NULL)
14394 goto exit_failure;
14395 uses = type->attrUses;
14396 }
14397 xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14398 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014399 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014400 }
14401 /*
14402 * Shrink attr. uses.
14403 */
14404 if (uses) {
14405 if (uses->nbItems == 0) {
14406 xmlSchemaItemListFree(uses);
14407 type->attrUses = NULL;
14408 }
14409 /*
14410 * TODO: We could shrink the size of the array
14411 * to fit the actual number of items.
14412 */
14413 }
14414 /*
14415 * Compute the complete wildcard.
14416 */
14417 if (WXS_IS_EXTENSION(type)) {
14418 if (baseType->attributeWildcard != NULL) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014419 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014420 * (3.2.2.1) "If the ·base wildcard· is non-·absent·, then
14421 * the appropriate case among the following:"
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014422 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014423 if (type->attributeWildcard != NULL) {
14424 /*
14425 * Union the complete wildcard with the base wildcard.
14426 * SPEC {attribute wildcard}
14427 * (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14428 * and {annotation} are those of the ·complete wildcard·,
14429 * and whose {namespace constraint} is the intensional union
14430 * of the {namespace constraint} of the ·complete wildcard·
14431 * and of the ·base wildcard·, as defined in Attribute
14432 * Wildcard Union (§3.10.6)."
14433 */
14434 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14435 baseType->attributeWildcard) == -1)
14436 goto exit_failure;
14437 } else {
14438 /*
14439 * (3.2.2.1.1) "If the ·complete wildcard· is ·absent·,
14440 * then the ·base wildcard·."
14441 */
14442 type->attributeWildcard = baseType->attributeWildcard;
14443 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014444 } else {
14445 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014446 * (3.2.2.2) "otherwise (the ·base wildcard· is ·absent·) the
14447 * ·complete wildcard"
14448 * NOOP
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014449 */
Daniel Veillard50355f02004-06-08 17:52:16 +000014450 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014451 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014452 /*
14453 * SPEC {attribute wildcard}
14454 * (3.1) "If the <restriction> alternative is chosen, then the
14455 * ·complete wildcard·;"
14456 * NOOP
14457 */
Daniel Veillard50355f02004-06-08 17:52:16 +000014458 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014459
Daniel Veillard3646d642004-06-02 19:19:14 +000014460 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014461
14462exit_failure:
14463 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000014464}
14465
14466/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000014467 * xmlSchemaTypeFinalContains:
14468 * @schema: the schema
14469 * @type: the type definition
14470 * @final: the final
14471 *
14472 * Evaluates if a type definition contains the given "final".
14473 * This does take "finalDefault" into account as well.
14474 *
14475 * Returns 1 if the type does containt the given "final",
14476 * 0 otherwise.
14477 */
14478static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014479xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014480{
Daniel Veillard01fa6152004-06-29 17:04:39 +000014481 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014482 return (0);
14483 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014484 return (1);
14485 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014486 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014487}
14488
14489/**
14490 * xmlSchemaGetUnionSimpleTypeMemberTypes:
14491 * @type: the Union Simple Type
14492 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014493 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014494 * returns NULL otherwise.
14495 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014496static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000014497xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14498{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014499 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014500 if (type->memberTypes != NULL)
14501 return (type->memberTypes);
14502 else
14503 type = type->baseType;
14504 }
14505 return (NULL);
14506}
14507
14508/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014509 * xmlSchemaGetParticleTotalRangeMin:
14510 * @particle: the particle
14511 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014512 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014513 * (all and sequence) + (choice)
14514 *
14515 * Returns the minimun Effective Total Range.
14516 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014517static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014518xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014519{
14520 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014521 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014522 return (0);
14523 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014524 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014525 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014526 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014527
14528 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014529 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014530 while (part != NULL) {
14531 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14532 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014533 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014534 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014535 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014536 if (cur == 0)
14537 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014538 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014539 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014540 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014541 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014542 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014543 } else {
14544 /* <all> and <sequence> */
14545 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014546 xmlSchemaParticlePtr part =
14547 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014548
14549 if (part == NULL)
14550 return (0);
14551 do {
14552 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14553 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014554 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014555 else
14556 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014557 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014558 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014559 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014560 }
14561}
14562
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014563/**
14564 * xmlSchemaGetParticleTotalRangeMax:
14565 * @particle: the particle
14566 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014567 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014568 * (all and sequence) + (choice)
14569 *
14570 * Returns the maximum Effective Total Range.
14571 */
14572static int
14573xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14574{
14575 if ((particle->children == NULL) ||
14576 (particle->children->children == NULL))
14577 return (0);
14578 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14579 int max = -1, cur;
14580 xmlSchemaParticlePtr part =
14581 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014582
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014583 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14584 if (part->children == NULL)
14585 continue;
14586 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14587 (part->children->type == XML_SCHEMA_TYPE_ANY))
14588 cur = part->maxOccurs;
14589 else
14590 cur = xmlSchemaGetParticleTotalRangeMax(part);
14591 if (cur == UNBOUNDED)
14592 return (UNBOUNDED);
14593 if ((max < cur) || (max == -1))
14594 max = cur;
14595 }
14596 /* TODO: Handle overflows? */
14597 return (particle->maxOccurs * max);
14598 } else {
14599 /* <all> and <sequence> */
14600 int sum = 0, cur;
14601 xmlSchemaParticlePtr part =
14602 (xmlSchemaParticlePtr) particle->children->children;
14603
14604 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14605 if (part->children == NULL)
14606 continue;
14607 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14608 (part->children->type == XML_SCHEMA_TYPE_ANY))
14609 cur = part->maxOccurs;
14610 else
14611 cur = xmlSchemaGetParticleTotalRangeMax(part);
14612 if (cur == UNBOUNDED)
14613 return (UNBOUNDED);
14614 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14615 return (UNBOUNDED);
14616 sum += cur;
14617 }
14618 /* TODO: Handle overflows? */
14619 return (particle->maxOccurs * sum);
14620 }
14621}
14622
14623/**
14624 * xmlSchemaIsParticleEmptiable:
14625 * @particle: the particle
14626 *
14627 * Schema Component Constraint: Particle Emptiable
14628 * Checks whether the given particle is emptiable.
14629 *
14630 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014631 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014632static int
14633xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14634{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014635 /*
14636 * SPEC (1) "Its {min occurs} is 0."
14637 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014638 if ((particle == NULL) || (particle->minOccurs == 0) ||
14639 (particle->children == NULL))
14640 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014641 /*
14642 * SPEC (2) "Its {term} is a group and the minimum part of the
14643 * effective total range of that group, [...] is 0."
14644 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014645 if (WXS_IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014646 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014647 return (1);
14648 }
14649 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014650}
14651
14652/**
14653 * xmlSchemaCheckCOSSTDerivedOK:
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014654 * @actxt: a context
Daniel Veillard01fa6152004-06-29 17:04:39 +000014655 * @type: the derived simple type definition
14656 * @baseType: the base type definition
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014657 * @subset: the subset of ('restriction', ect.)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014658 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014659 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014660 * Type Derivation OK (Simple) (cos-st-derived-OK)
14661 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014662 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000014663 * derived from @baseType.
14664 *
14665 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014666 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014667static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014668xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014669 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014670 xmlSchemaTypePtr baseType,
14671 int subset)
14672{
Daniel Veillard01fa6152004-06-29 17:04:39 +000014673 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014674 * 1 They are the same type definition.
14675 * TODO: The identy check might have to be more complex than this.
14676 */
14677 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014678 return (0);
14679 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014680 * 2.1 restriction is not in the subset, or in the {final}
14681 * of its own {base type definition};
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014682 *
14683 * NOTE that this will be used also via "xsi:type".
14684 *
14685 * TODO: Revise this, it looks strange. How can the "type"
14686 * not be fixed or *in* fixing?
Daniel Veillard01fa6152004-06-29 17:04:39 +000014687 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014688 if (WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014689 if (xmlSchemaTypeFixup(type, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014690 return(-1);
14691 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014692 if (xmlSchemaTypeFixup(baseType, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014693 return(-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014694 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014695 (xmlSchemaTypeFinalContains(type->baseType,
14696 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14697 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014698 }
14699 /* 2.2 */
14700 if (type->baseType == baseType) {
14701 /*
14702 * 2.2.1 D's ·base type definition· is B.
14703 */
14704 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014705 }
14706 /*
14707 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
14708 * and is validly derived from B given the subset, as defined by this
14709 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014710 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014711 if ((! WXS_IS_ANYTYPE(type->baseType)) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014712 (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014713 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014714 return (0);
14715 }
14716 /*
14717 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
Daniel Veillard01fa6152004-06-29 17:04:39 +000014718 * definition·.
14719 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014720 if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14721 (WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014722 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014723 }
14724 /*
14725 * 2.2.4 B's {variety} is union and D is validly derived from a type
14726 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000014727 * defined by this constraint.
14728 *
14729 * NOTE: This seems not to involve built-in types, since there is no
14730 * built-in Union Simple Type.
14731 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014732 if (WXS_IS_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014733 xmlSchemaTypeLinkPtr cur;
14734
14735 cur = baseType->memberTypes;
14736 while (cur != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014737 if (WXS_IS_TYPE_NOT_FIXED(cur->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014738 if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014739 return(-1);
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014740 if (xmlSchemaCheckCOSSTDerivedOK(actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014741 type, cur->type, subset) == 0)
14742 {
14743 /*
14744 * It just has to be validly derived from at least one
14745 * member-type.
14746 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014747 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014748 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014749 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014750 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014751 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014752 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14753}
14754
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014755/**
14756 * xmlSchemaCheckTypeDefCircularInternal:
14757 * @pctxt: the schema parser context
14758 * @ctxtType: the type definition
14759 * @ancestor: an ancestor of @ctxtType
14760 *
14761 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014762 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014763 *
14764 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14765 * circular, 0 otherwise.
14766 */
14767static int
14768xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14769 xmlSchemaTypePtr ctxtType,
14770 xmlSchemaTypePtr ancestor)
14771{
14772 int ret;
14773
14774 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14775 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014776
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014777 if (ctxtType == ancestor) {
14778 xmlSchemaPCustomErr(pctxt,
14779 XML_SCHEMAP_ST_PROPS_CORRECT_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014780 WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014781 "The definition is circular", NULL);
14782 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14783 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014784 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14785 /*
14786 * Avoid inifinite recursion on circular types not yet checked.
14787 */
14788 return (0);
14789 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014790 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14791 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14792 ancestor->baseType);
14793 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14794 return (ret);
14795}
14796
14797/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014798 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014799 * @item: the complex/simple type definition
14800 * @ctxt: the parser context
14801 * @name: the name
14802 *
14803 * Checks for circular type definitions.
14804 */
14805static void
14806xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014807 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014808{
14809 if ((item == NULL) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014810 (item->type == XML_SCHEMA_TYPE_BASIC) ||
14811 (item->baseType == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014812 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014813 xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14814 item->baseType);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014815}
Daniel Veillard01fa6152004-06-29 17:04:39 +000014816
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014817/*
14818* Simple Type Definition Representation OK (src-simple-type) 4
14819*
14820* "4 Circular union type definition is disallowed. That is, if the
14821* <union> alternative is chosen, there must not be any entries in the
14822* memberTypes [attribute] at any depth which resolve to the component
14823* corresponding to the <simpleType>."
14824*
14825* Note that this should work on the *representation* of a component,
14826* thus assumes any union types in the member types not being yet
14827* substituted. At this stage we need the variety of the types
14828* to be already computed.
14829*/
14830static int
14831xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14832 xmlSchemaTypePtr ctxType,
14833 xmlSchemaTypeLinkPtr members)
14834{
14835 xmlSchemaTypeLinkPtr member;
14836 xmlSchemaTypePtr memberType;
14837
14838 member = members;
14839 while (member != NULL) {
14840 memberType = member->type;
14841 while ((memberType != NULL) &&
14842 (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14843 if (memberType == ctxType) {
14844 xmlSchemaPCustomErr(pctxt,
14845 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014846 WXS_BASIC_CAST ctxType, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014847 "The union type definition is circular", NULL);
14848 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14849 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014850 if ((WXS_IS_UNION(memberType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014851 ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14852 {
14853 int res;
14854 memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14855 res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
14856 ctxType,
14857 xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
14858 memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
14859 if (res != 0)
14860 return(res);
14861 }
14862 memberType = memberType->baseType;
14863 }
14864 member = member->next;
14865 }
14866 return(0);
14867}
14868
14869static int
14870xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
14871 xmlSchemaTypePtr type)
14872{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014873 if (! WXS_IS_UNION(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014874 return(0);
14875 return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
14876 type->memberTypes));
14877}
14878
Daniel Veillard01fa6152004-06-29 17:04:39 +000014879/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014880 * xmlSchemaResolveTypeReferences:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014881 * @item: the complex/simple type definition
14882 * @ctxt: the parser context
14883 * @name: the name
14884 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014885 * Resolvese type definition references
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014886 */
14887static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014888xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014889 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014890{
14891 if (typeDef == NULL)
14892 return;
14893
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014894 /*
14895 * Resolve the base type.
14896 */
14897 if (typeDef->baseType == NULL) {
14898 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
14899 typeDef->base, typeDef->baseNs);
14900 if (typeDef->baseType == NULL) {
14901 xmlSchemaPResCompAttrErr(ctxt,
14902 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014903 WXS_BASIC_CAST typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014904 "base", typeDef->base, typeDef->baseNs,
14905 XML_SCHEMA_TYPE_SIMPLE, NULL);
14906 return;
14907 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014908 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014909 if (WXS_IS_SIMPLE(typeDef)) {
14910 if (WXS_IS_UNION(typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014911 /*
14912 * Resolve the memberTypes.
14913 */
14914 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
14915 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014916 } else if (WXS_IS_LIST(typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014917 /*
14918 * Resolve the itemType.
14919 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014920 if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
14921
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014922 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014923 typeDef->base, typeDef->baseNs);
14924
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014925 if ((typeDef->subtypes == NULL) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014926 (! WXS_IS_SIMPLE(typeDef->subtypes)))
14927 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014928 typeDef->subtypes = NULL;
14929 xmlSchemaPResCompAttrErr(ctxt,
14930 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014931 WXS_BASIC_CAST typeDef, typeDef->node,
14932 "itemType", typeDef->base, typeDef->baseNs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014933 XML_SCHEMA_TYPE_SIMPLE, NULL);
14934 }
14935 }
14936 return;
14937 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014938 }
14939 /*
14940 * The ball of letters below means, that if we have a particle
14941 * which has a QName-helper component as its {term}, we want
14942 * to resolve it...
14943 */
14944 else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
14945 ((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
14946 XML_SCHEMA_TYPE_PARTICLE) &&
14947 (WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
14948 ((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
14949 XML_SCHEMA_EXTRA_QNAMEREF))
14950 {
14951 xmlSchemaQNameRefPtr ref =
14952 WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
14953 xmlSchemaModelGroupDefPtr groupDef;
14954
14955 /*
14956 * URGENT TODO: Test this.
14957 */
14958 WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
14959 /*
14960 * Resolve the MG definition reference.
14961 */
14962 groupDef =
14963 WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
14964 ref->itemType, ref->name, ref->targetNamespace);
14965 if (groupDef == NULL) {
14966 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
14967 NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
14968 "ref", ref->name, ref->targetNamespace, ref->itemType,
14969 NULL);
14970 /* Remove the particle. */
14971 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
14972 } else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
14973 /* Remove the particle. */
14974 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
14975 else {
14976 /*
14977 * Assign the MG definition's {model group} to the
14978 * particle's {term}.
14979 */
14980 WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
14981
14982 if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
14983 /*
14984 * SPEC cos-all-limited (1.2)
14985 * "1.2 the {term} property of a particle with
14986 * {max occurs}=1 which is part of a pair which constitutes
14987 * the {content type} of a complex type definition."
14988 */
14989 if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
14990 xmlSchemaCustomErr(ACTXT_CAST ctxt,
14991 /* TODO: error code */
14992 XML_SCHEMAP_COS_ALL_LIMITED,
14993 WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
14994 "The particle's {max occurs} must be 1, since the "
14995 "reference resolves to an 'all' model group",
14996 NULL, NULL);
14997 }
14998 }
14999 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015000 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015001}
15002
15003
15004
15005/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000015006 * xmlSchemaCheckSTPropsCorrect:
15007 * @ctxt: the schema parser context
15008 * @type: the simple type definition
15009 *
15010 * Checks st-props-correct.
15011 *
15012 * Returns 0 if the properties are correct,
15013 * if not, a positive error code and -1 on internal
15014 * errors.
15015 */
15016static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015017xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015018 xmlSchemaTypePtr type)
15019{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015020 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015021 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015022
Daniel Veillardc0826a72004-08-10 14:17:33 +000015023 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015024 /*
15025 * Schema Component Constraint: Simple Type Definition Properties Correct
15026 *
15027 * NOTE: This is somehow redundant, since we actually built a simple type
15028 * to have all the needed information; this acts as an self test.
15029 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015030 /* Base type: If the datatype has been ·derived· by ·restriction·
15031 * then the Simple Type Definition component from which it is ·derived·,
15032 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000015033 */
15034 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015035 /*
15036 * TODO: Think about: "modulo the impact of Missing
15037 * Sub-components (§5.3)."
15038 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015039 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015040 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015041 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015042 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015043 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015044
Daniel Veillard01fa6152004-06-29 17:04:39 +000015045 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015046 if (! WXS_IS_SIMPLE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015047 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015048 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015049 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015050 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015051 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015052 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015053 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15054 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015055 if ( (WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015056 (WXS_IS_RESTRICTION(type) == 0) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015057 (! WXS_IS_ANY_SIMPLE_TYPE(baseType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015058 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015059 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015060 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015061 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015062 "the simple ur-type definition as base type, not '%s'",
15063 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015064 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015065 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15066 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015067 /*
15068 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015069 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015070 if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15071 (! WXS_IS_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015072 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015073 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015074 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015075 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015076 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15077 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015078 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015079
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015080 /*
15081 * 3 The {final} of the {base type definition} must not contain restriction.
15082 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015083 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015084 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15085 xmlSchemaPCustomErr(ctxt,
15086 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015087 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015088 "The 'final' of its base type '%s' must not contain "
15089 "'restriction'",
15090 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015091 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015092 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015093 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015094
15095 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015096 * 2 All simple type definitions must be derived ultimately from the ·simple
15097 * ur-type definition (so· circular definitions are disallowed). That is, it
15098 * must be possible to reach a built-in primitive datatype or the ·simple
15099 * ur-type definition· by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015100 *
15101 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000015102 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015103 return (0);
15104}
15105
15106/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015107 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000015108 * @ctxt: the schema parser context
15109 * @type: the simple type definition
15110 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015111 * Schema Component Constraint:
15112 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15113
15114 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015115 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000015116 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015117 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015118 * a positive error code otherwise.
15119 */
15120static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015121xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015122 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015123{
Daniel Veillardc0826a72004-08-10 14:17:33 +000015124 xmlChar *str = NULL;
15125
Daniel Veillard01fa6152004-06-29 17:04:39 +000015126 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015127 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15128 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015129 return (-1);
15130 }
15131
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015132 if (WXS_IS_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015133 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015134 /*
15135 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000015136 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015137 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015138 if (! WXS_IS_ATOMIC(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015139 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015140 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015141 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015142 "The base type '%s' is not an atomic simple type",
15143 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015144 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015145 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15146 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015147 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000015148 * restriction.
15149 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015150 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015151 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015152 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015153 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015154 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015155 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015156 "The final of its base type '%s' must not contain 'restriction'",
15157 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015158 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015159 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15160 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015161
15162 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000015163 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015164 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000015165 * Primitive datatypes.
15166 */
15167 if (type->facets != NULL) {
15168 xmlSchemaFacetPtr facet;
15169 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015170
Daniel Veillard01fa6152004-06-29 17:04:39 +000015171 primitive = xmlSchemaGetPrimitiveType(type);
15172 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015173 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15174 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015175 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015176 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015177 facet = type->facets;
15178 do {
15179 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015180 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015181 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015182 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015183 type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015184 }
15185 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015186 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015187 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015188 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015189 }
15190 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015191 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15192 * of the {base type definition} (call this BF),then the DF's {value}
15193 * must be a valid restriction of BF's {value} as defined in
15194 * [XML Schemas: Datatypes]."
15195 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015196 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015197 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015198 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015199 } else if (WXS_IS_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015200 xmlSchemaTypePtr itemType = NULL;
15201
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015202 itemType = type->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015203 if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015204 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15205 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015206 return (-1);
15207 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015208 if (WXS_IS_TYPE_NOT_FIXED(itemType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015209 xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015210 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015211 * 2.1 The {item type definition} must have a {variety} of atomic or
15212 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000015213 * must be atomic).
15214 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015215 if ((! WXS_IS_ATOMIC(itemType)) &&
15216 (! WXS_IS_UNION(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015217 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015218 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015219 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015220 "The item type '%s' does not have a variety of atomic or union",
15221 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015222 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015223 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015224 } else if (WXS_IS_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015225 xmlSchemaTypeLinkPtr member;
15226
15227 member = itemType->memberTypes;
15228 while (member != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015229 if (! WXS_IS_ATOMIC(member->type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015230 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015231 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015232 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015233 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015234 "member type '%s' of this item type is not atomic",
15235 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015236 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015237 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15238 }
15239 member = member->next;
15240 }
15241 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015242
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015243 if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015244 xmlSchemaFacetPtr facet;
15245 /*
15246 * This is the case if we have: <simpleType><list ..
15247 */
15248 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015249 * 2.3.1
15250 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000015251 * contain list.
15252 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015253 if (xmlSchemaTypeFinalContains(itemType,
15254 XML_SCHEMAS_TYPE_FINAL_LIST)) {
15255 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015256 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015257 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015258 "The final of its item type '%s' must not contain 'list'",
15259 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015260 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015261 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15262 }
15263 /*
15264 * 2.3.1.2 The {facets} must only contain the whiteSpace
15265 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015266 * OPTIMIZE TODO: the S4S already disallows any facet
15267 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015268 */
15269 if (type->facets != NULL) {
15270 facet = type->facets;
15271 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015272 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015273 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015274 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015275 type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015276 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15277 }
15278 facet = facet->next;
15279 } while (facet != NULL);
15280 }
15281 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015282 * MAYBE TODO: (Hmm, not really) Datatypes states:
15283 * A ·list· datatype can be ·derived· from an ·atomic· datatype
15284 * whose ·lexical space· allows space (such as string or anyURI)or
15285 * a ·union· datatype any of whose {member type definitions}'s
Daniel Veillard01fa6152004-06-29 17:04:39 +000015286 * ·lexical space· allows space.
15287 */
15288 } else {
15289 /*
15290 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015291 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015292 */
15293 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015294 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000015295 * 2.3.2.1 The {base type definition} must have a {variety} of list.
15296 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015297 if (! WXS_IS_LIST(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015298 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015299 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015300 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015301 "The base type '%s' must be a list type",
15302 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015303 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015304 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15305 }
15306 /*
15307 * 2.3.2.2 The {final} of the {base type definition} must not
15308 * contain restriction.
15309 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015310 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015311 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015312 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015313 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015314 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015315 "The 'final' of the base type '%s' must not contain 'restriction'",
15316 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015317 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015318 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15319 }
15320 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015321 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000015322 * from the {base type definition}'s {item type definition} given
15323 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
15324 */
15325 {
15326 xmlSchemaTypePtr baseItemType;
15327
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015328 baseItemType = type->baseType->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015329 if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015330 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15331 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015332 return (-1);
15333 }
15334 if ((itemType != baseItemType) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015335 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015336 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015337 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015338 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015339 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015340 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015341 "The item type '%s' is not validly derived from "
15342 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015343 xmlSchemaGetComponentQName(&str, itemType),
15344 xmlSchemaGetComponentQName(&strBIT, baseItemType),
15345 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015346
15347 FREE_AND_NULL(str)
15348 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015349 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015350 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15351 }
15352 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015353
Daniel Veillard01fa6152004-06-29 17:04:39 +000015354 if (type->facets != NULL) {
15355 xmlSchemaFacetPtr facet;
15356 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015357 /*
15358 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000015359 * and enumeration facet components are allowed among the {facets}.
15360 */
15361 facet = type->facets;
15362 do {
15363 switch (facet->type) {
15364 case XML_SCHEMA_FACET_LENGTH:
15365 case XML_SCHEMA_FACET_MINLENGTH:
15366 case XML_SCHEMA_FACET_MAXLENGTH:
15367 case XML_SCHEMA_FACET_WHITESPACE:
15368 /*
15369 * TODO: 2.5.1.2 List datatypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015370 * The value of ·whiteSpace· is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015371 */
15372 case XML_SCHEMA_FACET_PATTERN:
15373 case XML_SCHEMA_FACET_ENUMERATION:
15374 break;
15375 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015376 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015377 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015378 type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015379 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015380 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000015381 * invalid facets.
15382 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015383 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015384 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015385 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015386 facet = facet->next;
15387 } while (facet != NULL);
15388 if (ok == 0)
15389 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15390 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015391 * SPEC (2.3.2.5) (same as 1.3.2)
15392 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015393 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015394 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015395 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015396 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015397 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015398 } else if (WXS_IS_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015399 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015400 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000015401 * atomic or list.
15402 */
15403 xmlSchemaTypeLinkPtr member;
15404
15405 member = type->memberTypes;
15406 while (member != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015407 if (WXS_IS_TYPE_NOT_FIXED(member->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015408 xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015409
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015410 if ((! WXS_IS_ATOMIC(member->type)) &&
15411 (! WXS_IS_LIST(member->type))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015412 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015413 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015414 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015415 "The member type '%s' is neither an atomic, nor a list type",
15416 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015417 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015418 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15419 }
15420 member = member->next;
15421 }
15422 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015423 * 3.3.1 If the {base type definition} is the ·simple ur-type
15424 * definition·
Daniel Veillard01fa6152004-06-29 17:04:39 +000015425 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015426 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015427 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015428 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000015429 * {final} which does not contain union.
15430 */
15431 member = type->memberTypes;
15432 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015433 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015434 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015435 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015436 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015437 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015438 "The 'final' of member type '%s' contains 'union'",
15439 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015440 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015441 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15442 }
15443 member = member->next;
15444 }
15445 /*
15446 * 3.3.1.2 The {facets} must be empty.
15447 */
15448 if (type->facetSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015449 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015450 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015451 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015452 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015453 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15454 }
15455 } else {
15456 /*
15457 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015458 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015459 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015460 if (! WXS_IS_UNION(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015461 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015462 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015463 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015464 "The base type '%s' is not a union type",
15465 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015466 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015467 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15468 }
15469 /*
15470 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15471 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015472 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015473 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015474 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015475 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015476 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015477 "The 'final' of its base type '%s' must not contain 'restriction'",
15478 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015479 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015480 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15481 }
15482 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015483 * 3.3.2.3 The {member type definitions}, in order, must be validly
15484 * derived from the corresponding type definitions in the {base
15485 * type definition}'s {member type definitions} given the empty set,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015486 * as defined in Type Derivation OK (Simple) (§3.14.6).
15487 */
15488 {
15489 xmlSchemaTypeLinkPtr baseMember;
15490
15491 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015492 * OPTIMIZE: if the type is restricting, it has no local defined
15493 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015494 * thus a check for equality can be skipped.
15495 */
15496 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015497 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015498 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000015499 * types of it's base type. This check seems not necessary with
15500 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015501 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015502 */
15503 if (type->memberTypes != NULL) {
15504 member = type->memberTypes;
15505 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015506 if ((member == NULL) && (baseMember != NULL)) {
15507 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15508 "different number of member types in base");
15509 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015510 while (member != NULL) {
15511 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015512 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15513 "different number of member types in base");
Daniel Veillard14b56432006-03-09 18:41:40 +000015514 } else if ((member->type != baseMember->type) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015515 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015516 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015517 xmlChar *strBMT = NULL, *strBT = NULL;
15518
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015519 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015520 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015521 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015522 "The member type %s is not validly "
15523 "derived from its corresponding member "
15524 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015525 xmlSchemaGetComponentQName(&str, member->type),
15526 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15527 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015528 FREE_AND_NULL(str)
15529 FREE_AND_NULL(strBMT)
15530 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015531 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015532 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015533 member = member->next;
15534 baseMember = baseMember->next;
15535 }
15536 }
15537 }
15538 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015539 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000015540 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015541 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015542 if (type->facets != NULL) {
15543 xmlSchemaFacetPtr facet;
15544 int ok = 1;
15545
15546 facet = type->facets;
15547 do {
15548 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15549 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015550 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015551 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015552 type, facet);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015553 ok = 0;
15554 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015555 facet = facet->next;
15556 } while (facet != NULL);
15557 if (ok == 0)
15558 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015559
Daniel Veillard01fa6152004-06-29 17:04:39 +000015560 }
15561 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015562 * SPEC (3.3.2.5) (same as 1.3.2)
15563 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015564 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015565 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015566 */
15567 }
15568 }
15569
15570 return (0);
15571}
15572
15573/**
15574 * xmlSchemaCheckSRCSimpleType:
15575 * @ctxt: the schema parser context
15576 * @type: the simple type definition
15577 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015578 * Checks crc-simple-type constraints.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015579 *
15580 * Returns 0 if the constraints are satisfied,
15581 * if not a positive error code and -1 on internal
15582 * errors.
15583 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015584#if 0
Daniel Veillard01fa6152004-06-29 17:04:39 +000015585static int
15586xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15587 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015588{
15589 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000015590 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015591 * must satisfy the conditions set out in Constraints on Simple Type
15592 * Definition Schema Components (§3.14.6).
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015593 */
15594 if (WXS_IS_RESTRICTION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015595 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015596 * src-simple-type.2 "If the <restriction> alternative is chosen,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015597 * either it must have a base [attribute] or a <simpleType> among its
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015598 * [children], but not both."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015599 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015600 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015601 /*
15602 *
15603 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015604 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015605 /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015606 * an itemType [attribute] or a <simpleType> among its [children],
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015607 * but not both."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015608 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015609 * NOTE: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015610 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015611 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015612 /*
15613 * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015614 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015615 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015616 return (0);
15617}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015618#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000015619
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015620static int
15621xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15622{
15623 if (ctxt->vctxt == NULL) {
15624 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15625 if (ctxt->vctxt == NULL) {
15626 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015627 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015628 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015629 "failed to create a temp. validation context.\n",
15630 NULL, NULL);
15631 return (-1);
15632 }
15633 /* TODO: Pass user data. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015634 xmlSchemaSetValidErrors(ctxt->vctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000015635 ctxt->error, ctxt->warning, ctxt->errCtxt);
15636 xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15637 ctxt->serror, ctxt->errCtxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015638 }
15639 return (0);
15640}
15641
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015642static int
15643xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15644 xmlNodePtr node,
15645 xmlSchemaTypePtr type,
15646 const xmlChar *value,
15647 xmlSchemaValPtr *retVal,
15648 int fireErrors,
15649 int normalize,
15650 int isNormalized);
15651
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015652/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015653 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015654 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015655 * @type: the simple type definition
15656 * @value: the default value
15657 * @node: an optional node (the holder of the value)
15658 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015659 * Schema Component Constraint: Element Default Valid (Immediate)
15660 * (cos-valid-default)
15661 * This will be used by the parser only. For the validator there's
15662 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015663 *
15664 * Returns 0 if the constraints are satisfied,
15665 * if not, a positive error code and -1 on internal
15666 * errors.
15667 */
15668static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015669xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15670 xmlNodePtr node,
15671 xmlSchemaTypePtr type,
15672 const xmlChar *value,
15673 xmlSchemaValPtr *val)
15674{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015675 int ret = 0;
15676
15677 /*
15678 * cos-valid-default:
15679 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015680 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015681 * definition the appropriate case among the following must be true:
15682 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015683 if WXS_IS_COMPLEX(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015684 /*
15685 * Complex type.
15686 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015687 * SPEC (2.1) "its {content type} must be a simple type definition
15688 * or mixed."
15689 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015690 * type}'s particle must be ·emptiable· as defined by
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015691 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000015692 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015693 if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15694 ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015695 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015696 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015697 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015698 WXS_BASIC_CAST type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015699 "For a string to be a valid default, the type definition "
15700 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015701 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015702 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15703 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015704 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015705 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015706 * 1 If the type definition is a simple type definition, then the string
15707 * must be ·valid· with respect to that definition as defined by String
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015708 * Valid (§3.14.4).
15709 *
15710 * AND
15711 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015712 * 2.2.1 If the {content type} is a simple type definition, then the
15713 * string must be ·valid· with respect to that simple type definition
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015714 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015715 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015716 if (WXS_IS_SIMPLE(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015717 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015718 type, value, val, 1, 1, 0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015719 else if (WXS_HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015720 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015721 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015722 else
15723 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015724
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015725 if (ret < 0) {
15726 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15727 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015728 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015729
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015730 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000015731}
15732
15733/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015734 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000015735 * @ctxt: the schema parser context
15736 * @type: the complex type definition
15737 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015738 *.(4.6) Constraints on Complex Type Definition Schema Components
15739 * Schema Component Constraint:
15740 * Complex Type Definition Properties Correct (ct-props-correct)
15741 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000015742 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015743 * Returns 0 if the constraints are satisfied, a positive
15744 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000015745 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015746static int
15747xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15748 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000015749{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015750 /*
15751 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15752 *
15753 * SPEC (1) "The values of the properties of a complex type definition must
15754 * be as described in the property tableau in The Complex Type Definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015755 * Schema Component (§3.4.1), modulo the impact of Missing
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015756 * Sub-components (§5.3)."
15757 */
15758 if ((type->baseType != NULL) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015759 (WXS_IS_SIMPLE(type->baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015760 (WXS_IS_EXTENSION(type) == 0)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015761 /*
15762 * SPEC (2) "If the {base type definition} is a simple type definition,
15763 * the {derivation method} must be extension."
15764 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015765 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015766 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015767 NULL, WXS_BASIC_CAST type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015768 "If the base type is a simple type, the derivation method must be "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015769 "'extension'", NULL, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015770 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015771 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015772 /*
15773 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
15774 * definition·. That is, it must be possible to reach the ·ur-type
15775 * definition by repeatedly following the {base type definition}."
15776 *
15777 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015778 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015779 /*
15780 * NOTE that (4) and (5) need the following:
15781 * - attribute uses need to be already inherited (apply attr. prohibitions)
15782 * - attribute group references need to be expanded already
15783 * - simple types need to be typefixed already
15784 */
15785 if (type->attrUses &&
15786 (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15787 {
15788 xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15789 xmlSchemaAttributeUsePtr use, tmp;
15790 int i, j, hasId = 0;
15791
15792 for (i = uses->nbItems -1; i >= 0; i--) {
15793 use = uses->items[i];
15794
15795 /*
15796 * SPEC ct-props-correct
15797 * (4) "Two distinct attribute declarations in the
15798 * {attribute uses} must not have identical {name}s and
15799 * {target namespace}s."
15800 */
15801 if (i > 0) {
15802 for (j = i -1; j >= 0; j--) {
15803 tmp = uses->items[j];
15804 if ((WXS_ATTRUSE_DECL_NAME(use) ==
15805 WXS_ATTRUSE_DECL_NAME(tmp)) &&
15806 (WXS_ATTRUSE_DECL_TNS(use) ==
15807 WXS_ATTRUSE_DECL_TNS(tmp)))
15808 {
15809 xmlChar *str = NULL;
15810
15811 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15812 XML_SCHEMAP_AG_PROPS_CORRECT,
15813 NULL, WXS_BASIC_CAST type,
15814 "Duplicate %s",
15815 xmlSchemaGetComponentDesignation(&str, use),
15816 NULL);
15817 FREE_AND_NULL(str);
15818 /*
15819 * Remove the duplicate.
15820 */
15821 if (xmlSchemaItemListRemove(uses, i) == -1)
15822 goto exit_failure;
15823 goto next_use;
15824 }
15825 }
15826 }
15827 /*
15828 * SPEC ct-props-correct
15829 * (5) "Two distinct attribute declarations in the
15830 * {attribute uses} must not have {type definition}s which
15831 * are or are derived from ID."
15832 */
15833 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15834 if (xmlSchemaIsDerivedFromBuiltInType(
15835 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15836 {
15837 if (hasId) {
15838 xmlChar *str = NULL;
15839
15840 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15841 XML_SCHEMAP_AG_PROPS_CORRECT,
15842 NULL, WXS_BASIC_CAST type,
15843 "There must not exist more than one attribute "
15844 "declaration of type 'xs:ID' "
15845 "(or derived from 'xs:ID'). The %s violates this "
15846 "constraint",
15847 xmlSchemaGetComponentDesignation(&str, use),
15848 NULL);
15849 FREE_AND_NULL(str);
15850 if (xmlSchemaItemListRemove(uses, i) == -1)
15851 goto exit_failure;
15852 }
15853
15854 hasId = 1;
15855 }
15856 }
15857next_use: {}
15858 }
15859 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015860 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015861exit_failure:
15862 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +000015863}
15864
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015865static int
15866xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
15867 xmlSchemaTypePtr typeB)
15868{
15869 /*
15870 * TODO: This should implement component-identity
15871 * in the future.
15872 */
15873 if ((typeA == NULL) || (typeB == NULL))
15874 return (0);
15875 return (typeA == typeB);
15876}
15877
15878/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015879 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015880 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015881 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015882 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015883 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015884 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015885 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015886 * Type Derivation OK (Complex) (cos-ct-derived-ok)
15887 *
15888 * STATUS: completed
15889 *
15890 * Returns 0 if the constraints are satisfied, or 1
15891 * if not.
15892 */
15893static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015894xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015895 xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015896 xmlSchemaTypePtr baseType,
15897 int set)
15898{
15899 int equal = xmlSchemaAreEqualTypes(type, baseType);
15900 /* TODO: Error codes. */
15901 /*
15902 * SPEC "For a complex type definition (call it D, for derived)
15903 * to be validly derived from a type definition (call this
15904 * B, for base) given a subset of {extension, restriction}
15905 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015906 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015907 if (! equal) {
15908 /*
15909 * SPEC (1) "If B and D are not the same type definition, then the
15910 * {derivation method} of D must not be in the subset."
15911 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015912 if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
15913 ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015914 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015915 } else {
15916 /*
15917 * SPEC (2.1) "B and D must be the same type definition."
15918 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015919 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015920 }
15921 /*
15922 * SPEC (2.2) "B must be D's {base type definition}."
15923 */
15924 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015925 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015926 /*
15927 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
15928 * definition·."
15929 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015930 if (WXS_IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015931 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015932
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015933 if (WXS_IS_COMPLEX(type->baseType)) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015934 /*
15935 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
15936 * must be validly derived from B given the subset as defined by this
15937 * constraint."
15938 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015939 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015940 baseType, set));
15941 } else {
15942 /*
15943 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
15944 * must be validly derived from B given the subset as defined in Type
15945 * Derivation OK (Simple) (§3.14.6).
15946 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015947 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015948 baseType, set));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015949 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015950}
15951
15952/**
15953 * xmlSchemaCheckCOSDerivedOK:
15954 * @type: the derived simple type definition
15955 * @baseType: the base type definition
15956 *
15957 * Calls:
15958 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015959 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015960 * Checks wheter @type can be validly derived from @baseType.
15961 *
15962 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015963 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015964static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015965xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015966 xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015967 xmlSchemaTypePtr baseType,
15968 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015969{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015970 if (WXS_IS_SIMPLE(type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015971 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015972 else
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015973 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015974}
15975
William M. Brack2f2a6632004-08-20 23:09:47 +000015976/**
15977 * xmlSchemaCheckCOSCTExtends:
15978 * @ctxt: the schema parser context
15979 * @type: the complex type definition
15980 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015981 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015982 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015983 * Derivation Valid (Extension) (cos-ct-extends)
15984 *
15985 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015986 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015987 * (1.5)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015988 * (1.4.3.2.2.2) "Particle Valid (Extension)"
William M. Brack2f2a6632004-08-20 23:09:47 +000015989 *
15990 * Returns 0 if the constraints are satisfied, a positive
15991 * error code if not and -1 if an internal error occured.
15992 */
15993static int
15994xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
15995 xmlSchemaTypePtr type)
15996{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015997 xmlSchemaTypePtr base = type->baseType;
15998 /*
15999 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16000 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000016001 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016002 /*
16003 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016004 * then all of the following must be true:"
16005 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016006 if (WXS_IS_COMPLEX(base)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000016007 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016008 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016009 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000016010 */
16011 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16012 xmlSchemaPCustomErr(ctxt,
16013 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016014 WXS_BASIC_CAST type, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000016015 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016016 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000016017 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16018 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016019
16020 /*
16021 * ATTENTION: The constrains (1.2) and (1.3) are not applied,
16022 * since they are automatically satisfied through the
16023 * inheriting mechanism.
16024 * Note that even if redefining components, the inheriting mechanism
16025 * is used.
16026 */
16027#if 0
William M. Brack2f2a6632004-08-20 23:09:47 +000016028 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016029 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016030 * uses}
16031 * of the complex type definition itself, that is, for every attribute
16032 * use in the {attribute uses} of the {base type definition}, there
16033 * must be an attribute use in the {attribute uses} of the complex
16034 * type definition itself whose {attribute declaration} has the same
16035 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016036 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000016037 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016038 if (base->attrUses != NULL) {
16039 int i, j, found;
16040 xmlSchemaAttributeUsePtr use, buse;
William M. Brack2f2a6632004-08-20 23:09:47 +000016041
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016042 for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16043 buse = (WXS_LIST_CAST base->attrUses)->items[i];
16044 found = 0;
16045 if (type->attrUses != NULL) {
16046 use = (WXS_LIST_CAST type->attrUses)->items[j];
16047 for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16048 {
16049 if ((WXS_ATTRUSE_DECL_NAME(use) ==
16050 WXS_ATTRUSE_DECL_NAME(buse)) &&
16051 (WXS_ATTRUSE_DECL_TNS(use) ==
16052 WXS_ATTRUSE_DECL_TNS(buse)) &&
16053 (WXS_ATTRUSE_TYPEDEF(use) ==
16054 WXS_ATTRUSE_TYPEDEF(buse))
16055 {
16056 found = 1;
16057 break;
16058 }
16059 }
16060 }
16061 if (! found) {
16062 xmlChar *str = NULL;
16063
16064 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16065 XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16066 NULL, WXS_BASIC_CAST type,
16067 /*
16068 * TODO: The report does not indicate that also the
16069 * type needs to be the same.
16070 */
16071 "This type is missing a matching correspondent "
16072 "for its {base type}'s %s in its {attribute uses}",
16073 xmlSchemaGetComponentDesignation(&str,
16074 buse->children),
16075 NULL);
16076 FREE_AND_NULL(str)
16077 }
16078 }
16079 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016080 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016081 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16082 * definition must also have one, and the base type definition's
16083 * {attribute wildcard}'s {namespace constraint} must be a subset
16084 * of the complex type definition's {attribute wildcard}'s {namespace
16085 * constraint}, as defined by Wildcard Subset (§3.10.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016086 */
16087
16088 /*
16089 * MAYBE TODO: Enable if ever needed. But this will be needed only
16090 * if created the type via a schema construction API.
16091 */
16092 if (base->attributeWildcard != NULL) {
16093 if (type->attributeWilcard == NULL) {
16094 xmlChar *str = NULL;
16095
16096 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16097 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16098 NULL, type,
16099 "The base %s has an attribute wildcard, "
16100 "but this type is missing an attribute wildcard",
16101 xmlSchemaGetComponentDesignation(&str, base));
16102 FREE_AND_NULL(str)
16103
16104 } else if (xmlSchemaCheckCOSNSSubset(
16105 base->attributeWildcard, type->attributeWildcard))
16106 {
16107 xmlChar *str = NULL;
16108
16109 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16110 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16111 NULL, type,
16112 "The attribute wildcard is not a valid "
16113 "superset of the one in the base %s",
16114 xmlSchemaGetComponentDesignation(&str, base));
16115 FREE_AND_NULL(str)
16116 }
16117 }
16118#endif
16119 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016120 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000016121 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016122 if ((type->contentTypeDef != NULL) &&
16123 (type->contentTypeDef == base->contentTypeDef)) {
16124 /*
16125 * SPEC (1.4.1) "The {content type} of the {base type definition}
16126 * and the {content type} of the complex type definition itself
16127 * must be the same simple type definition"
16128 * PASS
16129 */
16130 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16131 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16132 /*
16133 * SPEC (1.4.2) "The {content type} of both the {base type
16134 * definition} and the complex type definition itself must
16135 * be empty."
16136 * PASS
16137 */
16138 } else {
16139 /*
16140 * SPEC (1.4.3) "All of the following must be true:"
16141 */
16142 if (type->subtypes == NULL) {
16143 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016144 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016145 * definition itself must specify a particle.
16146 */
16147 xmlSchemaPCustomErr(ctxt,
16148 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016149 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016150 "The content type must specify a particle", NULL);
16151 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16152 }
16153 /*
16154 * SPEC (1.4.3.2) "One of the following must be true:"
16155 */
16156 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16157 /*
16158 * SPEC (1.4.3.2.1) "The {content type} of the {base type
16159 * definition} must be empty.
16160 * PASS
16161 */
16162 } else {
16163 /*
16164 * SPEC (1.4.3.2.2) "All of the following must be true:"
16165 */
16166 if ((type->contentType != base->contentType) ||
16167 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16168 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16169 /*
16170 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16171 * or both must be element-only."
16172 */
16173 xmlSchemaPCustomErr(ctxt,
16174 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016175 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016176 "The content type of both, the type and its base "
16177 "type, must either 'mixed' or 'element-only'", NULL);
16178 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016179 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016180 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016181 * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016182 * complex type definition must be a ·valid extension·
16183 * of the {base type definition}'s particle, as defined
16184 * in Particle Valid (Extension) (§3.9.6)."
16185 *
16186 * NOTE that we won't check "Particle Valid (Extension)",
16187 * since it is ensured by the derivation process in
16188 * xmlSchemaTypeFixup(). We need to implement this when heading
16189 * for a construction API
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016190 * TODO: !! This is needed to be checked if redefining a type !!
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016191 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016192 }
16193 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016194 * URGENT TODO (1.5)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016195 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016196 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016197 } else {
16198 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016199 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016200 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000016201 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016202 if (type->contentTypeDef != base) {
16203 /*
16204 * SPEC (2.1) "The {content type} must be the same simple type
16205 * definition."
16206 */
16207 xmlSchemaPCustomErr(ctxt,
16208 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016209 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016210 "The content type must be the simple base type", NULL);
16211 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16212 }
16213 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16214 /*
16215 * SPEC (2.2) "The {final} of the {base type definition} must not
16216 * contain extension"
16217 * NOTE that this is the same as (1.1).
16218 */
16219 xmlSchemaPCustomErr(ctxt,
16220 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016221 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016222 "The 'final' of the base type definition "
16223 "contains 'extension'", NULL);
16224 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016225 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016226 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016227 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016228}
16229
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016230/**
16231 * xmlSchemaCheckDerivationOKRestriction:
16232 * @ctxt: the schema parser context
16233 * @type: the complex type definition
16234 *
16235 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016236 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016237 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16238 *
16239 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016240 * missing:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016241 * (5.4.2) ???
16242 *
16243 * ATTENTION:
16244 * In XML Schema 1.1 this will be:
16245 * Validation Rule: Checking complex type subsumption
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016246 *
16247 * Returns 0 if the constraints are satisfied, a positive
16248 * error code if not and -1 if an internal error occured.
16249 */
16250static int
16251xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16252 xmlSchemaTypePtr type)
16253{
16254 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016255
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016256 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016257 * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016258 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016259 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016260 base = type->baseType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016261 if (! WXS_IS_COMPLEX(base)) {
16262 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16263 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16264 type->node, WXS_BASIC_CAST type,
16265 "The base type must be a complex type", NULL, NULL);
16266 return(ctxt->err);
16267 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016268 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16269 /*
16270 * SPEC (1) "The {base type definition} must be a complex type
16271 * definition whose {final} does not contain restriction."
16272 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016273 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16274 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16275 type->node, WXS_BASIC_CAST type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016276 "The 'final' of the base type definition "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016277 "contains 'restriction'", NULL, NULL);
16278 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016279 }
16280 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016281 * SPEC (2), (3) and (4)
16282 * Those are handled in a separate function, since the
16283 * same constraints are needed for redefinition of
16284 * attribute groups as well.
16285 */
16286 if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16287 XML_SCHEMA_ACTION_DERIVE,
16288 WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16289 type->attrUses, base->attrUses,
16290 type->attributeWildcard,
16291 base->attributeWildcard) == -1)
16292 {
16293 return(-1);
16294 }
16295 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016296 * SPEC (5) "One of the following must be true:"
16297 */
16298 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16299 /*
16300 * SPEC (5.1) "The {base type definition} must be the
16301 * ·ur-type definition·."
16302 * PASS
16303 */
16304 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16305 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16306 /*
16307 * SPEC (5.2.1) "The {content type} of the complex type definition
16308 * must be a simple type definition"
16309 *
16310 * SPEC (5.2.2) "One of the following must be true:"
16311 */
16312 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016313 (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16314 {
16315 int err;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016316 /*
16317 * SPEC (5.2.2.1) "The {content type} of the {base type
16318 * definition} must be a simple type definition from which
16319 * the {content type} is validly derived given the empty
16320 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016321 *
16322 * ATTENTION TODO: This seems not needed if the type implicitely
16323 * derived from the base type.
16324 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016325 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016326 err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16327 type->contentTypeDef, base->contentTypeDef, 0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016328 if (err != 0) {
16329 xmlChar *strA = NULL, *strB = NULL;
16330
16331 if (err == -1)
16332 return(-1);
16333 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16334 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16335 NULL, WXS_BASIC_CAST type,
16336 "The {content type} %s is not validly derived from the "
16337 "base type's {content type} %s",
16338 xmlSchemaGetComponentDesignation(&strA,
16339 type->contentTypeDef),
16340 xmlSchemaGetComponentDesignation(&strB,
16341 base->contentTypeDef));
16342 FREE_AND_NULL(strA);
16343 FREE_AND_NULL(strB);
16344 return(ctxt->err);
16345 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016346 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16347 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016348 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016349 /*
16350 * SPEC (5.2.2.2) "The {base type definition} must be mixed
16351 * and have a particle which is ·emptiable· as defined in
16352 * Particle Emptiable (§3.9.6)."
16353 * PASS
16354 */
16355 } else {
16356 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016357 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16358 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016359 "The content type of the base type must be either "
16360 "a simple type or 'mixed' and an emptiable particle", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016361 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016362 }
16363 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16364 /*
16365 * SPEC (5.3.1) "The {content type} of the complex type itself must
16366 * be empty"
16367 */
16368 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16369 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016370 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016371 * definition} must also be empty."
16372 * PASS
16373 */
16374 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16375 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16376 xmlSchemaIsParticleEmptiable(
16377 (xmlSchemaParticlePtr) base->subtypes)) {
16378 /*
16379 * SPEC (5.3.2.2) "The {content type} of the {base type
16380 * definition} must be elementOnly or mixed and have a particle
16381 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
16382 * PASS
16383 */
16384 } else {
16385 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016386 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16387 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016388 "The content type of the base type must be either "
16389 "empty or 'mixed' (or 'elements-only') and an emptiable "
16390 "particle", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016391 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016392 }
16393 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016394 WXS_HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016395 /*
16396 * SPEC (5.4.1.1) "The {content type} of the complex type definition
16397 * itself must be element-only"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016398 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016399 if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016400 /*
16401 * SPEC (5.4.1.2) "The {content type} of the complex type
16402 * definition itself and of the {base type definition} must be
16403 * mixed"
16404 */
16405 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016406 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16407 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016408 "If the content type is 'mixed', then the content type of the "
16409 "base type must also be 'mixed'", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016410 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016411 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016412 /*
16413 * SPEC (5.4.2) "The particle of the complex type definition itself
16414 * must be a ·valid restriction· of the particle of the {content
16415 * type} of the {base type definition} as defined in Particle Valid
16416 * (Restriction) (§3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016417 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016418 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016419 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016420 } else {
16421 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016422 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16423 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016424 "The type is not a valid restriction of its base type", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016425 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016426 }
16427 return (0);
16428}
16429
16430/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016431 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016432 * @ctxt: the schema parser context
16433 * @type: the complex type definition
16434 *
16435 * (3.4.6) Constraints on Complex Type Definition Schema Components
16436 *
16437 * Returns 0 if the constraints are satisfied, a positive
16438 * error code if not and -1 if an internal error occured.
16439 */
16440static int
16441xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16442 xmlSchemaTypePtr type)
16443{
16444 int ret;
16445 /*
16446 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016447 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016448 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16449 if (ret != 0)
16450 return (ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016451 if (WXS_IS_EXTENSION(type))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016452 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16453 else
16454 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16455 return (ret);
16456}
16457
16458/**
16459 * xmlSchemaCheckSRCCT:
16460 * @ctxt: the schema parser context
16461 * @type: the complex type definition
16462 *
16463 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016464 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016465 * Complex Type Definition Representation OK (src-ct)
16466 *
16467 * Returns 0 if the constraints are satisfied, a positive
16468 * error code if not and -1 if an internal error occured.
16469 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016470static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016471xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016472 xmlSchemaTypePtr type)
16473{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016474 xmlSchemaTypePtr base;
16475 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016476
16477 /*
16478 * TODO: Adjust the error codes here, as I used
16479 * XML_SCHEMAP_SRC_CT_1 only yet.
16480 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016481 base = type->baseType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016482 if (! WXS_HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016483 /*
16484 * 1 If the <complexContent> alternative is chosen, the type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016485 * ·resolved· to by the ·actual value· of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016486 * must be a complex type definition;
16487 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016488 if (! WXS_IS_COMPLEX(base)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016489 xmlChar *str = NULL;
16490 xmlSchemaPCustomErr(ctxt,
16491 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016492 WXS_BASIC_CAST type, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016493 "If using <complexContent>, the base type is expected to be "
16494 "a complex type. The base type '%s' is a simple type",
16495 xmlSchemaFormatQName(&str, base->targetNamespace,
16496 base->name));
16497 FREE_AND_NULL(str)
16498 return (XML_SCHEMAP_SRC_CT_1);
16499 }
16500 } else {
16501 /*
16502 * SPEC
16503 * 2 If the <simpleContent> alternative is chosen, all of the
16504 * following must be true:
16505 * 2.1 The type definition ·resolved· to by the ·actual value· of the
16506 * base [attribute] must be one of the following:
16507 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016508 if (WXS_IS_SIMPLE(base)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016509 if (WXS_IS_EXTENSION(type) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016510 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016511 /*
16512 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016513 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016514 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016515 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016516 xmlSchemaPCustomErr(ctxt,
16517 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016518 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016519 "If using <simpleContent> and <restriction>, the base "
16520 "type must be a complex type. The base type '%s' is "
16521 "a simple type",
16522 xmlSchemaFormatQName(&str, base->targetNamespace,
16523 base->name));
16524 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016525 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016526 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016527 } else {
16528 /* Base type is a complex type. */
16529 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16530 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16531 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016532 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016533 * simple type definition;
16534 * PASS
16535 */
16536 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016537 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016538 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016539 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016540 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016541 type->name);
16542 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016543 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016544 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016545 (WXS_IS_RESTRICTION(type))) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016546
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016547 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016548 * 2.1.2 only if the <restriction> alternative is also
16549 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016550 * is mixed and a particle emptiable.
16551 */
16552 if (! xmlSchemaIsParticleEmptiable(
16553 (xmlSchemaParticlePtr) base->subtypes)) {
16554 ret = XML_SCHEMAP_SRC_CT_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016555 } else
16556 /*
16557 * Attention: at this point the <simpleType> child is in
16558 * ->contentTypeDef (put there during parsing).
16559 */
16560 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016561 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016562 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016563 * 2.2 If clause 2.1.2 above is satisfied, then there
16564 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016565 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016566 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016567 /* TODO: Change error code to ..._SRC_CT_2_2. */
16568 xmlSchemaPCustomErr(ctxt,
16569 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016570 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016571 "A <simpleType> is expected among the children "
16572 "of <restriction>, if <simpleContent> is used and "
16573 "the base type '%s' is a complex type",
16574 xmlSchemaFormatQName(&str, base->targetNamespace,
16575 base->name));
16576 FREE_AND_NULL(str)
16577 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016578 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016579 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016580 ret = XML_SCHEMAP_SRC_CT_1;
16581 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016582 }
16583 if (ret > 0) {
16584 xmlChar *str = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016585 if (WXS_IS_RESTRICTION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016586 xmlSchemaPCustomErr(ctxt,
16587 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016588 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016589 "If <simpleContent> and <restriction> is used, the "
16590 "base type must be a simple type or a complex type with "
16591 "mixed content and particle emptiable. The base type "
16592 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016593 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016594 base->name));
16595 } else {
16596 xmlSchemaPCustomErr(ctxt,
16597 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016598 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016599 "If <simpleContent> and <extension> is used, the "
16600 "base type must be a simple type. The base type '%s' "
16601 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016602 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016603 base->name));
16604 }
16605 FREE_AND_NULL(str)
16606 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016607 }
16608 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016609 * SPEC (3) "The corresponding complex type definition component must
16610 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016611 * Definition Schema Components (§3.4.6);"
16612 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016613 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016614 /*
16615 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016616 * above for {attribute wildcard} is satisfied, the intensional
16617 * intersection must be expressible, as defined in Attribute Wildcard
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016618 * Intersection (§3.10.6).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016619 * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016620 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016621 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016622}
William M. Brack2f2a6632004-08-20 23:09:47 +000016623
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016624#ifdef ENABLE_PARTICLE_RESTRICTION
16625/**
16626 * xmlSchemaCheckParticleRangeOK:
16627 * @ctxt: the schema parser context
16628 * @type: the complex type definition
16629 *
16630 * (3.9.6) Constraints on Particle Schema Components
16631 * Schema Component Constraint:
16632 * Occurrence Range OK (range-ok)
16633 *
16634 * STATUS: complete
16635 *
16636 * Returns 0 if the constraints are satisfied, a positive
16637 * error code if not and -1 if an internal error occured.
16638 */
16639static int
16640xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16641 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016642{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016643 if (rmin < bmin)
16644 return (1);
16645 if ((bmax != UNBOUNDED) &&
16646 (rmax > bmax))
16647 return (1);
16648 return (0);
16649}
16650
16651/**
16652 * xmlSchemaCheckRCaseNameAndTypeOK:
16653 * @ctxt: the schema parser context
16654 * @r: the restricting element declaration particle
16655 * @b: the base element declaration particle
16656 *
16657 * (3.9.6) Constraints on Particle Schema Components
16658 * Schema Component Constraint:
16659 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16660 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016661 *
16662 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016663 * MISSING (3.2.3)
16664 * CLARIFY: (3.2.2)
16665 *
16666 * Returns 0 if the constraints are satisfied, a positive
16667 * error code if not and -1 if an internal error occured.
16668 */
16669static int
16670xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16671 xmlSchemaParticlePtr r,
16672 xmlSchemaParticlePtr b)
16673{
16674 xmlSchemaElementPtr elemR, elemB;
16675
16676 /* TODO: Error codes (rcase-NameAndTypeOK). */
16677 elemR = (xmlSchemaElementPtr) r->children;
16678 elemB = (xmlSchemaElementPtr) b->children;
16679 /*
16680 * SPEC (1) "The declarations' {name}s and {target namespace}s are
16681 * the same."
16682 */
16683 if ((elemR != elemB) &&
16684 ((! xmlStrEqual(elemR->name, elemB->name)) ||
16685 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16686 return (1);
16687 /*
16688 * SPEC (2) "R's occurrence range is a valid restriction of B's
16689 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16690 */
16691 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16692 b->minOccurs, b->maxOccurs) != 0)
16693 return (1);
16694 /*
16695 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16696 * {scope} are global."
16697 */
16698 if (elemR == elemB)
16699 return (0);
16700 /*
16701 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16702 */
16703 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16704 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16705 return (1);
16706 /*
16707 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16708 * or is not fixed, or R's declaration's {value constraint} is fixed
16709 * with the same value."
16710 */
16711 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16712 ((elemR->value == NULL) ||
16713 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16714 /* TODO: Equality of the initial value or normalized or canonical? */
16715 (! xmlStrEqual(elemR->value, elemB->value))))
16716 return (1);
16717 /*
16718 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16719 * definitions} is a subset of B's declaration's {identity-constraint
16720 * definitions}, if any."
16721 */
16722 if (elemB->idcs != NULL) {
16723 /* TODO */
16724 }
16725 /*
16726 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16727 * superset of B's declaration's {disallowed substitutions}."
16728 */
16729 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16730 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16731 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16732 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16733 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16734 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16735 return (1);
16736 /*
16737 * SPEC (3.2.5) "R's {type definition} is validly derived given
16738 * {extension, list, union} from B's {type definition}"
16739 *
16740 * BADSPEC TODO: What's the point of adding "list" and "union" to the
16741 * set, if the corresponding constraints handle "restriction" and
16742 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016743 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016744 */
16745 {
16746 int set = 0;
16747
16748 set |= SUBSET_EXTENSION;
16749 set |= SUBSET_LIST;
16750 set |= SUBSET_UNION;
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016751 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016752 elemB->subtypes, set) != 0)
16753 return (1);
16754 }
16755 return (0);
16756}
16757
16758/**
16759 * xmlSchemaCheckRCaseNSCompat:
16760 * @ctxt: the schema parser context
16761 * @r: the restricting element declaration particle
16762 * @b: the base wildcard particle
16763 *
16764 * (3.9.6) Constraints on Particle Schema Components
16765 * Schema Component Constraint:
16766 * Particle Derivation OK (Elt:Any -- NSCompat)
16767 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016768 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016769 * STATUS: complete
16770 *
16771 * Returns 0 if the constraints are satisfied, a positive
16772 * error code if not and -1 if an internal error occured.
16773 */
16774static int
16775xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16776 xmlSchemaParticlePtr r,
16777 xmlSchemaParticlePtr b)
16778{
16779 /* TODO:Error codes (rcase-NSCompat). */
16780 /*
16781 * SPEC "For an element declaration particle to be a ·valid restriction·
16782 * of a wildcard particle all of the following must be true:"
16783 *
16784 * SPEC (1) "The element declaration's {target namespace} is ·valid·
16785 * with respect to the wildcard's {namespace constraint} as defined by
16786 * Wildcard allows Namespace Name (§3.10.4)."
16787 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016788 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016789 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16790 return (1);
16791 /*
16792 * SPEC (2) "R's occurrence range is a valid restriction of B's
16793 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16794 */
16795 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16796 b->minOccurs, b->maxOccurs) != 0)
16797 return (1);
16798
16799 return (0);
16800}
16801
16802/**
16803 * xmlSchemaCheckRCaseRecurseAsIfGroup:
16804 * @ctxt: the schema parser context
16805 * @r: the restricting element declaration particle
16806 * @b: the base model group particle
16807 *
16808 * (3.9.6) Constraints on Particle Schema Components
16809 * Schema Component Constraint:
16810 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16811 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016812 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016813 * STATUS: TODO
16814 *
16815 * Returns 0 if the constraints are satisfied, a positive
16816 * error code if not and -1 if an internal error occured.
16817 */
16818static int
16819xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16820 xmlSchemaParticlePtr r,
16821 xmlSchemaParticlePtr b)
16822{
16823 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16824 TODO
16825 return (0);
16826}
16827
16828/**
16829 * xmlSchemaCheckRCaseNSSubset:
16830 * @ctxt: the schema parser context
16831 * @r: the restricting wildcard particle
16832 * @b: the base wildcard particle
16833 *
16834 * (3.9.6) Constraints on Particle Schema Components
16835 * Schema Component Constraint:
16836 * Particle Derivation OK (Any:Any -- NSSubset)
16837 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016838 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016839 * STATUS: complete
16840 *
16841 * Returns 0 if the constraints are satisfied, a positive
16842 * error code if not and -1 if an internal error occured.
16843 */
16844static int
16845xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16846 xmlSchemaParticlePtr r,
16847 xmlSchemaParticlePtr b,
16848 int isAnyTypeBase)
16849{
16850 /* TODO: Error codes (rcase-NSSubset). */
16851 /*
16852 * SPEC (1) "R's occurrence range is a valid restriction of B's
16853 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16854 */
16855 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16856 b->minOccurs, b->maxOccurs))
16857 return (1);
16858 /*
16859 * SPEC (2) "R's {namespace constraint} must be an intensional subset
16860 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
16861 */
16862 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
16863 (xmlSchemaWildcardPtr) b->children))
16864 return (1);
16865 /*
16866 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
16867 * definition·, R's {process contents} must be identical to or stronger
16868 * than B's {process contents}, where strict is stronger than lax is
16869 * stronger than skip."
16870 */
16871 if (! isAnyTypeBase) {
16872 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
16873 ((xmlSchemaWildcardPtr) b->children)->processContents)
16874 return (1);
16875 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016876
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016877 return (0);
16878}
16879
16880/**
16881 * xmlSchemaCheckCOSParticleRestrict:
16882 * @ctxt: the schema parser context
16883 * @type: the complex type definition
16884 *
16885 * (3.9.6) Constraints on Particle Schema Components
16886 * Schema Component Constraint:
16887 * Particle Valid (Restriction) (cos-particle-restrict)
16888 *
16889 * STATUS: TODO
16890 *
16891 * Returns 0 if the constraints are satisfied, a positive
16892 * error code if not and -1 if an internal error occured.
16893 */
16894static int
16895xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
16896 xmlSchemaParticlePtr r,
16897 xmlSchemaParticlePtr b)
16898{
16899 int ret = 0;
16900
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016901 /*part = WXS_TYPE_PARTICLE(type);
16902 basePart = WXS_TYPE_PARTICLE(base);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016903 */
16904
16905 TODO
16906
16907 /*
16908 * SPEC (1) "They are the same particle."
16909 */
16910 if (r == b)
16911 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016912
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016913
16914 return (0);
16915}
16916
16917/**
16918 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
16919 * @ctxt: the schema parser context
16920 * @r: the model group particle
16921 * @b: the base wildcard particle
16922 *
16923 * (3.9.6) Constraints on Particle Schema Components
16924 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016925 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016926 * NSRecurseCheckCardinality)
16927 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016928 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016929 * STATUS: TODO: subst-groups
16930 *
16931 * Returns 0 if the constraints are satisfied, a positive
16932 * error code if not and -1 if an internal error occured.
16933 */
16934static int
16935xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
16936 xmlSchemaParticlePtr r,
16937 xmlSchemaParticlePtr b)
16938{
16939 xmlSchemaParticlePtr part;
16940 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
16941 if ((r->children == NULL) || (r->children->children == NULL))
16942 return (-1);
16943 /*
16944 * SPEC "For a group particle to be a ·valid restriction· of a
16945 * wildcard particle..."
16946 *
16947 * SPEC (1) "Every member of the {particles} of the group is a ·valid
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016948 * restriction· of the wildcard as defined by
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016949 * Particle Valid (Restriction) (§3.9.6)."
16950 */
16951 part = (xmlSchemaParticlePtr) r->children->children;
16952 do {
16953 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
16954 return (1);
16955 part = (xmlSchemaParticlePtr) part->next;
16956 } while (part != NULL);
16957 /*
16958 * SPEC (2) "The effective total range of the group [...] is a
16959 * valid restriction of B's occurrence range as defined by
16960 * Occurrence Range OK (§3.9.6)."
16961 */
16962 if (xmlSchemaCheckParticleRangeOK(
16963 xmlSchemaGetParticleTotalRangeMin(r),
16964 xmlSchemaGetParticleTotalRangeMax(r),
16965 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016966 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016967 return (0);
16968}
16969
16970/**
16971 * xmlSchemaCheckRCaseRecurse:
16972 * @ctxt: the schema parser context
16973 * @r: the <all> or <sequence> model group particle
16974 * @b: the base <all> or <sequence> model group particle
16975 *
16976 * (3.9.6) Constraints on Particle Schema Components
16977 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016978 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016979 Recurse)
16980 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016981 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016982 * STATUS: ?
16983 * TODO: subst-groups
16984 *
16985 * Returns 0 if the constraints are satisfied, a positive
16986 * error code if not and -1 if an internal error occured.
16987 */
16988static int
16989xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
16990 xmlSchemaParticlePtr r,
16991 xmlSchemaParticlePtr b)
16992{
16993 /* xmlSchemaParticlePtr part; */
16994 /* TODO: Error codes (rcase-Recurse). */
16995 if ((r->children == NULL) || (b->children == NULL) ||
16996 (r->children->type != b->children->type))
16997 return (-1);
16998 /*
16999 * SPEC "For an all or sequence group particle to be a ·valid
17000 * restriction· of another group particle with the same {compositor}..."
17001 *
17002 * SPEC (1) "R's occurrence range is a valid restriction of B's
17003 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
17004 */
17005 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17006 b->minOccurs, b->maxOccurs))
17007 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017008
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017009
17010 return (0);
17011}
17012
17013#endif
17014
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017015#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17016 xmlSchemaPCustomErrExt(pctxt, \
17017 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017018 WXS_BASIC_CAST fac1, fac1->node, \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017019 "It is an error for both '%s' and '%s' to be specified on the "\
17020 "same type definition", \
17021 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17022 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17023
17024#define FACET_RESTR_ERR(fac1, msg) \
17025 xmlSchemaPCustomErr(pctxt, \
17026 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017027 WXS_BASIC_CAST fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017028 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017029
17030#define FACET_RESTR_FIXED_ERR(fac) \
17031 xmlSchemaPCustomErr(pctxt, \
17032 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017033 WXS_BASIC_CAST fac, fac->node, \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017034 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017035 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017036
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017037static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017038xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17039 xmlSchemaFacetPtr facet1,
17040 xmlSchemaFacetPtr facet2,
17041 int lessGreater,
17042 int orEqual,
17043 int ofBase)
17044{
17045 xmlChar *msg = NULL;
17046
17047 msg = xmlStrdup(BAD_CAST "'");
17048 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17049 msg = xmlStrcat(msg, BAD_CAST "' has to be");
17050 if (lessGreater == 0)
17051 msg = xmlStrcat(msg, BAD_CAST " equal to");
17052 if (lessGreater == 1)
17053 msg = xmlStrcat(msg, BAD_CAST " greater than");
17054 else
17055 msg = xmlStrcat(msg, BAD_CAST " less than");
17056
17057 if (orEqual)
17058 msg = xmlStrcat(msg, BAD_CAST " or equal to");
17059 msg = xmlStrcat(msg, BAD_CAST " '");
17060 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17061 if (ofBase)
17062 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17063 else
17064 msg = xmlStrcat(msg, BAD_CAST "'");
17065
17066 xmlSchemaPCustomErr(pctxt,
17067 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017068 WXS_BASIC_CAST facet1, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017069 (const char *) msg, NULL);
17070
17071 if (msg != NULL)
17072 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017073}
17074
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017075/*
17076* xmlSchemaDeriveAndValidateFacets:
17077*
17078* Schema Component Constraint: Simple Type Restriction (Facets)
17079* (st-restrict-facets)
17080*/
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017081static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017082xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17083 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017084{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017085 xmlSchemaTypePtr base = type->baseType;
17086 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017087 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017088 flength = NULL, ftotdig = NULL, ffracdig = NULL,
17089 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17090 fmininc = NULL, fmaxinc = NULL,
17091 fminexc = NULL, fmaxexc = NULL,
17092 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17093 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17094 bfmininc = NULL, bfmaxinc = NULL,
17095 bfminexc = NULL, bfmaxexc = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000017096 int res; /* err = 0, fixedErr; */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017097
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017098 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017099 * SPEC st-restrict-facets 1:
17100 * "The {variety} of R is the same as that of B."
17101 */
17102 /*
17103 * SPEC st-restrict-facets 2:
17104 * "If {variety} is atomic, the {primitive type definition}
17105 * of R is the same as that of B."
17106 *
17107 * NOTE: we leave 1 & 2 out for now, since this will be
17108 * satisfied by the derivation process.
17109 * CONSTRUCTION TODO: Maybe needed if using a construction API.
17110 */
17111 /*
17112 * SPEC st-restrict-facets 3:
17113 * "The {facets} of R are the union of S and the {facets}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017114 * of B, eliminating duplicates. To eliminate duplicates,
17115 * when a facet of the same kind occurs in both S and the
17116 * {facets} of B, the one in the {facets} of B is not
17117 * included, with the exception of enumeration and pattern
17118 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017119 * are allowed."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017120 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017121
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017122 if ((type->facetSet == NULL) && (base->facetSet == NULL))
17123 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017124
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017125 last = type->facetSet;
17126 if (last != NULL)
17127 while (last->next != NULL)
17128 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017129
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017130 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17131 facet = cur->facet;
17132 switch (facet->type) {
17133 case XML_SCHEMA_FACET_LENGTH:
17134 flength = facet; break;
17135 case XML_SCHEMA_FACET_MINLENGTH:
17136 fminlen = facet; break;
17137 case XML_SCHEMA_FACET_MININCLUSIVE:
17138 fmininc = facet; break;
17139 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17140 fminexc = facet; break;
17141 case XML_SCHEMA_FACET_MAXLENGTH:
17142 fmaxlen = facet; break;
17143 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17144 fmaxinc = facet; break;
17145 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17146 fmaxexc = facet; break;
17147 case XML_SCHEMA_FACET_TOTALDIGITS:
17148 ftotdig = facet; break;
17149 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17150 ffracdig = facet; break;
17151 default:
17152 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017153 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017154 }
17155 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17156 facet = cur->facet;
17157 switch (facet->type) {
17158 case XML_SCHEMA_FACET_LENGTH:
17159 bflength = facet; break;
17160 case XML_SCHEMA_FACET_MINLENGTH:
17161 bfminlen = facet; break;
17162 case XML_SCHEMA_FACET_MININCLUSIVE:
17163 bfmininc = facet; break;
17164 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17165 bfminexc = facet; break;
17166 case XML_SCHEMA_FACET_MAXLENGTH:
17167 bfmaxlen = facet; break;
17168 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17169 bfmaxinc = facet; break;
17170 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17171 bfmaxexc = facet; break;
17172 case XML_SCHEMA_FACET_TOTALDIGITS:
17173 bftotdig = facet; break;
17174 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17175 bffracdig = facet; break;
17176 default:
17177 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017178 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017179 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017180 /*
17181 * length and minLength or maxLength (2.2) + (3.2)
17182 */
17183 if (flength && (fminlen || fmaxlen)) {
17184 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17185 "either of 'minLength' or 'maxLength' to be specified on "
17186 "the same type definition")
17187 }
17188 /*
17189 * Mutual exclusions in the same derivation step.
17190 */
17191 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017192 /*
17193 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017194 */
17195 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17196 }
17197 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017198 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017199 * SCC "minInclusive and minExclusive"
17200 */
17201 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017202 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017203
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017204 if (flength && bflength) {
17205 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017206 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017207 * The values have to be equal.
17208 */
17209 res = xmlSchemaCompareValues(flength->val, bflength->val);
17210 if (res == -2)
17211 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017212 if (res != 0)
17213 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17214 if ((res != 0) && (bflength->fixed)) {
17215 FACET_RESTR_FIXED_ERR(flength)
17216 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017217
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017218 }
17219 if (fminlen && bfminlen) {
17220 /*
17221 * SCC "minLength valid restriction"
17222 * minLength >= BASE minLength
17223 */
17224 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17225 if (res == -2)
17226 goto internal_error;
17227 if (res == -1)
17228 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17229 if ((res != 0) && (bfminlen->fixed)) {
17230 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017231 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017232 }
17233 if (fmaxlen && bfmaxlen) {
17234 /*
17235 * SCC "maxLength valid restriction"
17236 * maxLength <= BASE minLength
17237 */
17238 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17239 if (res == -2)
17240 goto internal_error;
17241 if (res == 1)
17242 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17243 if ((res != 0) && (bfmaxlen->fixed)) {
17244 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017245 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017246 }
17247 /*
17248 * SCC "length and minLength or maxLength"
17249 */
17250 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017251 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017252 if (flength) {
17253 if (! fminlen)
17254 flength = bflength;
17255 if (fminlen) {
17256 /* (1.1) length >= minLength */
17257 res = xmlSchemaCompareValues(flength->val, fminlen->val);
17258 if (res == -2)
17259 goto internal_error;
17260 if (res == -1)
17261 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17262 }
17263 if (! fmaxlen)
17264 fmaxlen = bfmaxlen;
17265 if (fmaxlen) {
17266 /* (2.1) length <= maxLength */
17267 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17268 if (res == -2)
17269 goto internal_error;
17270 if (res == 1)
17271 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17272 }
17273 }
17274 if (fmaxinc) {
17275 /*
17276 * "maxInclusive"
17277 */
17278 if (fmininc) {
17279 /* SCC "maxInclusive >= minInclusive" */
17280 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17281 if (res == -2)
17282 goto internal_error;
17283 if (res == -1) {
17284 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17285 }
17286 }
17287 /*
17288 * SCC "maxInclusive valid restriction"
17289 */
17290 if (bfmaxinc) {
17291 /* maxInclusive <= BASE maxInclusive */
17292 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17293 if (res == -2)
17294 goto internal_error;
17295 if (res == 1)
17296 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17297 if ((res != 0) && (bfmaxinc->fixed)) {
17298 FACET_RESTR_FIXED_ERR(fmaxinc)
17299 }
17300 }
17301 if (bfmaxexc) {
17302 /* maxInclusive < BASE maxExclusive */
17303 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17304 if (res == -2)
17305 goto internal_error;
17306 if (res != -1) {
17307 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17308 }
17309 }
17310 if (bfmininc) {
17311 /* maxInclusive >= BASE minInclusive */
17312 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17313 if (res == -2)
17314 goto internal_error;
17315 if (res == -1) {
17316 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17317 }
17318 }
17319 if (bfminexc) {
17320 /* maxInclusive > BASE minExclusive */
17321 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17322 if (res == -2)
17323 goto internal_error;
17324 if (res != 1) {
17325 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17326 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017327 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017328 }
17329 if (fmaxexc) {
17330 /*
17331 * "maxExclusive >= minExclusive"
17332 */
17333 if (fminexc) {
17334 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17335 if (res == -2)
17336 goto internal_error;
17337 if (res == -1) {
17338 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17339 }
17340 }
17341 /*
17342 * "maxExclusive valid restriction"
17343 */
17344 if (bfmaxexc) {
17345 /* maxExclusive <= BASE maxExclusive */
17346 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17347 if (res == -2)
17348 goto internal_error;
17349 if (res == 1) {
17350 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17351 }
17352 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017353 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017354 }
17355 }
17356 if (bfmaxinc) {
17357 /* maxExclusive <= BASE maxInclusive */
17358 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17359 if (res == -2)
17360 goto internal_error;
17361 if (res == 1) {
17362 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17363 }
17364 }
17365 if (bfmininc) {
17366 /* maxExclusive > BASE minInclusive */
17367 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17368 if (res == -2)
17369 goto internal_error;
17370 if (res != 1) {
17371 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17372 }
17373 }
17374 if (bfminexc) {
17375 /* maxExclusive > BASE minExclusive */
17376 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17377 if (res == -2)
17378 goto internal_error;
17379 if (res != 1) {
17380 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17381 }
17382 }
17383 }
17384 if (fminexc) {
17385 /*
17386 * "minExclusive < maxInclusive"
17387 */
17388 if (fmaxinc) {
17389 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17390 if (res == -2)
17391 goto internal_error;
17392 if (res != -1) {
17393 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17394 }
17395 }
17396 /*
17397 * "minExclusive valid restriction"
17398 */
17399 if (bfminexc) {
17400 /* minExclusive >= BASE minExclusive */
17401 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17402 if (res == -2)
17403 goto internal_error;
17404 if (res == -1) {
17405 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17406 }
17407 if ((res != 0) && (bfminexc->fixed)) {
17408 FACET_RESTR_FIXED_ERR(fminexc)
17409 }
17410 }
17411 if (bfmaxinc) {
17412 /* minExclusive <= BASE maxInclusive */
17413 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17414 if (res == -2)
17415 goto internal_error;
17416 if (res == 1) {
17417 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17418 }
17419 }
17420 if (bfmininc) {
17421 /* minExclusive >= BASE minInclusive */
17422 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17423 if (res == -2)
17424 goto internal_error;
17425 if (res == -1) {
17426 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17427 }
17428 }
17429 if (bfmaxexc) {
17430 /* minExclusive < BASE maxExclusive */
17431 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17432 if (res == -2)
17433 goto internal_error;
17434 if (res != -1) {
17435 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17436 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017437 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017438 }
17439 if (fmininc) {
17440 /*
17441 * "minInclusive < maxExclusive"
17442 */
17443 if (fmaxexc) {
17444 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17445 if (res == -2)
17446 goto internal_error;
17447 if (res != -1) {
17448 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17449 }
17450 }
17451 /*
17452 * "minExclusive valid restriction"
17453 */
17454 if (bfmininc) {
17455 /* minInclusive >= BASE minInclusive */
17456 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17457 if (res == -2)
17458 goto internal_error;
17459 if (res == -1) {
17460 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17461 }
17462 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017463 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017464 }
17465 }
17466 if (bfmaxinc) {
17467 /* minInclusive <= BASE maxInclusive */
17468 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17469 if (res == -2)
17470 goto internal_error;
Daniel Veillard0a119eb2005-07-20 13:46:00 +000017471 if (res == 1) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017472 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17473 }
17474 }
17475 if (bfminexc) {
17476 /* minInclusive > BASE minExclusive */
17477 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17478 if (res == -2)
17479 goto internal_error;
17480 if (res != 1)
17481 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17482 }
17483 if (bfmaxexc) {
17484 /* minInclusive < BASE maxExclusive */
17485 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17486 if (res == -2)
17487 goto internal_error;
17488 if (res != -1)
17489 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17490 }
17491 }
17492 if (ftotdig && bftotdig) {
17493 /*
17494 * SCC " totalDigits valid restriction"
17495 * totalDigits <= BASE totalDigits
17496 */
17497 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17498 if (res == -2)
17499 goto internal_error;
17500 if (res == 1)
17501 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17502 -1, 1, 1);
17503 if ((res != 0) && (bftotdig->fixed)) {
17504 FACET_RESTR_FIXED_ERR(ftotdig)
17505 }
17506 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017507 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017508 /*
17509 * SCC "fractionDigits valid restriction"
17510 * fractionDigits <= BASE fractionDigits
17511 */
17512 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17513 if (res == -2)
17514 goto internal_error;
17515 if (res == 1)
17516 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17517 -1, 1, 1);
17518 if ((res != 0) && (bffracdig->fixed)) {
17519 FACET_RESTR_FIXED_ERR(ffracdig)
17520 }
17521 }
17522 /*
17523 * SCC "fractionDigits less than or equal to totalDigits"
17524 */
17525 if (! ftotdig)
17526 ftotdig = bftotdig;
17527 if (! ffracdig)
17528 ffracdig = bffracdig;
17529 if (ftotdig && ffracdig) {
17530 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17531 if (res == -2)
17532 goto internal_error;
17533 if (res == 1)
17534 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17535 -1, 1, 0);
17536 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017537 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017538 * *Enumerations* won' be added here, since only the first set
17539 * of enumerations in the ancestor-or-self axis is used
17540 * for validation, plus we need to use the base type of those
17541 * enumerations for whitespace.
17542 *
17543 * *Patterns*: won't be add here, since they are ORed at
17544 * type level and ANDed at ancestor level. This will
17545 * happed during validation by walking the base axis
17546 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017547 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017548 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17549 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017550 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017551 * Special handling of enumerations and patterns.
17552 * TODO: hmm, they should not appear in the set, so remove this.
17553 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017554 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017555 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017556 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017557 /*
17558 * Search for a duplicate facet in the current type.
17559 */
17560 link = type->facetSet;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000017561 /* err = 0; */
17562 /* fixedErr = 0; */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017563 while (link != NULL) {
17564 facet = link->facet;
17565 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017566 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017567 case XML_SCHEMA_FACET_WHITESPACE:
17568 /*
17569 * The whitespace must be stronger.
17570 */
17571 if (facet->whitespace < bfacet->whitespace) {
17572 FACET_RESTR_ERR(flength,
17573 "The 'whitespace' value has to be equal to "
17574 "or stronger than the 'whitespace' value of "
17575 "the base type")
17576 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017577 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017578 (facet->whitespace != bfacet->whitespace)) {
17579 FACET_RESTR_FIXED_ERR(facet)
17580 }
17581 break;
17582 default:
17583 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017584 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017585 /* Duplicate found. */
17586 break;
17587 }
17588 link = link->next;
17589 }
17590 /*
17591 * If no duplicate was found: add the base types's facet
17592 * to the set.
17593 */
17594 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017595 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017596 xmlMalloc(sizeof(xmlSchemaFacetLink));
17597 if (link == NULL) {
17598 xmlSchemaPErrMemory(pctxt,
17599 "deriving facets, creating a facet link", NULL);
17600 return (-1);
17601 }
17602 link->facet = cur->facet;
17603 link->next = NULL;
17604 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017605 type->facetSet = link;
17606 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017607 last->next = link;
17608 last = link;
17609 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017610
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017611 }
17612
17613 return (0);
17614internal_error:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017615 PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17616 "an error occured");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017617 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017618}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017619
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017620static int
17621xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17622 xmlSchemaTypePtr type)
17623{
17624 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17625 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017626 * The actual value is then formed by replacing any union type
17627 * definition in the ·explicit members· with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017628 * {member type definitions}, in order.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017629 *
17630 * TODO: There's a bug entry at
17631 * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17632 * which indicates that we'll keep the union types the future.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017633 */
17634 link = type->memberTypes;
17635 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017636
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017637 if (WXS_IS_TYPE_NOT_FIXED(link->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000017638 xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017639
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017640 if (WXS_IS_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017641 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017642 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017643 link->type = subLink->type;
17644 if (subLink->next != NULL) {
17645 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017646 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017647 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017648 while (subLink != NULL) {
17649 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017650 xmlMalloc(sizeof(xmlSchemaTypeLink));
17651 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017652 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017653 NULL);
17654 return (-1);
17655 }
17656 newLink->type = subLink->type;
17657 prevLink->next = newLink;
17658 prevLink = newLink;
17659 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017660
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017661 subLink = subLink->next;
17662 }
17663 }
17664 }
17665 }
17666 link = link->next;
17667 }
17668 return (0);
17669}
17670
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017671static void
17672xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17673{
17674 int has = 0, needVal = 0, normVal = 0;
17675
17676 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17677 if (has) {
17678 needVal = (type->baseType->flags &
17679 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17680 normVal = (type->baseType->flags &
17681 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17682 }
17683 if (type->facets != NULL) {
17684 xmlSchemaFacetPtr fac;
17685
17686 for (fac = type->facets; fac != NULL; fac = fac->next) {
17687 switch (fac->type) {
17688 case XML_SCHEMA_FACET_WHITESPACE:
17689 break;
17690 case XML_SCHEMA_FACET_PATTERN:
17691 normVal = 1;
17692 has = 1;
17693 break;
17694 case XML_SCHEMA_FACET_ENUMERATION:
17695 needVal = 1;
17696 normVal = 1;
17697 has = 1;
17698 break;
17699 default:
17700 has = 1;
17701 break;
17702 }
17703 }
17704 }
17705 if (normVal)
17706 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17707 if (needVal)
17708 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17709 if (has)
17710 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17711
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017712 if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017713 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17714 /*
17715 * OPTIMIZE VAL TODO: Some facets need a computed value.
17716 */
17717 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17718 (prim->builtInType != XML_SCHEMAS_STRING)) {
17719 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17720 }
17721 }
17722}
17723
17724static int
17725xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17726{
17727
17728
17729 /*
17730 * Evaluate the whitespace-facet value.
17731 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017732 if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017733 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17734 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017735 } else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017736 return (0);
17737
17738 if (type->facetSet != NULL) {
17739 xmlSchemaFacetLinkPtr lin;
17740
17741 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17742 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17743 switch (lin->facet->whitespace) {
17744 case XML_SCHEMAS_FACET_PRESERVE:
17745 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17746 break;
17747 case XML_SCHEMAS_FACET_REPLACE:
17748 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17749 break;
17750 case XML_SCHEMAS_FACET_COLLAPSE:
17751 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17752 break;
17753 default:
17754 return (-1);
17755 }
17756 return (0);
17757 }
17758 }
17759 }
17760 /*
17761 * For all ·atomic· datatypes other than string (and types ·derived·
17762 * by ·restriction· from it) the value of whiteSpace is fixed to
17763 * collapse
17764 */
17765 {
17766 xmlSchemaTypePtr anc;
17767
17768 for (anc = type->baseType; anc != NULL &&
17769 anc->builtInType != XML_SCHEMAS_ANYTYPE;
17770 anc = anc->baseType) {
17771
17772 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17773 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17774 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17775
17776 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17777 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17778 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17779
17780 } else
17781 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17782 break;
17783 }
17784 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017785 }
17786 return (0);
17787}
17788
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017789static int
17790xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17791 xmlSchemaTypePtr type)
Daniel Veillard4255d502002-04-16 15:50:10 +000017792{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017793 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17794 return(0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017795 if (! WXS_IS_TYPE_NOT_FIXED_1(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017796 return(0);
17797 type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017798
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017799 if (WXS_IS_LIST(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017800 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017801 * Corresponds to <simpleType><list>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017802 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017803 if (type->subtypes == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017804 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017805 * This one is really needed, so get out.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017806 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017807 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017808 "list type has no item-type assigned");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017809 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017810 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017811 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017812 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017813 * Corresponds to <simpleType><union>...
17814 */
17815 if (type->memberTypes == NULL) {
17816 /*
17817 * This one is really needed, so get out.
17818 */
17819 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17820 "union type has no member-types assigned");
17821 return(-1);
17822 }
17823 } else {
17824 /*
17825 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017826 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017827 if (type->baseType == NULL) {
17828 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17829 "type has no base-type assigned");
17830 return(-1);
17831 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017832 if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017833 if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17834 return(-1);
17835 /*
17836 * Variety
17837 * If the <restriction> alternative is chosen, then the
17838 * {variety} of the {base type definition}.
17839 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017840 if (WXS_IS_ATOMIC(type->baseType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017841 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017842 else if (WXS_IS_LIST(type->baseType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017843 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017844 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017845 * Inherit the itemType.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017846 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017847 type->subtypes = type->baseType->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017848 } else if (WXS_IS_UNION(type->baseType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017849 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017850 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017851 * NOTE that we won't assign the memberTypes of the base,
17852 * since this will make trouble when freeing them; we will
17853 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017854 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017855 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017856 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017857 return(0);
17858}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017859
Daniel Veillard8651f532002-04-17 09:06:27 +000017860#ifdef DEBUG_TYPE
Daniel Veillard67952602006-01-05 15:29:44 +000017861static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017862xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
17863 xmlSchemaTypePtr type)
17864{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017865 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017866 xmlGenericError(xmlGenericErrorContext,
17867 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017868 type->node->doc->URL,
17869 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000017870 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017871 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000017872 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017873 if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017874 switch (type->contentType) {
17875 case XML_SCHEMA_CONTENT_SIMPLE:
17876 xmlGenericError(xmlGenericErrorContext, "simple\n");
17877 break;
17878 case XML_SCHEMA_CONTENT_ELEMENTS:
17879 xmlGenericError(xmlGenericErrorContext, "elements\n");
17880 break;
17881 case XML_SCHEMA_CONTENT_UNKNOWN:
17882 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
17883 break;
17884 case XML_SCHEMA_CONTENT_EMPTY:
17885 xmlGenericError(xmlGenericErrorContext, "empty\n");
17886 break;
17887 case XML_SCHEMA_CONTENT_MIXED:
17888 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017889 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017890 xmlGenericError(xmlGenericErrorContext,
17891 "mixed as emptiable particle\n");
17892 else
17893 xmlGenericError(xmlGenericErrorContext, "mixed\n");
17894 break;
17895 /* Removed, since not used. */
17896 /*
17897 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
17898 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
17899 break;
17900 */
17901 case XML_SCHEMA_CONTENT_BASIC:
17902 xmlGenericError(xmlGenericErrorContext, "basic\n");
17903 break;
17904 default:
17905 xmlGenericError(xmlGenericErrorContext,
17906 "not registered !!!\n");
17907 break;
17908 }
Daniel Veillard8651f532002-04-17 09:06:27 +000017909 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017910}
Daniel Veillard8651f532002-04-17 09:06:27 +000017911#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017912
17913/*
17914* 3.14.6 Constraints on Simple Type Definition Schema Components
17915*/
17916static int
17917xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
17918 xmlSchemaTypePtr type)
17919{
17920 int res, olderrs = pctxt->nberrors;
17921
17922 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17923 return(-1);
17924
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017925 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017926 return(0);
17927
17928 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
17929 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
17930
17931 if (type->baseType == NULL) {
17932 PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
17933 "missing baseType");
17934 goto exit_failure;
17935 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017936 if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000017937 xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017938 /*
17939 * If a member type of a union is a union itself, we need to substitute
17940 * that member type for its member types.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017941 * NOTE that this might change in WXS 1.1; i.e. we will keep the union
17942 * types in WXS 1.1.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017943 */
17944 if ((type->memberTypes != NULL) &&
17945 (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
17946 return(-1);
17947 /*
17948 * SPEC src-simple-type 1
17949 * "The corresponding simple type definition, if any, must satisfy
17950 * the conditions set out in Constraints on Simple Type Definition
17951 * Schema Components (§3.14.6)."
17952 */
17953 /*
17954 * Schema Component Constraint: Simple Type Definition Properties Correct
17955 * (st-props-correct)
17956 */
17957 res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
17958 HFAILURE HERROR
17959 /*
17960 * Schema Component Constraint: Derivation Valid (Restriction, Simple)
17961 * (cos-st-restricts)
17962 */
17963 res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
17964 HFAILURE HERROR
17965 /*
17966 * TODO: Removed the error report, since it got annoying to get an
17967 * extra error report, if anything failed until now.
17968 * Enable this if needed.
17969 *
17970 * xmlSchemaPErr(ctxt, type->node,
17971 * XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
17972 * "Simple type '%s' does not satisfy the constraints "
17973 * "on simple type definitions.\n",
17974 * type->name, NULL);
17975 */
17976 /*
17977 * Schema Component Constraint: Simple Type Restriction (Facets)
17978 * (st-restrict-facets)
17979 */
17980 res = xmlSchemaCheckFacetValues(type, pctxt);
17981 HFAILURE HERROR
17982 if ((type->facetSet != NULL) ||
17983 (type->baseType->facetSet != NULL)) {
17984 res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
17985 HFAILURE HERROR
17986 }
17987 /*
17988 * Whitespace value.
17989 */
17990 res = xmlSchemaTypeFixupWhitespace(type);
17991 HFAILURE HERROR
17992 xmlSchemaTypeFixupOptimFacets(type);
17993
17994exit_error:
17995#ifdef DEBUG_TYPE
17996 xmlSchemaDebugFixedType(pctxt, type);
17997#endif
17998 if (olderrs != pctxt->nberrors)
17999 return(pctxt->err);
18000 return(0);
18001
18002exit_failure:
18003#ifdef DEBUG_TYPE
18004 xmlSchemaDebugFixedType(pctxt, type);
18005#endif
18006 return(-1);
18007}
18008
18009static int
18010xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18011 xmlSchemaTypePtr type)
18012{
18013 int res = 0, olderrs = pctxt->nberrors;
18014 xmlSchemaTypePtr baseType = type->baseType;
18015
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018016 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018017 return(0);
18018 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18019 if (baseType == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018020 PERROR_INT("xmlSchemaFixupComplexType",
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018021 "missing baseType");
18022 goto exit_failure;
18023 }
18024 /*
18025 * Fixup the base type.
18026 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018027 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018028 xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018029 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18030 /*
18031 * Skip fixup if the base type is invalid.
18032 * TODO: Generate a warning!
18033 */
18034 return(0);
18035 }
18036 /*
18037 * This basically checks if the base type can be derived.
18038 */
18039 res = xmlSchemaCheckSRCCT(pctxt, type);
18040 HFAILURE HERROR
18041 /*
18042 * Fixup the content type.
18043 */
18044 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18045 /*
18046 * Corresponds to <complexType><simpleContent>...
18047 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018048 if ((WXS_IS_COMPLEX(baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018049 (baseType->contentTypeDef != NULL) &&
18050 (WXS_IS_RESTRICTION(type))) {
18051 xmlSchemaTypePtr contentBase, content;
18052#ifdef ENABLE_NAMED_LOCALS
18053 char buf[30];
18054 const xmlChar *tmpname;
18055#endif
18056 /*
18057 * SPEC (1) If <restriction> + base type is <complexType>,
18058 * "whose own {content type} is a simple type..."
18059 */
18060 if (type->contentTypeDef != NULL) {
18061 /*
18062 * SPEC (1.1) "the simple type definition corresponding to the
18063 * <simpleType> among the [children] of <restriction> if there
18064 * is one;"
18065 * Note that this "<simpleType> among the [children]" was put
18066 * into ->contentTypeDef during parsing.
18067 */
18068 contentBase = type->contentTypeDef;
18069 type->contentTypeDef = NULL;
18070 } else {
18071 /*
18072 * (1.2) "...otherwise (<restriction> has no <simpleType>
18073 * among its [children]), the simple type definition which
18074 * is the {content type} of the ... base type."
18075 */
18076 contentBase = baseType->contentTypeDef;
18077 }
18078 /*
18079 * SPEC
18080 * "... a simple type definition which restricts the simple
18081 * type definition identified in clause 1.1 or clause 1.2
18082 * with a set of facet components"
18083 *
18084 * Create the anonymous simple type, which will be the content
18085 * type of the complex type.
18086 */
18087#ifdef ENABLE_NAMED_LOCALS
18088 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18089 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018090 content = xmlSchemaAddType(pctxt, pctxt->schema,
18091 XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018092 type->node, 0);
18093#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018094 content = xmlSchemaAddType(pctxt, pctxt->schema,
18095 XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018096 type->node, 0);
18097#endif
18098 if (content == NULL)
18099 goto exit_failure;
18100 /*
18101 * We will use the same node as for the <complexType>
18102 * to have it somehow anchored in the schema doc.
18103 */
18104 content->type = XML_SCHEMA_TYPE_SIMPLE;
18105 content->baseType = contentBase;
18106 /*
18107 * Move the facets, previously anchored on the
18108 * complexType during parsing.
18109 */
18110 content->facets = type->facets;
18111 type->facets = NULL;
18112 content->facetSet = type->facetSet;
18113 type->facetSet = NULL;
18114
18115 type->contentTypeDef = content;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018116 if (WXS_IS_TYPE_NOT_FIXED(contentBase))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018117 xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018118 /*
18119 * Fixup the newly created type. We don't need to check
18120 * for circularity here.
18121 */
18122 res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18123 HFAILURE HERROR
18124 res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18125 HFAILURE HERROR
18126
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018127 } else if ((WXS_IS_COMPLEX(baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018128 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18129 (WXS_IS_RESTRICTION(type))) {
18130 /*
18131 * SPEC (2) If <restriction> + base is a mixed <complexType> with
18132 * an emptiable particle, then a simple type definition which
18133 * restricts the <restriction>'s <simpleType> child.
18134 */
18135 if ((type->contentTypeDef == NULL) ||
18136 (type->contentTypeDef->baseType == NULL)) {
18137 /*
18138 * TODO: Check if this ever happens.
18139 */
18140 xmlSchemaPCustomErr(pctxt,
18141 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018142 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018143 "Internal error: xmlSchemaTypeFixup, "
18144 "complex type '%s': the <simpleContent><restriction> "
18145 "is missing a <simpleType> child, but was not catched "
18146 "by xmlSchemaCheckSRCCT()", type->name);
18147 goto exit_failure;
18148 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018149 } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018150 /*
18151 * SPEC (3) If <extension> + base is <complexType> with
18152 * <simpleType> content, "...then the {content type} of that
18153 * complex type definition"
18154 */
18155 if (baseType->contentTypeDef == NULL) {
18156 /*
18157 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18158 * should have catched this already.
18159 */
18160 xmlSchemaPCustomErr(pctxt,
18161 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018162 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018163 "Internal error: xmlSchemaTypeFixup, "
18164 "complex type '%s': the <extension>ed base type is "
18165 "a complex type with no simple content type",
18166 type->name);
18167 goto exit_failure;
18168 }
18169 type->contentTypeDef = baseType->contentTypeDef;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018170 } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018171 /*
18172 * SPEC (4) <extension> + base is <simpleType>
18173 * "... then that simple type definition"
18174 */
18175 type->contentTypeDef = baseType;
18176 } else {
18177 /*
18178 * TODO: Check if this ever happens.
18179 */
18180 xmlSchemaPCustomErr(pctxt,
18181 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018182 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018183 "Internal error: xmlSchemaTypeFixup, "
18184 "complex type '%s' with <simpleContent>: unhandled "
18185 "derivation case", type->name);
18186 goto exit_failure;
18187 }
18188 } else {
18189 int dummySequence = 0;
18190 xmlSchemaParticlePtr particle =
18191 (xmlSchemaParticlePtr) type->subtypes;
18192 /*
18193 * Corresponds to <complexType><complexContent>...
18194 *
18195 * NOTE that the effective mixed was already set during parsing of
18196 * <complexType> and <complexContent>; its flag value is
18197 * XML_SCHEMAS_TYPE_MIXED.
18198 *
18199 * Compute the "effective content":
18200 * (2.1.1) + (2.1.2) + (2.1.3)
18201 */
18202 if ((particle == NULL) ||
18203 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18204 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18205 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18206 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18207 (particle->minOccurs == 0))) &&
18208 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18209 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18210 /*
18211 * SPEC (2.1.4) "If the ·effective mixed· is true, then
18212 * a particle whose properties are as follows:..."
18213 *
18214 * Empty sequence model group with
18215 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18216 * NOTE that we sill assign it the <complexType> node to
18217 * somehow anchor it in the doc.
18218 */
18219 if ((particle == NULL) ||
18220 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18221 /*
18222 * Create the particle.
18223 */
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000018224 particle = xmlSchemaAddParticle(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018225 type->node, 1, 1);
18226 if (particle == NULL)
18227 goto exit_failure;
18228 /*
18229 * Create the model group.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018230 */ /* URGENT TODO: avoid adding to pending items. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018231 particle->children = (xmlSchemaTreeItemPtr)
18232 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18233 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18234 if (particle->children == NULL)
18235 goto exit_failure;
18236
18237 type->subtypes = (xmlSchemaTypePtr) particle;
18238 }
18239 dummySequence = 1;
18240 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18241 } else {
18242 /*
18243 * SPEC (2.1.5) "otherwise empty"
18244 */
18245 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18246 }
18247 } else {
18248 /*
18249 * SPEC (2.2) "otherwise the particle corresponding to the
18250 * <all>, <choice>, <group> or <sequence> among the
18251 * [children]."
18252 */
18253 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18254 }
18255 /*
18256 * Compute the "content type".
18257 */
18258 if (WXS_IS_RESTRICTION(type)) {
18259 /*
18260 * SPEC (3.1) "If <restriction>..."
18261 * (3.1.1) + (3.1.2) */
18262 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18263 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18264 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18265 }
18266 } else {
18267 /*
18268 * SPEC (3.2) "If <extension>..."
18269 */
18270 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18271 /*
18272 * SPEC (3.2.1)
18273 */
18274 type->contentType = baseType->contentType;
18275 type->subtypes = baseType->subtypes;
18276 /*
18277 * NOTE that the effective mixed is ignored here.
18278 */
18279 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18280 /*
18281 * SPEC (3.2.2)
18282 */
18283 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18284 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18285 } else {
18286 /*
18287 * SPEC (3.2.3)
18288 */
18289 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18290 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18291 /*
18292 * "A model group whose {compositor} is sequence and whose
18293 * {particles} are..."
18294 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018295 if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18296 (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18297 ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18298 XML_SCHEMA_TYPE_ALL))
18299 {
18300 /*
18301 * SPEC cos-all-limited (1)
18302 */
18303 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18304 /* TODO: error code */
18305 XML_SCHEMAP_COS_ALL_LIMITED,
18306 WXS_ITEM_NODE(type), NULL,
18307 "The type has an 'all' model group in its "
18308 "{content type} and thus cannot be derived from "
18309 "a non-empty type, since this would produce a "
18310 "'sequence' model group containing the 'all' "
18311 "model group; 'all' model groups are not "
18312 "allowed to appear inside other model groups",
18313 NULL, NULL);
18314
18315 } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18316 (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18317 ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18318 XML_SCHEMA_TYPE_ALL))
18319 {
18320 /*
18321 * SPEC cos-all-limited (1)
18322 */
18323 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18324 /* TODO: error code */
18325 XML_SCHEMAP_COS_ALL_LIMITED,
18326 WXS_ITEM_NODE(type), NULL,
18327 "A type cannot be derived by extension from a type "
18328 "which has an 'all' model group in its "
18329 "{content type}, since this would produce a "
18330 "'sequence' model group containing the 'all' "
18331 "model group; 'all' model groups are not "
18332 "allowed to appear inside other model groups",
18333 NULL, NULL);
18334
18335 } else if (! dummySequence) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018336 xmlSchemaTreeItemPtr effectiveContent =
18337 (xmlSchemaTreeItemPtr) type->subtypes;
18338 /*
18339 * Create the particle.
18340 */
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000018341 particle = xmlSchemaAddParticle(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018342 type->node, 1, 1);
18343 if (particle == NULL)
18344 goto exit_failure;
18345 /*
18346 * Create the "sequence" model group.
18347 */
18348 particle->children = (xmlSchemaTreeItemPtr)
18349 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18350 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18351 if (particle->children == NULL)
18352 goto exit_failure;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018353 WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018354 /*
18355 * SPEC "the particle of the {content type} of
18356 * the ... base ..."
18357 * Create a duplicate of the base type's particle
18358 * and assign its "term" to it.
18359 */
18360 particle->children->children =
18361 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000018362 type->node,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018363 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
18364 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
18365 if (particle->children->children == NULL)
18366 goto exit_failure;
18367 particle = (xmlSchemaParticlePtr)
18368 particle->children->children;
18369 particle->children =
18370 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
18371 /*
18372 * SPEC "followed by the ·effective content·."
18373 */
18374 particle->next = effectiveContent;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018375 /*
18376 * This all will result in:
18377 * new-particle
18378 * --> new-sequence(
18379 * new-particle
18380 * --> base-model,
18381 * this-particle
18382 * --> this-model
18383 * )
18384 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018385 } else {
18386 /*
18387 * This is the case when there is already an empty
18388 * <sequence> with minOccurs==maxOccurs==1.
18389 * Just add the base types's content type.
18390 * NOTE that, although we miss to add an intermediate
18391 * <sequence>, this should produce no difference to
18392 * neither the regex compilation of the content model,
18393 * nor to the complex type contraints.
18394 */
18395 particle->children->children =
18396 (xmlSchemaTreeItemPtr) baseType->subtypes;
18397 }
18398 }
18399 }
18400 }
18401 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018402 * Now fixup attribute uses:
18403 * - expand attr. group references
18404 * - intersect attribute wildcards
18405 * - inherit attribute uses of the base type
18406 * - inherit or union attr. wildcards if extending
18407 * - apply attr. use prohibitions if restricting
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018408 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018409 res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018410 HFAILURE HERROR
18411 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018412 * Apply the complex type component constraints; this will not
18413 * check attributes, since this is done in
18414 * xmlSchemaFixupTypeAttributeUses().
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018415 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018416 res = xmlSchemaCheckCTComponent(pctxt, type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018417 HFAILURE HERROR
18418
18419#ifdef DEBUG_TYPE
18420 xmlSchemaDebugFixedType(pctxt, type);
18421#endif
18422 if (olderrs != pctxt->nberrors)
18423 return(pctxt->err);
18424 else
18425 return(0);
18426
18427exit_error:
18428 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18429#ifdef DEBUG_TYPE
18430 xmlSchemaDebugFixedType(pctxt, type);
18431#endif
18432 return(pctxt->err);
18433
18434exit_failure:
18435 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18436#ifdef DEBUG_TYPE
18437 xmlSchemaDebugFixedType(pctxt, type);
18438#endif
18439 return(-1);
18440}
18441
18442
18443/**
18444 * xmlSchemaTypeFixup:
18445 * @typeDecl: the schema type definition
18446 * @ctxt: the schema parser context
18447 *
18448 * Fixes the content model of the type.
18449 * URGENT TODO: We need an int result!
18450 */
18451static int
18452xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018453 xmlSchemaAbstractCtxtPtr actxt)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018454{
18455 if (type == NULL)
18456 return(0);
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018457 if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18458 AERROR_INT("xmlSchemaTypeFixup",
18459 "this function needs a parser context");
18460 return(-1);
18461 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018462 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018463 return(0);
18464 if (type->type == XML_SCHEMA_TYPE_COMPLEX)
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018465 return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018466 else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018467 return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018468 return(0);
Daniel Veillard4255d502002-04-16 15:50:10 +000018469}
18470
18471/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018472 * xmlSchemaCheckFacet:
18473 * @facet: the facet
18474 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000018475 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018476 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018477 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018478 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018479 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018480 * Returns 0 if valid, a positive error code if not valid and
18481 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018482 */
18483int
18484xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018485 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018486 xmlSchemaParserCtxtPtr pctxt,
18487 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018488{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018489 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018490
Daniel Veillardce682bc2004-11-05 17:22:25 +000018491 if ((facet == NULL) || (typeDecl == NULL))
18492 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018493 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018494 * TODO: will the parser context be given if used from
18495 * the relaxNG module?
18496 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018497 if (pctxt == NULL)
18498 ctxtGiven = 0;
18499 else
18500 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018501
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018502 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018503 case XML_SCHEMA_FACET_MININCLUSIVE:
18504 case XML_SCHEMA_FACET_MINEXCLUSIVE:
18505 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018506 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18507 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018508 /*
18509 * Okay we need to validate the value
18510 * at that point.
18511 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018512 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018513
18514 /* 4.3.5.5 Constraints on enumeration Schema Components
18515 * Schema Component Constraint: enumeration valid restriction
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018516 * It is an ·error· if any member of {value} is not in the
18517 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018518 *
18519 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018520 * The value ·must· be in the
18521 * ·value space· of the ·base type·.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018522 */
18523 /*
18524 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018525 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018526 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018527 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018528 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018529 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018530 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018531 */
18532 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18533 base = typeDecl->baseType;
18534 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018535 PERROR_INT("xmlSchemaCheckFacet",
18536 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018537 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018538 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018539 } else
18540 base = typeDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018541
18542 if (! ctxtGiven) {
18543 /*
18544 * A context is needed if called from RelaxNG.
18545 */
18546 pctxt = xmlSchemaNewParserCtxt("*");
18547 if (pctxt == NULL)
18548 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018549 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018550 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018551 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018552 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018553 * facet->node is just the node holding the facet
18554 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018555 * of the facet.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018556 */
18557 ret = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018558 ACTXT_CAST pctxt, facet->node, base,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018559 facet->value, &(facet->val), 1, 1, 0);
18560 if (ret != 0) {
18561 if (ret < 0) {
18562 /* No error message for RelaxNG. */
18563 if (ctxtGiven) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018564 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018565 XML_SCHEMAP_INTERNAL, facet->node, NULL,
18566 "Internal error: xmlSchemaCheckFacet, "
18567 "failed to validate the value '%s' of the "
18568 "facet '%s' against the base type",
18569 facet->value, xmlSchemaFacetTypeToString(facet->type));
18570 }
18571 goto internal_error;
18572 }
18573 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18574 /* No error message for RelaxNG. */
18575 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018576 xmlChar *str = NULL;
18577
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018578 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018579 ret, facet->node, WXS_BASIC_CAST facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018580 "The value '%s' of the facet does not validate "
18581 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018582 facet->value,
18583 xmlSchemaFormatQName(&str,
18584 base->targetNamespace, base->name));
18585 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018586 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018587 goto exit;
18588 } else if (facet->val == NULL) {
18589 if (ctxtGiven) {
18590 PERROR_INT("xmlSchemaCheckFacet",
18591 "value was not computed");
18592 }
18593 TODO
18594 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018595 break;
18596 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018597 case XML_SCHEMA_FACET_PATTERN:
18598 facet->regexp = xmlRegexpCompile(facet->value);
18599 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018600 ret = XML_SCHEMAP_REGEXP_INVALID;
18601 /* No error message for RelaxNG. */
18602 if (ctxtGiven) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018603 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018604 ret, facet->node, WXS_BASIC_CAST typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018605 "The value '%s' of the facet 'pattern' is not a "
18606 "valid regular expression",
18607 facet->value, NULL);
18608 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018609 }
18610 break;
18611 case XML_SCHEMA_FACET_TOTALDIGITS:
18612 case XML_SCHEMA_FACET_FRACTIONDIGITS:
18613 case XML_SCHEMA_FACET_LENGTH:
18614 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018615 case XML_SCHEMA_FACET_MINLENGTH:
18616
18617 if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18618 ret = xmlSchemaValidatePredefinedType(
18619 xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18620 facet->value, &(facet->val));
18621 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018622 ret = xmlSchemaValidatePredefinedType(
18623 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18624 facet->value, &(facet->val));
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018625 }
18626 if (ret != 0) {
18627 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018628 /* No error message for RelaxNG. */
18629 if (ctxtGiven) {
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018630 PERROR_INT("xmlSchemaCheckFacet",
18631 "validating facet value");
18632 }
18633 goto internal_error;
18634 }
18635 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18636 /* No error message for RelaxNG. */
18637 if (ctxtGiven) {
18638 /* error code */
18639 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18640 ret, facet->node, WXS_BASIC_CAST typeDecl,
18641 "The value '%s' of the facet '%s' is not a valid '%s'",
18642 facet->value,
18643 xmlSchemaFacetTypeToString(facet->type),
18644 (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18645 BAD_CAST "nonNegativeInteger" :
18646 BAD_CAST "positiveInteger",
18647 NULL);
18648 }
18649 }
18650 break;
18651
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018652 case XML_SCHEMA_FACET_WHITESPACE:{
18653 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18654 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18655 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18656 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18657 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18658 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18659 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018660 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18661 /* No error message for RelaxNG. */
18662 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018663 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018664 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018665 ret, facet->node, WXS_BASIC_CAST typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018666 "The value '%s' of the facet 'whitespace' is not "
18667 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018668 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018669 }
18670 }
18671 default:
18672 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018673 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018674exit:
18675 if ((! ctxtGiven) && (pctxt != NULL))
18676 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018677 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018678internal_error:
18679 if ((! ctxtGiven) && (pctxt != NULL))
18680 xmlSchemaFreeParserCtxt(pctxt);
18681 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018682}
18683
18684/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018685 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000018686 * @typeDecl: the schema type definition
18687 * @ctxt: the schema parser context
18688 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018689 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000018690 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018691static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018692xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018693 xmlSchemaParserCtxtPtr pctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000018694{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018695 int res, olderrs = pctxt->nberrors;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018696 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018697 /*
18698 * NOTE: It is intended to use the facets list, instead
18699 * of facetSet.
18700 */
18701 if (typeDecl->facets != NULL) {
18702 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018703
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018704 /*
18705 * Temporarily assign the "schema" to the validation context
18706 * of the parser context. This is needed for NOTATION validation.
18707 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018708 if (pctxt->vctxt == NULL) {
18709 if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18710 return(-1);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018711 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018712 pctxt->vctxt->schema = pctxt->schema;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018713 while (facet != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018714 res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18715 HFAILURE
Daniel Veillard01fa6152004-06-29 17:04:39 +000018716 facet = facet->next;
18717 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018718 pctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018719 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018720 if (olderrs != pctxt->nberrors)
18721 return(pctxt->err);
18722 return(0);
18723exit_failure:
18724 return(-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018725}
18726
18727/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018728 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018729 * @ctxtMGroup: the searched model group
18730 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018731 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018732 *
18733 * This one is intended to be used by
18734 * xmlSchemaCheckGroupDefCircular only.
18735 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018736 * Returns the particle with the circular model group definition reference,
18737 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018738 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018739static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018740xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018741 xmlSchemaTreeItemPtr particle)
18742{
18743 xmlSchemaTreeItemPtr circ = NULL;
18744 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018745 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018746
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018747 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018748 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018749 if (term == NULL)
18750 continue;
18751 switch (term->type) {
18752 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018753 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018754 if (gdef == groupDef)
18755 return (particle);
18756 /*
18757 * Mark this model group definition to avoid infinite
18758 * recursion on circular references not yet examined.
18759 */
18760 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18761 continue;
18762 if (gdef->children != NULL) {
18763 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18764 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18765 gdef->children->children);
18766 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18767 if (circ != NULL)
18768 return (circ);
18769 }
18770 break;
18771 case XML_SCHEMA_TYPE_SEQUENCE:
18772 case XML_SCHEMA_TYPE_CHOICE:
18773 case XML_SCHEMA_TYPE_ALL:
18774 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18775 if (circ != NULL)
18776 return (circ);
18777 break;
18778 default:
18779 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018780 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018781 }
18782 return (NULL);
18783}
18784
18785/**
18786 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018787 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018788 * @ctxt: the parser context
18789 * @name: the name
18790 *
18791 * Checks for circular references to model group definitions.
18792 */
18793static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018794xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018795 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018796{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018797 /*
18798 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018799 * 2 Circular groups are disallowed. That is, within the {particles}
18800 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018801 * is the group itself.
18802 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018803 if ((item == NULL) ||
18804 (item->type != XML_SCHEMA_TYPE_GROUP) ||
18805 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018806 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018807 {
18808 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018809
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018810 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018811 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018812 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018813 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018814 * TODO: The error report is not adequate: this constraint
18815 * is defined for model groups but not definitions, but since
18816 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018817 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018818 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018819 */
18820 xmlSchemaPCustomErr(ctxt,
18821 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018822 NULL, WXS_ITEM_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018823 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018824 "defined", xmlSchemaFormatQName(&str,
18825 item->targetNamespace, item->name));
18826 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018827 /*
18828 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018829 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018830 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018831 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018832 }
18833 }
18834}
18835
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018836/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018837 * xmlSchemaModelGroupToModelGroupDefFixup:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018838 * @ctxt: the parser context
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018839 * @mg: the model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018840 *
18841 * Assigns the model group of model group definitions to the "term"
18842 * of the referencing particle.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018843 * In xmlSchemaResolveModelGroupParticleReferences the model group
18844 * definitions were assigned to the "term", since needed for the
18845 * circularity check.
18846 *
18847 * Schema Component Constraint:
18848 * All Group Limited (cos-all-limited) (1.2)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018849 */
18850static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018851xmlSchemaModelGroupToModelGroupDefFixup(
18852 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18853 xmlSchemaModelGroupPtr mg)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018854{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018855 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
18856
18857 while (particle != NULL) {
18858 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
18859 ((WXS_PARTICLE_TERM(particle))->type !=
18860 XML_SCHEMA_TYPE_GROUP))
18861 {
18862 particle = WXS_PTC_CAST particle->next;
18863 continue;
18864 }
18865 if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
18866 /*
18867 * TODO: Remove the particle.
18868 */
18869 WXS_PARTICLE_TERM(particle) = NULL;
18870 particle = WXS_PTC_CAST particle->next;
18871 continue;
18872 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018873 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018874 * Assign the model group to the {term} of the particle.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018875 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018876 WXS_PARTICLE_TERM(particle) =
18877 WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
18878
18879 particle = WXS_PTC_CAST particle->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018880 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018881}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018882
18883/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018884 * xmlSchemaCheckAttrGroupCircularRecur:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018885 * @ctxtGr: the searched attribute group
18886 * @attr: the current attribute list to be processed
18887 *
18888 * This one is intended to be used by
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018889 * xmlSchemaCheckAttrGroupCircular only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018890 *
18891 * Returns the circular attribute grou reference, otherwise NULL.
18892 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018893static xmlSchemaQNameRefPtr
18894xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
18895 xmlSchemaItemListPtr list)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018896{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018897 xmlSchemaAttributeGroupPtr gr;
18898 xmlSchemaQNameRefPtr ref, circ;
18899 int i;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018900 /*
18901 * We will search for an attribute group reference which
18902 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018903 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018904 for (i = 0; i < list->nbItems; i++) {
18905 ref = list->items[i];
18906 if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
18907 (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
18908 (ref->item != NULL))
18909 {
18910 gr = WXS_ATTR_GROUP_CAST ref->item;
18911 if (gr == ctxtGr)
18912 return(ref);
18913 if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
18914 continue;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018915 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018916 * Mark as visited to avoid infinite recursion on
18917 * circular references not yet examined.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018918 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018919 if ((gr->attrUses) &&
18920 (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
18921 {
18922 gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
18923 circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
18924 (xmlSchemaItemListPtr) gr->attrUses);
18925 gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
18926 if (circ != NULL)
18927 return (circ);
18928 }
18929
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018930 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018931 }
18932 return (NULL);
18933}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018934
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018935/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018936 * xmlSchemaCheckAttrGroupCircular:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018937 * attrGr: the attribute group definition
18938 * @ctxt: the parser context
18939 * @name: the name
18940 *
18941 * Checks for circular references of attribute groups.
18942 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018943static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018944xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018945 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018946{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018947 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018948 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018949 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018950 * 3 Circular group reference is disallowed outside <redefine>.
18951 * That is, unless this element information item's parent is
18952 * <redefine>, then among the [children], if any, there must
18953 * not be an <attributeGroup> with ref [attribute] which resolves
18954 * to the component corresponding to this <attributeGroup>. Indirect
18955 * circularity is also ruled out. That is, when QName resolution
18956 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
18957 * any <attributeGroup>s with a ref [attribute] among the [children],
18958 * it must not be the case that a ·QName· is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018959 * which resolves to the component corresponding to this <attributeGroup>.
18960 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018961 if (attrGr->attrUses == NULL)
18962 return(0);
18963 else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
18964 return(0);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018965 else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018966 xmlSchemaQNameRefPtr circ;
18967
18968 circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
18969 (xmlSchemaItemListPtr) attrGr->attrUses);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018970 if (circ != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018971 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018972 /*
18973 * TODO: Report the referenced attr group as QName.
18974 */
18975 xmlSchemaPCustomErr(ctxt,
18976 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018977 NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018978 "Circular reference to the attribute group '%s' "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018979 "defined", xmlSchemaGetComponentQName(&str, attrGr));
18980 FREE_AND_NULL(str);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018981 /*
18982 * NOTE: We will cut the reference to avoid further
18983 * confusion of the processor.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018984 * BADSPEC TODO: The spec should define how to process in this case.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018985 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018986 circ->item = NULL;
18987 return(ctxt->err);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018988 }
18989 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018990 return(0);
18991}
18992
18993static int
18994xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
18995 xmlSchemaAttributeGroupPtr attrGr);
18996
18997/**
18998 * xmlSchemaExpandAttributeGroupRefs:
18999 * @pctxt: the parser context
19000 * @node: the node of the component holding the attribute uses
19001 * @completeWild: the intersected wildcard to be returned
19002 * @list: the attribute uses
19003 *
19004 * Substitutes contained attribute group references
19005 * for their attribute uses. Wilcards are intersected.
19006 * Attribute use prohibitions are removed from the list
19007 * and returned via the @prohibs list.
19008 * Pointlessness of attr. prohibs, if a matching attr. decl
19009 * is existent a well, are checked.
19010 */
19011static int
19012xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19013 xmlSchemaBasicItemPtr item,
19014 xmlSchemaWildcardPtr *completeWild,
19015 xmlSchemaItemListPtr list,
19016 xmlSchemaItemListPtr prohibs)
19017{
19018 xmlSchemaAttributeGroupPtr gr;
19019 xmlSchemaAttributeUsePtr use;
19020 xmlSchemaItemListPtr sublist;
19021 int i, j;
19022 int created = (*completeWild == NULL) ? 0 : 1;
19023
19024 if (prohibs)
19025 prohibs->nbItems = 0;
19026
19027 for (i = 0; i < list->nbItems; i++) {
19028 use = list->items[i];
19029
19030 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19031 if (prohibs == NULL) {
19032 PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19033 "unexpected attr prohibition found");
19034 return(-1);
19035 }
19036 /*
19037 * Remove from attribute uses.
19038 */
19039 if (xmlSchemaItemListRemove(list, i) == -1)
19040 return(-1);
19041 i--;
19042 /*
19043 * Note that duplicate prohibitions were already
19044 * handled at parsing time.
19045 */
19046 /*
19047 * Add to list of prohibitions.
19048 */
19049 xmlSchemaItemListAddSize(prohibs, 2, use);
19050 continue;
19051 }
19052 if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19053 ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19054 {
19055 if ((WXS_QNAME_CAST use)->item == NULL)
19056 return(-1);
19057 gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19058 /*
19059 * Expand the referenced attr. group.
19060 * TODO: remove this, this is done in a previous step, so
19061 * already done here.
19062 */
19063 if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19064 if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19065 return(-1);
19066 }
19067 /*
19068 * Build the 'complete' wildcard; i.e. intersect multiple
19069 * wildcards.
19070 */
19071 if (gr->attributeWildcard != NULL) {
19072 if (*completeWild == NULL) {
19073 *completeWild = gr->attributeWildcard;
19074 } else {
19075 if (! created) {
19076 xmlSchemaWildcardPtr tmpWild;
19077
19078 /*
19079 * Copy the first encountered wildcard as context,
19080 * except for the annotation.
19081 *
19082 * Although the complete wildcard might not correspond
19083 * to any node in the schema, we will anchor it on
19084 * the node of the owner component.
19085 */
19086 tmpWild = xmlSchemaAddWildcard(pctxt, pctxt->schema,
19087 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19088 WXS_ITEM_NODE(item));
19089 if (tmpWild == NULL)
19090 return(-1);
19091 if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19092 tmpWild, *completeWild) == -1)
19093 return (-1);
19094 tmpWild->processContents = (*completeWild)->processContents;
19095 *completeWild = tmpWild;
19096 created = 1;
19097 }
19098
19099 if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19100 gr->attributeWildcard) == -1)
19101 return(-1);
19102 }
19103 }
19104 /*
19105 * Just remove the reference if the referenced group does not
19106 * contain any attribute uses.
19107 */
19108 if (gr->attrUses == NULL) {
19109 if (xmlSchemaItemListRemove(list, i) == -1)
19110 return(-1);
19111 i--;
19112 continue;
19113 }
19114 /*
19115 * Add the attribute uses.
19116 */
19117 sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19118 if (sublist->nbItems != 0) {
19119 list->items[i] = sublist->items[0];
19120 if (sublist->nbItems != 1) {
19121 for (j = 1; j < sublist->nbItems; j++) {
19122 i++;
19123 if (xmlSchemaItemListInsert(list,
19124 sublist->items[j], i) == -1)
19125 return(-1);
19126 }
19127 }
19128 }
19129 }
19130
19131 }
19132 /*
19133 * Handle pointless prohibitions of declared attributes.
19134 */
19135 if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19136 xmlSchemaAttributeUseProhibPtr prohib;
19137
19138 for (i = prohibs->nbItems -1; i >= 0; i--) {
19139 prohib = prohibs->items[i];
19140 for (j = 0; j < list->nbItems; j++) {
19141 use = list->items[j];
19142
19143 if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19144 (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19145 {
19146 xmlChar *str = NULL;
19147
19148 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19149 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19150 prohib->node, NULL,
19151 "Skipping pointless attribute use prohibition "
19152 "'%s', since a corresponding attribute use "
19153 "exists already in the type definition",
19154 xmlSchemaFormatQName(&str,
19155 prohib->targetNamespace, prohib->name),
19156 NULL, NULL);
19157 FREE_AND_NULL(str);
19158 /*
19159 * Remove the prohibition.
19160 */
19161 if (xmlSchemaItemListRemove(prohibs, i) == -1)
19162 return(-1);
19163 break;
19164 }
19165 }
19166 }
19167 }
19168 return(0);
19169}
19170
19171/**
19172 * xmlSchemaAttributeGroupExpandRefs:
19173 * @pctxt: the parser context
19174 * @attrGr: the attribute group definition
19175 *
19176 * Computation of:
19177 * {attribute uses} property
19178 * {attribute wildcard} property
19179 *
19180 * Substitutes contained attribute group references
19181 * for their attribute uses. Wilcards are intersected.
19182 */
19183static int
19184xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19185 xmlSchemaAttributeGroupPtr attrGr)
19186{
19187 if ((attrGr->attrUses == NULL) ||
19188 (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19189 return(0);
19190
19191 attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19192 if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19193 &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19194 return(-1);
19195 return(0);
19196}
19197
19198/**
19199 * xmlSchemaAttributeGroupExpandRefs:
19200 * @pctxt: the parser context
19201 * @attrGr: the attribute group definition
19202 *
19203 * Substitutes contained attribute group references
19204 * for their attribute uses. Wilcards are intersected.
19205 *
19206 * Schema Component Constraint:
19207 * Attribute Group Definition Properties Correct (ag-props-correct)
19208 */
19209static int
19210xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19211 xmlSchemaAttributeGroupPtr attrGr)
19212{
19213 /*
19214 * SPEC ag-props-correct
19215 * (1) "The values of the properties of an attribute group definition
19216 * must be as described in the property tableau in The Attribute
19217 * Group Definition Schema Component (§3.6.1), modulo the impact of
19218 * Missing Sub-components (§5.3);"
19219 */
19220
19221 if ((attrGr->attrUses != NULL) &&
19222 (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19223 {
19224 xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19225 xmlSchemaAttributeUsePtr use, tmp;
19226 int i, j, hasId = 0;
19227
19228 for (i = uses->nbItems -1; i >= 0; i--) {
19229 use = uses->items[i];
19230 /*
19231 * SPEC ag-props-correct
19232 * (2) "Two distinct members of the {attribute uses} must not have
19233 * {attribute declaration}s both of whose {name}s match and whose
19234 * {target namespace}s are identical."
19235 */
19236 if (i > 0) {
19237 for (j = i -1; j >= 0; j--) {
19238 tmp = uses->items[j];
19239 if ((WXS_ATTRUSE_DECL_NAME(use) ==
19240 WXS_ATTRUSE_DECL_NAME(tmp)) &&
19241 (WXS_ATTRUSE_DECL_TNS(use) ==
19242 WXS_ATTRUSE_DECL_TNS(tmp)))
19243 {
19244 xmlChar *str = NULL;
19245
19246 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19247 XML_SCHEMAP_AG_PROPS_CORRECT,
19248 attrGr->node, WXS_BASIC_CAST attrGr,
19249 "Duplicate %s",
19250 xmlSchemaGetComponentDesignation(&str, use),
19251 NULL);
19252 FREE_AND_NULL(str);
19253 /*
19254 * Remove the duplicate.
19255 */
19256 if (xmlSchemaItemListRemove(uses, i) == -1)
19257 return(-1);
19258 goto next_use;
19259 }
19260 }
19261 }
19262 /*
19263 * SPEC ag-props-correct
19264 * (3) "Two distinct members of the {attribute uses} must not have
19265 * {attribute declaration}s both of whose {type definition}s are or
19266 * are derived from ID."
19267 * TODO: Does 'derived' include member-types of unions?
19268 */
19269 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19270 if (xmlSchemaIsDerivedFromBuiltInType(
19271 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19272 {
19273 if (hasId) {
19274 xmlChar *str = NULL;
19275
19276 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19277 XML_SCHEMAP_AG_PROPS_CORRECT,
19278 attrGr->node, WXS_BASIC_CAST attrGr,
19279 "There must not exist more than one attribute "
19280 "declaration of type 'xs:ID' "
19281 "(or derived from 'xs:ID'). The %s violates this "
19282 "constraint",
19283 xmlSchemaGetComponentDesignation(&str, use),
19284 NULL);
19285 FREE_AND_NULL(str);
19286 if (xmlSchemaItemListRemove(uses, i) == -1)
19287 return(-1);
19288 }
19289 hasId = 1;
19290 }
19291 }
19292next_use: {}
19293 }
19294 }
19295 return(0);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019296}
19297
19298/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019299 * xmlSchemaResolveAttrGroupReferences:
Daniel Veillard13e04c62002-04-23 17:51:29 +000019300 * @attrgrpDecl: the schema attribute definition
19301 * @ctxt: the schema parser context
19302 * @name: the attribute name
19303 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019304 * Resolves references to attribute group definitions.
Daniel Veillard13e04c62002-04-23 17:51:29 +000019305 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019306static int
19307xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19308 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard13e04c62002-04-23 17:51:29 +000019309{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019310 xmlSchemaAttributeGroupPtr group;
Daniel Veillard13e04c62002-04-23 17:51:29 +000019311
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019312 if (ref->item != NULL)
19313 return(0);
19314 group = xmlSchemaGetAttributeGroup(ctxt->schema,
19315 ref->name,
19316 ref->targetNamespace);
19317 if (group == NULL) {
19318 xmlSchemaPResCompAttrErr(ctxt,
19319 XML_SCHEMAP_SRC_RESOLVE,
19320 NULL, ref->node,
19321 "ref", ref->name, ref->targetNamespace,
19322 ref->itemType, NULL);
19323 return(ctxt->err);
Daniel Veillard3646d642004-06-02 19:19:14 +000019324 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019325 ref->item = WXS_BASIC_CAST group;
19326 return(0);
Daniel Veillard13e04c62002-04-23 17:51:29 +000019327}
19328
19329/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019330 * xmlSchemaCheckAttrPropsCorrect:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019331 * @item: an schema attribute declaration/use
19332 * @ctxt: a schema parser context
19333 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019334 *
19335 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019336 * Schema Component Constraint:
19337 * Attribute Declaration Properties Correct (a-props-correct)
Daniel Veillard4255d502002-04-16 15:50:10 +000019338 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019339 * Validates the value constraints of an attribute declaration/use.
19340 * NOTE that this needs the simle type definitions to be already
19341 * builded and checked.
Daniel Veillard4255d502002-04-16 15:50:10 +000019342 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019343static int
19344xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19345 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019346{
19347
19348 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019349 * SPEC a-props-correct (1)
19350 * "The values of the properties of an attribute declaration must
19351 * be as described in the property tableau in The Attribute
19352 * Declaration Schema Component (§3.2.1), modulo the impact of
19353 * Missing Sub-components (§5.3)."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019354 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019355
19356 if (WXS_ATTR_TYPEDEF(attr) == NULL)
19357 return(0);
19358
19359 if (attr->defValue != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019360 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019361
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019362 /*
19363 * SPEC a-props-correct (3)
19364 * "If the {type definition} is or is derived from ID then there
19365 * must not be a {value constraint}."
19366 */
19367 if (xmlSchemaIsDerivedFromBuiltInType(
19368 WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19369 {
19370 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19371 XML_SCHEMAP_A_PROPS_CORRECT_3,
19372 NULL, WXS_BASIC_CAST attr,
19373 "Value constraints are not allowed if the type definition "
19374 "is or is derived from xs:ID",
19375 NULL, NULL);
19376 return(pctxt->err);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019377 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019378 /*
19379 * SPEC a-props-correct (2)
19380 * "if there is a {value constraint}, the canonical lexical
19381 * representation of its value must be ·valid· with respect
19382 * to the {type definition} as defined in String Valid (§3.14.4)."
19383 * TODO: Don't care about the *cononical* stuff here, this requirement
19384 * will be removed in WXS 1.1 anyway.
19385 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019386 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019387 attr->node, WXS_ATTR_TYPEDEF(attr),
19388 attr->defValue, &(attr->defVal),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019389 1, 1, 0);
19390 if (ret != 0) {
19391 if (ret < 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019392 PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019393 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019394 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019395 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019396 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019397 XML_SCHEMAP_A_PROPS_CORRECT_2,
19398 NULL, WXS_BASIC_CAST attr,
19399 "The value of the value constraint is not valid",
19400 NULL, NULL);
19401 return(pctxt->err);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019402 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019403 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019404
19405 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019406}
19407
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019408static xmlSchemaElementPtr
19409xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19410 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019411{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019412 xmlSchemaElementPtr ret;
19413
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019414 if (WXS_SUBST_HEAD(ancestor) == NULL)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019415 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019416 if (WXS_SUBST_HEAD(ancestor) == elemDecl)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019417 return (ancestor);
19418
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019419 if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019420 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019421 WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019422 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019423 WXS_SUBST_HEAD(ancestor));
19424 WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019425
19426 return (ret);
19427}
19428
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019429/**
19430 * xmlSchemaCheckElemPropsCorrect:
19431 * @ctxt: a schema parser context
19432 * @decl: the element declaration
19433 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019434 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019435 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019436 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019437 *
19438 * STATUS:
19439 * missing: (6)
19440 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019441static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019442xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19443 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019444{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019445 int ret = 0;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019446 xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019447 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019448 * SPEC (1) "The values of the properties of an element declaration
19449 * must be as described in the property tableau in The Element
19450 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
19451 * Sub-components (§5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019452 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019453 if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19454 xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019455
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019456 xmlSchemaCheckElementDeclComponent(head, pctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019457 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019458 * SPEC (3) "If there is a non-·absent· {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019459 * affiliation}, then {scope} must be global."
19460 */
19461 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19462 xmlSchemaPCustomErr(pctxt,
19463 XML_SCHEMAP_E_PROPS_CORRECT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019464 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019465 "Only global element declarations can have a "
19466 "substitution group affiliation", NULL);
19467 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019468 }
19469 /*
19470 * TODO: SPEC (6) "Circular substitution groups are disallowed.
19471 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019472 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019473 * property."
19474 */
19475 if (head == elemDecl)
19476 circ = head;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019477 else if (WXS_SUBST_HEAD(head) != NULL)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019478 circ = xmlSchemaCheckSubstGroupCircular(head, head);
19479 else
19480 circ = NULL;
19481 if (circ != NULL) {
19482 xmlChar *strA = NULL, *strB = NULL;
19483
19484 xmlSchemaPCustomErrExt(pctxt,
19485 XML_SCHEMAP_E_PROPS_CORRECT_6,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019486 WXS_BASIC_CAST circ, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019487 "The element declaration '%s' defines a circular "
19488 "substitution group to element declaration '%s'",
19489 xmlSchemaGetComponentQName(&strA, circ),
19490 xmlSchemaGetComponentQName(&strB, head),
19491 NULL);
19492 FREE_AND_NULL(strA)
19493 FREE_AND_NULL(strB)
19494 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19495 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019496 /*
19497 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019498 * the {type definition}
19499 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019500 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019501 * of the {substitution group exclusions} of the {substitution group
19502 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
19503 * (if the {type definition} is complex) or as defined in
19504 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019505 * simple)."
19506 *
19507 * NOTE: {substitution group exclusions} means the values of the
19508 * attribute "final".
19509 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019510
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019511 if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019512 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019513
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019514 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19515 set |= SUBSET_EXTENSION;
19516 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19517 set |= SUBSET_RESTRICTION;
19518
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000019519 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019520 WXS_ELEM_TYPEDEF(head), set) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019521 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19522
19523 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019524 xmlSchemaPCustomErrExt(pctxt,
19525 XML_SCHEMAP_E_PROPS_CORRECT_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019526 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019527 "The type definition '%s' was "
19528 "either rejected by the substitution group "
19529 "affiliation '%s', or not validly derived from its type "
19530 "definition '%s'",
19531 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019532 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019533 xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019534 FREE_AND_NULL(strA)
19535 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019536 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019537 }
19538 }
19539 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019540 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019541 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019542 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019543 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019544 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019545 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019546 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019547 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019548 ((WXS_IS_SIMPLE(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019549 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019550 (WXS_IS_COMPLEX(typeDef) &&
19551 WXS_HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019552 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19553 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019554
19555 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19556 xmlSchemaPCustomErr(pctxt,
19557 XML_SCHEMAP_E_PROPS_CORRECT_5,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019558 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019559 "The type definition (or type definition's content type) is or "
19560 "is derived from ID; value constraints are not allowed in "
19561 "conjunction with such a type definition", NULL);
19562 } else if (elemDecl->value != NULL) {
19563 int vcret;
19564 xmlNodePtr node = NULL;
19565
19566 /*
19567 * SPEC (2) "If there is a {value constraint}, the canonical lexical
19568 * representation of its value must be ·valid· with respect to the
19569 * {type definition} as defined in Element Default Valid (Immediate)
19570 * (§3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019571 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019572 if (typeDef == NULL) {
19573 xmlSchemaPErr(pctxt, elemDecl->node,
19574 XML_SCHEMAP_INTERNAL,
19575 "Internal error: xmlSchemaCheckElemPropsCorrect, "
19576 "type is missing... skipping validation of "
19577 "the value constraint", NULL, NULL);
19578 return (-1);
19579 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019580 if (elemDecl->node != NULL) {
19581 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19582 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19583 BAD_CAST "fixed");
19584 else
19585 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19586 BAD_CAST "default");
19587 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019588 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19589 typeDef, elemDecl->value, &(elemDecl->defVal));
19590 if (vcret != 0) {
19591 if (vcret < 0) {
19592 PERROR_INT("xmlSchemaElemCheckValConstr",
19593 "failed to validate the value constraint of an "
19594 "element declaration");
19595 return (-1);
19596 }
19597 return (vcret);
19598 }
19599 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019600
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019601 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019602}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019603
19604/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019605 * xmlSchemaCheckElemSubstGroup:
19606 * @ctxt: a schema parser context
19607 * @decl: the element declaration
19608 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019609 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019610 * Schema Component Constraint:
19611 * Substitution Group (cos-equiv-class)
19612 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019613 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019614 * a list will be built for each subst. group head, holding all direct
19615 * referents to this head.
19616 * NOTE that this function needs:
19617 * 1. circular subst. groups to be checked beforehand
19618 * 2. the declaration's type to be derived from the head's type
19619 *
19620 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019621 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019622 */
19623static void
19624xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19625 xmlSchemaElementPtr elemDecl)
19626{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019627 if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019628 /* SPEC (1) "Its {abstract} is false." */
19629 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19630 return;
19631 {
19632 xmlSchemaElementPtr head;
19633 xmlSchemaTypePtr headType, type;
19634 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019635 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019636 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19637 * {disallowed substitutions} as the blocking constraint, as defined in
19638 * Substitution Group OK (Transitive) (§3.3.6)."
19639 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019640 for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19641 head = WXS_SUBST_HEAD(head)) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019642 set = 0;
19643 methSet = 0;
19644 /*
19645 * The blocking constraints.
19646 */
19647 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19648 continue;
19649 headType = head->subtypes;
19650 type = elemDecl->subtypes;
19651 if (headType == type)
19652 goto add_member;
19653 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19654 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19655 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19656 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19657 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019658 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019659 * "The set of all {derivation method}s involved in the
19660 * derivation of D's {type definition} from C's {type definition}
19661 * does not intersect with the union of the blocking constraint,
19662 * C's {prohibited substitutions} (if C is complex, otherwise the
19663 * empty set) and the {prohibited substitutions} (respectively the
19664 * empty set) of any intermediate {type definition}s in the
19665 * derivation of D's {type definition} from C's {type definition}."
19666 */
19667 /*
19668 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19669 * subst.head axis, the methSet does not need to be computed for
19670 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019671 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019672 /*
19673 * The set of all {derivation method}s involved in the derivation
19674 */
19675 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019676 if ((WXS_IS_EXTENSION(type)) &&
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019677 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19678 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019679
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019680 if (WXS_IS_RESTRICTION(type) &&
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019681 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19682 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19683
19684 type = type->baseType;
19685 }
19686 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019687 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019688 * the head's type.
19689 */
19690 type = elemDecl->subtypes->baseType;
19691 while (type != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019692 if (WXS_IS_COMPLEX(type)) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019693 if ((type->flags &
19694 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19695 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19696 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19697 if ((type->flags &
19698 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19699 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19700 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19701 } else
19702 break;
19703 if (type == headType)
19704 break;
19705 type = type->baseType;
19706 }
19707 if ((set != 0) &&
19708 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19709 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19710 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19711 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19712 continue;
19713 }
19714add_member:
19715 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19716 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19717 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19718 }
19719 }
19720}
19721
19722/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019723 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019724 * @item: an schema element declaration/particle
19725 * @ctxt: a schema parser context
19726 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019727 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019728 * Validates the value constraints of an element declaration.
19729 *
19730 * Fixes finish doing the computations on the element declarations.
19731 */
19732static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019733xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019734 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019735{
19736 if (elemDecl == NULL)
19737 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019738 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19739 return;
19740 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019741 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
19742 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019743}
19744
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019745/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019746 * xmlSchemaResolveModelGroupParticleReferences:
19747 * @particle: a particle component
19748 * @ctxt: a parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019749 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019750 * Resolves references of a model group's {particles} to
19751 * model group definitions and to element declarations.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019752 */
19753static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019754xmlSchemaResolveModelGroupParticleReferences(
19755 xmlSchemaParserCtxtPtr ctxt,
19756 xmlSchemaModelGroupPtr mg)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019757{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019758 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19759 xmlSchemaQNameRefPtr ref;
19760 xmlSchemaBasicItemPtr refItem;
19761
19762 /*
19763 * URGENT TODO: Test this.
19764 */
19765 while (particle != NULL) {
19766 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19767 ((WXS_PARTICLE_TERM(particle))->type !=
19768 XML_SCHEMA_EXTRA_QNAMEREF))
19769 {
19770 goto next_particle;
19771 }
19772 ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019773 /*
19774 * Resolve the reference.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019775 * NULL the {term} by default.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019776 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019777 particle->children = NULL;
19778
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019779 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
19780 ref->itemType, ref->name, ref->targetNamespace);
19781 if (refItem == NULL) {
19782 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019783 NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019784 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019785 /* TODO: remove the particle. */
19786 goto next_particle;
19787 }
19788 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
19789 if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
19790 /* TODO: remove the particle. */
19791 goto next_particle;
19792 /*
19793 * NOTE that we will assign the model group definition
19794 * itself to the "term" of the particle. This will ease
19795 * the check for circular model group definitions. After
19796 * that the "term" will be assigned the model group of the
19797 * model group definition.
19798 */
19799 if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
19800 XML_SCHEMA_TYPE_ALL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019801 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019802 * SPEC cos-all-limited (1)
19803 * SPEC cos-all-limited (1.2)
19804 * "It appears only as the value of one or both of the
19805 * following properties:"
19806 * (1.1) "the {model group} property of a model group
19807 * definition."
19808 * (1.2) "the {term} property of a particle [... of] the "
19809 * {content type} of a complex type definition."
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019810 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019811 xmlSchemaCustomErr(ACTXT_CAST ctxt,
19812 /* TODO: error code */
19813 XML_SCHEMAP_COS_ALL_LIMITED,
19814 WXS_ITEM_NODE(particle), NULL,
19815 "A model group definition is referenced, but "
19816 "it contains an 'all' model group, which "
19817 "cannot be contained by model groups",
19818 NULL, NULL);
19819 /* TODO: remove the particle. */
19820 goto next_particle;
19821 }
19822 particle->children = (xmlSchemaTreeItemPtr) refItem;
19823 } else {
19824 /*
19825 * TODO: Are referenced element declarations the only
19826 * other components we expect here?
19827 */
19828 particle->children = (xmlSchemaTreeItemPtr) refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019829 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019830next_particle:
19831 particle = WXS_PTC_CAST particle->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019832 }
19833}
19834
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019835static int
19836xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
19837 xmlSchemaValPtr y)
19838{
19839 xmlSchemaTypePtr tx, ty, ptx, pty;
19840 int ret;
19841
19842 while (x != NULL) {
19843 /* Same types. */
19844 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
19845 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
19846 ptx = xmlSchemaGetPrimitiveType(tx);
19847 pty = xmlSchemaGetPrimitiveType(ty);
19848 /*
19849 * (1) if a datatype T' is ·derived· by ·restriction· from an
19850 * atomic datatype T then the ·value space· of T' is a subset of
19851 * the ·value space· of T. */
19852 /*
19853 * (2) if datatypes T' and T'' are ·derived· by ·restriction·
19854 * from a common atomic ancestor T then the ·value space·s of T'
19855 * and T'' may overlap.
19856 */
19857 if (ptx != pty)
19858 return(0);
19859 /*
19860 * We assume computed values to be normalized, so do a fast
19861 * string comparison for string based types.
19862 */
19863 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019864 WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019865 if (! xmlStrEqual(
19866 xmlSchemaValueGetAsString(x),
19867 xmlSchemaValueGetAsString(y)))
19868 return (0);
19869 } else {
19870 ret = xmlSchemaCompareValuesWhtsp(
19871 x, XML_SCHEMA_WHITESPACE_PRESERVE,
19872 y, XML_SCHEMA_WHITESPACE_PRESERVE);
19873 if (ret == -2)
19874 return(-1);
19875 if (ret != 0)
19876 return(0);
19877 }
19878 /*
19879 * Lists.
19880 */
19881 x = xmlSchemaValueGetNext(x);
19882 if (x != NULL) {
19883 y = xmlSchemaValueGetNext(y);
19884 if (y == NULL)
19885 return (0);
19886 } else if (xmlSchemaValueGetNext(y) != NULL)
19887 return (0);
19888 else
19889 return (1);
19890 }
19891 return (0);
19892}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019893
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019894/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019895 * xmlSchemaResolveAttrUseReferences:
19896 * @item: an attribute use
19897 * @ctxt: a parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019898 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019899 * Resolves the referenced attribute declaration.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019900 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019901static int
19902xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
19903 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000019904{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019905 if ((ctxt == NULL) || (ause == NULL))
19906 return(-1);
19907 if ((ause->attrDecl == NULL) ||
19908 (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
19909 return(0);
19910
19911 {
19912 xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
19913
19914 /*
19915 * TODO: Evaluate, what errors could occur if the declaration is not
19916 * found.
19917 */
19918 ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
19919 ref->name, ref->targetNamespace);
19920 if (ause->attrDecl == NULL) {
19921 xmlSchemaPResCompAttrErr(ctxt,
19922 XML_SCHEMAP_SRC_RESOLVE,
19923 WXS_BASIC_CAST ause, ause->node,
19924 "ref", ref->name, ref->targetNamespace,
19925 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
19926 return(ctxt->err);;
19927 }
19928 }
19929 return(0);
19930}
19931
19932/**
19933 * xmlSchemaCheckAttrUsePropsCorrect:
19934 * @ctxt: a parser context
19935 * @use: an attribute use
19936 *
19937 * Schema Component Constraint:
19938 * Attribute Use Correct (au-props-correct)
19939 *
19940 */
19941static int
19942xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
19943 xmlSchemaAttributeUsePtr use)
19944{
19945 if ((ctxt == NULL) || (use == NULL))
19946 return(-1);
19947 if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
19948 ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
19949 return(0);
19950
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019951 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019952 * SPEC au-props-correct (1)
19953 * "The values of the properties of an attribute use must be as
19954 * described in the property tableau in The Attribute Use Schema
19955 * Component (§3.5.1), modulo the impact of Missing
19956 * Sub-components (§5.3)."
Daniel Veillardc0826a72004-08-10 14:17:33 +000019957 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019958
19959 if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
19960 ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
19961 ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
19962 {
19963 xmlSchemaPCustomErr(ctxt,
19964 XML_SCHEMAP_AU_PROPS_CORRECT_2,
19965 WXS_BASIC_CAST use, NULL,
19966 "The attribute declaration has a 'fixed' value constraint "
19967 ", thus the attribute use must also have a 'fixed' value "
19968 "constraint",
19969 NULL);
19970 return(ctxt->err);
19971 }
19972 /*
19973 * Compute and check the value constraint's value.
19974 */
19975 if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
19976 int ret;
19977 /*
19978 * TODO: The spec seems to be missing a check of the
19979 * value constraint of the attribute use. We will do it here.
19980 */
19981 /*
19982 * SPEC a-props-correct (3)
19983 */
19984 if (xmlSchemaIsDerivedFromBuiltInType(
19985 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19986 {
19987 xmlSchemaCustomErr(ACTXT_CAST ctxt,
19988 XML_SCHEMAP_AU_PROPS_CORRECT,
19989 NULL, WXS_BASIC_CAST use,
19990 "Value constraints are not allowed if the type definition "
19991 "is or is derived from xs:ID",
19992 NULL, NULL);
19993 return(ctxt->err);
19994 }
19995
19996 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
19997 use->node, WXS_ATTRUSE_TYPEDEF(use),
19998 use->defValue, &(use->defVal),
19999 1, 1, 0);
20000 if (ret != 0) {
20001 if (ret < 0) {
20002 PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20003 "calling xmlSchemaVCheckCVCSimpleType()");
20004 return(-1);
20005 }
20006 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20007 XML_SCHEMAP_AU_PROPS_CORRECT,
20008 NULL, WXS_BASIC_CAST use,
20009 "The value of the value constraint is not valid",
20010 NULL, NULL);
20011 return(ctxt->err);
20012 }
20013 }
20014 /*
20015 * SPEC au-props-correct (2)
20016 * "If the {attribute declaration} has a fixed
20017 * {value constraint}, then if the attribute use itself has a
20018 * {value constraint}, it must also be fixed and its value must match
20019 * that of the {attribute declaration}'s {value constraint}."
20020 */
20021 if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20022 (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20023 {
20024 if (! xmlSchemaAreValuesEqual(use->defVal,
20025 (WXS_ATTRUSE_DECL(use))->defVal))
20026 {
20027 xmlSchemaPCustomErr(ctxt,
20028 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20029 WXS_BASIC_CAST use, NULL,
20030 "The 'fixed' value constraint of the attribute use "
20031 "must match the attribute declaration's value "
20032 "constraint '%s'",
20033 (WXS_ATTRUSE_DECL(use))->defValue);
20034 }
20035 return(ctxt->err);
20036 }
20037 return(0);
20038}
20039
20040
20041
20042
20043/**
20044 * xmlSchemaResolveAttrTypeReferences:
20045 * @item: an attribute declaration
20046 * @ctxt: a parser context
20047 *
20048 * Resolves the referenced type definition component.
20049 */
20050static int
20051xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20052 xmlSchemaParserCtxtPtr ctxt)
20053{
Daniel Veillard01fa6152004-06-29 17:04:39 +000020054 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020055 * The simple type definition corresponding to the <simpleType> element
20056 * information item in the [children], if present, otherwise the simple
20057 * type definition ·resolved· to by the ·actual value· of the type
Daniel Veillard01fa6152004-06-29 17:04:39 +000020058 * [attribute], if present, otherwise the ·simple ur-type definition·.
20059 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020060 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020061 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020062 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20063 if (item->subtypes != NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020064 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020065 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020066 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000020067
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020068 type = xmlSchemaGetType(ctxt->schema, item->typeName,
20069 item->typeNs);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020070 if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000020071 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000020072 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020073 WXS_BASIC_CAST item, item->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020074 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020075 XML_SCHEMA_TYPE_SIMPLE, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020076 return(ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020077 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020078 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020079
Daniel Veillard3646d642004-06-02 19:19:14 +000020080 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020081 /*
20082 * The type defaults to the xs:anySimpleType.
20083 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020084 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20085 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020086 return(0);
Daniel Veillard4255d502002-04-16 15:50:10 +000020087}
20088
20089/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020090 * xmlSchemaResolveIDCKeyReferences:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020091 * @idc: the identity-constraint definition
20092 * @ctxt: the schema parser context
20093 * @name: the attribute name
20094 *
20095 * Resolve keyRef references to key/unique IDCs.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020096 * Schema Component Constraint:
20097 * Identity-constraint Definition Properties Correct (c-props-correct)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020098 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020099static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020100xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020101 xmlSchemaParserCtxtPtr pctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020102{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020103 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020104 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020105 if (idc->ref->name != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020106 idc->ref->item = (xmlSchemaBasicItemPtr)
20107 xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20108 idc->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020109 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020110 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020111 * TODO: It is actually not an error to fail to resolve
20112 * at this stage. BUT we need to be that strict!
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020113 */
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020114 xmlSchemaPResCompAttrErr(pctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020115 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020116 WXS_BASIC_CAST idc, idc->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020117 "refer", idc->ref->name,
20118 idc->ref->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020119 XML_SCHEMA_TYPE_IDC_KEY, NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020120 return(pctxt->err);
20121 } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20122 /*
20123 * SPEC c-props-correct (1)
20124 */
20125 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20126 XML_SCHEMAP_C_PROPS_CORRECT,
20127 NULL, WXS_BASIC_CAST idc,
20128 "The keyref references a keyref",
20129 NULL, NULL);
20130 idc->ref->item = NULL;
20131 return(pctxt->err);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020132 } else {
20133 if (idc->nbFields !=
20134 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20135 xmlChar *str = NULL;
20136 xmlSchemaIDCPtr refer;
20137
20138 refer = (xmlSchemaIDCPtr) idc->ref->item;
20139 /*
20140 * SPEC c-props-correct(2)
20141 * "If the {identity-constraint category} is keyref,
20142 * the cardinality of the {fields} must equal that of
20143 * the {fields} of the {referenced key}.
20144 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020145 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020146 XML_SCHEMAP_C_PROPS_CORRECT,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020147 NULL, WXS_BASIC_CAST idc,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020148 "The cardinality of the keyref differs from the "
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020149 "cardinality of the referenced key/unique '%s'",
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020150 xmlSchemaFormatQName(&str, refer->targetNamespace,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020151 refer->name),
20152 NULL);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020153 FREE_AND_NULL(str)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020154 return(pctxt->err);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020155 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020156 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020157 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020158 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020159}
20160
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020161static int
20162xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20163 xmlSchemaParserCtxtPtr pctxt)
20164{
20165 if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20166 prohib->targetNamespace) == NULL) {
20167
20168 xmlSchemaPResCompAttrErr(pctxt,
20169 XML_SCHEMAP_SRC_RESOLVE,
20170 NULL, prohib->node,
20171 "ref", prohib->name, prohib->targetNamespace,
20172 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20173 return(XML_SCHEMAP_SRC_RESOLVE);
20174 }
20175 return(0);
20176}
20177
20178#define WXS_REDEFINED_TYPE(c) \
20179(((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20180
20181#define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20182(((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20183
20184#define WXS_REDEFINED_ATTR_GROUP(c) \
20185(((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20186
20187static int
20188xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20189{
20190 int err = 0;
20191 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20192 xmlSchemaBasicItemPtr prev, item;
20193 int wasRedefined;
20194
20195 if (redef == NULL)
20196 return(0);
20197
20198 do {
20199 item = redef->item;
20200 /*
20201 * First try to locate the redefined component in the
20202 * schema graph starting with the redefined schema.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020203 * NOTE: According to this schema bug entry:
20204 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20205 * it's not clear if the referenced component needs to originate
20206 * from the <redefine>d schema _document_ or the schema; the latter
20207 * would include all imported and included sub-schemas of the
20208 * <redefine>d schema. Currenlty we latter approach is used.
20209 * SUPPLEMENT: It seems that the WG moves towards the latter
20210 * approach, so we are doing it right.
20211 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020212 */
20213 prev = xmlSchemaFindRedefCompInGraph(
20214 redef->targetBucket, item->type,
20215 redef->refName, redef->refTargetNs);
20216 if (prev == NULL) {
20217 xmlChar *str = NULL;
20218 xmlNodePtr node;
20219
20220 /*
20221 * SPEC src-redefine:
20222 * (6.2.1) "The ·actual value· of its own name attribute plus
20223 * target namespace must successfully ·resolve· to a model
20224 * group definition in I."
20225 * (7.2.1) "The ·actual value· of its own name attribute plus
20226 * target namespace must successfully ·resolve· to an attribute
20227 * group definition in I."
20228
20229 *
20230 * Note that, if we are redefining with the use of references
20231 * to components, the spec assumes the src-resolve to be used;
20232 * but this won't assure that we search only *inside* the
20233 * redefined schema.
20234 */
20235 if (redef->reference)
20236 node = WXS_ITEM_NODE(redef->reference);
20237 else
20238 node = WXS_ITEM_NODE(item);
20239 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20240 /*
20241 * TODO: error code.
20242 * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20243 * reference kind.
20244 */
20245 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
Kasimier T. Buchcik5d2998b2005-11-22 17:36:01 +000020246 "The %s '%s' to be redefined could not be found in "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020247 "the redefined schema",
20248 WXS_ITEM_TYPE_NAME(item),
20249 xmlSchemaFormatQName(&str, redef->refTargetNs,
20250 redef->refName));
20251 FREE_AND_NULL(str);
20252 err = pctxt->err;
20253 redef = redef->next;
20254 continue;
20255 }
20256 /*
20257 * TODO: Obtaining and setting the redefinition state is really
20258 * clumsy.
20259 */
20260 wasRedefined = 0;
20261 switch (item->type) {
20262 case XML_SCHEMA_TYPE_COMPLEX:
20263 case XML_SCHEMA_TYPE_SIMPLE:
20264 if ((WXS_TYPE_CAST prev)->flags &
20265 XML_SCHEMAS_TYPE_REDEFINED)
20266 {
20267 wasRedefined = 1;
20268 break;
20269 }
20270 /* Mark it as redefined. */
20271 (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20272 /*
20273 * Assign the redefined type to the
20274 * base type of the redefining type.
20275 * TODO: How
20276 */
20277 ((xmlSchemaTypePtr) item)->baseType =
20278 (xmlSchemaTypePtr) prev;
20279 break;
20280 case XML_SCHEMA_TYPE_GROUP:
20281 if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20282 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20283 {
20284 wasRedefined = 1;
20285 break;
20286 }
20287 /* Mark it as redefined. */
20288 (WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20289 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20290 if (redef->reference != NULL) {
20291 /*
20292 * Overwrite the QName-reference with the
20293 * referenced model group def.
20294 */
20295 (WXS_PTC_CAST redef->reference)->children =
20296 WXS_TREE_CAST prev;
20297 }
20298 redef->target = prev;
20299 break;
20300 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20301 if ((WXS_ATTR_GROUP_CAST prev)->flags &
20302 XML_SCHEMAS_ATTRGROUP_REDEFINED)
20303 {
20304 wasRedefined = 1;
20305 break;
20306 }
20307 (WXS_ATTR_GROUP_CAST prev)->flags |=
20308 XML_SCHEMAS_ATTRGROUP_REDEFINED;
20309 if (redef->reference != NULL) {
20310 /*
20311 * Assign the redefined attribute group to the
20312 * QName-reference component.
20313 * This is the easy case, since we will just
20314 * expand the redefined group.
20315 */
20316 (WXS_QNAME_CAST redef->reference)->item = prev;
20317 redef->target = NULL;
20318 } else {
20319 /*
20320 * This is the complicated case: we need
20321 * to apply src-redefine (7.2.2) at a later
20322 * stage, i.e. when attribute group references
20323 * have beed expanded and simple types have
20324 * beed fixed.
20325 */
20326 redef->target = prev;
20327 }
20328 break;
20329 default:
20330 PERROR_INT("xmlSchemaResolveRedefReferences",
20331 "Unexpected redefined component type");
20332 return(-1);
20333 }
20334 if (wasRedefined) {
20335 xmlChar *str = NULL;
20336 xmlNodePtr node;
20337
20338 if (redef->reference)
20339 node = WXS_ITEM_NODE(redef->reference);
20340 else
20341 node = WXS_ITEM_NODE(redef->item);
20342
20343 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20344 /* TODO: error code. */
20345 XML_SCHEMAP_SRC_REDEFINE,
20346 node, NULL,
20347 "The referenced %s was already redefined. Multiple "
20348 "redefinition of the same component is not supported",
20349 xmlSchemaGetComponentDesignation(&str, prev),
20350 NULL);
20351 FREE_AND_NULL(str)
20352 err = pctxt->err;
20353 redef = redef->next;
20354 continue;
20355 }
20356 redef = redef->next;
20357 } while (redef != NULL);
20358
20359 return(err);
20360}
20361
20362static int
20363xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20364{
20365 int err = 0;
20366 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20367 xmlSchemaBasicItemPtr item;
20368
20369 if (redef == NULL)
20370 return(0);
20371
20372 do {
20373 if (redef->target == NULL) {
20374 redef = redef->next;
20375 continue;
20376 }
20377 item = redef->item;
20378
20379 switch (item->type) {
20380 case XML_SCHEMA_TYPE_SIMPLE:
20381 case XML_SCHEMA_TYPE_COMPLEX:
20382 /*
20383 * Since the spec wants the {name} of the redefined
20384 * type to be 'absent', we'll NULL it.
20385 */
20386 (WXS_TYPE_CAST redef->target)->name = NULL;
20387
20388 /*
20389 * TODO: Seems like there's nothing more to do. The normal
20390 * inheritance mechanism is used. But not 100% sure.
20391 */
20392 break;
20393 case XML_SCHEMA_TYPE_GROUP:
20394 /*
20395 * URGENT TODO:
20396 * SPEC src-redefine:
20397 * (6.2.2) "The {model group} of the model group definition
20398 * which corresponds to it per XML Representation of Model
20399 * Group Definition Schema Components (§3.7.2) must be a
20400 * ·valid restriction· of the {model group} of that model
20401 * group definition in I, as defined in Particle Valid
20402 * (Restriction) (§3.9.6)."
20403 */
20404 break;
20405 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20406 /*
20407 * SPEC src-redefine:
20408 * (7.2.2) "The {attribute uses} and {attribute wildcard} of
20409 * the attribute group definition which corresponds to it
20410 * per XML Representation of Attribute Group Definition Schema
20411 * Components (§3.6.2) must be ·valid restrictions· of the
20412 * {attribute uses} and {attribute wildcard} of that attribute
20413 * group definition in I, as defined in clause 2, clause 3 and
20414 * clause 4 of Derivation Valid (Restriction, Complex)
20415 * (§3.4.6) (where references to the base type definition are
20416 * understood as references to the attribute group definition
20417 * in I)."
20418 */
20419 err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20420 XML_SCHEMA_ACTION_REDEFINE,
20421 item, redef->target,
20422 (WXS_ATTR_GROUP_CAST item)->attrUses,
20423 (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20424 (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20425 (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20426 if (err == -1)
20427 return(-1);
20428 break;
20429 default:
20430 break;
20431 }
20432 redef = redef->next;
20433 } while (redef != NULL);
20434 return(0);
20435}
20436
20437
20438static int
20439xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20440 xmlSchemaBucketPtr bucket)
20441{
20442 xmlSchemaBasicItemPtr item;
20443 int err;
20444 xmlHashTablePtr *table;
20445 const xmlChar *name;
20446 int i;
20447
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020448#define WXS_GET_GLOBAL_HASH(c, slot) { \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020449 if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20450 table = &(WXS_IMPBUCKET((c))->schema->slot); \
20451 else \
20452 table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20453
20454 /*
20455 * Add global components to the schema's hash tables.
20456 * This is the place where duplicate components will be
20457 * detected.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020458 * TODO: I think normally we should support imports of the
20459 * same namespace from multiple locations. We don't do currently,
20460 * but if we do then according to:
20461 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20462 * we would need, if imported directly, to import redefined
20463 * components as well to be able to catch clashing components.
20464 * (I hope I'll still know what this means after some months :-()
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020465 */
20466 if (bucket == NULL)
20467 return(-1);
20468 if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20469 return(0);
20470 bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20471
20472 for (i = 0; i < bucket->globals->nbItems; i++) {
20473 item = bucket->globals->items[i];
20474 table = NULL;
20475 switch (item->type) {
20476 case XML_SCHEMA_TYPE_COMPLEX:
20477 case XML_SCHEMA_TYPE_SIMPLE:
20478 if (WXS_REDEFINED_TYPE(item))
20479 continue;
20480 name = (WXS_TYPE_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020481 WXS_GET_GLOBAL_HASH(bucket, typeDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020482 break;
20483 case XML_SCHEMA_TYPE_ELEMENT:
20484 name = (WXS_ELEM_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020485 WXS_GET_GLOBAL_HASH(bucket, elemDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020486 break;
20487 case XML_SCHEMA_TYPE_ATTRIBUTE:
20488 name = (WXS_ATTR_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020489 WXS_GET_GLOBAL_HASH(bucket, attrDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020490 break;
20491 case XML_SCHEMA_TYPE_GROUP:
20492 if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20493 continue;
20494 name = (WXS_MODEL_GROUPDEF_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020495 WXS_GET_GLOBAL_HASH(bucket, groupDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020496 break;
20497 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20498 if (WXS_REDEFINED_ATTR_GROUP(item))
20499 continue;
20500 name = (WXS_ATTR_GROUP_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020501 WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020502 break;
20503 case XML_SCHEMA_TYPE_IDC_KEY:
20504 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20505 case XML_SCHEMA_TYPE_IDC_KEYREF:
20506 name = (WXS_IDC_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020507 WXS_GET_GLOBAL_HASH(bucket, idcDef)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020508 break;
20509 case XML_SCHEMA_TYPE_NOTATION:
20510 name = ((xmlSchemaNotationPtr) item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020511 WXS_GET_GLOBAL_HASH(bucket, notaDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020512 break;
20513 default:
20514 PERROR_INT("xmlSchemaAddComponents",
20515 "Unexpected global component type");
20516 continue;
20517 }
20518 if (*table == NULL) {
20519 *table = xmlHashCreateDict(10, pctxt->dict);
20520 if (*table == NULL) {
20521 PERROR_INT("xmlSchemaAddComponents",
20522 "failed to create a component hash table");
20523 return(-1);
20524 }
20525 }
20526 err = xmlHashAddEntry(*table, name, item);
20527 if (err != 0) {
20528 xmlChar *str = NULL;
20529
20530 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20531 XML_SCHEMAP_REDEFINED_TYPE,
20532 WXS_ITEM_NODE(item),
20533 WXS_BASIC_CAST item,
20534 "A global %s '%s' does already exist",
20535 WXS_ITEM_TYPE_NAME(item),
20536 xmlSchemaGetComponentQName(&str, item));
20537 FREE_AND_NULL(str);
20538 }
20539 }
20540 /*
20541 * Process imported/included schemas.
20542 */
20543 if (bucket->relations != NULL) {
20544 xmlSchemaSchemaRelationPtr rel = bucket->relations;
20545 do {
20546 if ((rel->bucket != NULL) &&
20547 ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20548 if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20549 return(-1);
20550 }
20551 rel = rel->next;
20552 } while (rel != NULL);
20553 }
20554 return(0);
20555}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020556
20557static int
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020558xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20559 xmlSchemaBucketPtr rootBucket)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020560{
20561 xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20562 xmlSchemaTreeItemPtr item, *items;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020563 int nbItems, i, ret = 0;
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000020564 xmlSchemaBucketPtr oldbucket = con->bucket;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020565
20566#define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20567
20568 if ((con->pending == NULL) ||
20569 (con->pending->nbItems == 0))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020570 return(0);
20571
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000020572 /*
20573 * Since xmlSchemaFixupComplexType() will create new particles
20574 * (local components), and those particle components need a bucket
20575 * on the constructor, we'll assure here that the constructor has
20576 * a bucket.
20577 * TODO: Think about storing locals _only_ on the main bucket.
20578 */
20579 if (con->bucket == NULL)
20580 con->bucket = rootBucket;
20581
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020582 /* TODO:
20583 * SPEC (src-redefine):
20584 * (6.2) "If it has no such self-reference, then all of the
20585 * following must be true:"
20586
20587 * (6.2.2) The {model group} of the model group definition which
20588 * corresponds to it per XML Representation of Model Group
20589 * Definition Schema Components (§3.7.2) must be a ·valid
20590 * restriction· of the {model group} of that model group definition
20591 * in I, as defined in Particle Valid (Restriction) (§3.9.6)."
20592 */
20593 xmlSchemaCheckSRCRedefineFirst(pctxt);
20594
20595 /*
20596 * Add global components to the schemata's hash tables.
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000020597 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020598 xmlSchemaAddComponents(pctxt, rootBucket);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020599
20600 pctxt->ctxtType = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020601 items = (xmlSchemaTreeItemPtr *) con->pending->items;
20602 nbItems = con->pending->nbItems;
20603 /*
20604 * Now that we have parsed *all* the schema document(s) and converted
20605 * them to schema components, we can resolve references, apply component
20606 * constraints, create the FSA from the content model, etc.
20607 */
20608 /*
20609 * Resolve references of..
20610 *
20611 * 1. element declarations:
20612 * - the type definition
20613 * - the substitution group affiliation
20614 * 2. simple/complex types:
20615 * - the base type definition
20616 * - the memberTypes of union types
20617 * - the itemType of list types
20618 * 3. attributes declarations and attribute uses:
20619 * - the type definition
20620 * - if an attribute use, then the attribute declaration
20621 * 4. attribute group references:
20622 * - the attribute group definition
20623 * 5. particles:
20624 * - the term of the particle (e.g. a model group)
20625 * 6. IDC key-references:
20626 * - the referenced IDC 'key' or 'unique' definition
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020627 * 7. Attribute prohibitions which had a "ref" attribute.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020628 */
20629 for (i = 0; i < nbItems; i++) {
20630 item = items[i];
20631 switch (item->type) {
20632 case XML_SCHEMA_TYPE_ELEMENT:
20633 xmlSchemaResolveElementReferences(
20634 (xmlSchemaElementPtr) item, pctxt);
20635 FIXHFAILURE;
20636 break;
20637 case XML_SCHEMA_TYPE_COMPLEX:
20638 case XML_SCHEMA_TYPE_SIMPLE:
20639 xmlSchemaResolveTypeReferences(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020640 (xmlSchemaTypePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020641 FIXHFAILURE;
20642 break;
20643 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020644 xmlSchemaResolveAttrTypeReferences(
20645 (xmlSchemaAttributePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020646 FIXHFAILURE;
20647 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020648 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20649 xmlSchemaResolveAttrUseReferences(
20650 (xmlSchemaAttributeUsePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020651 FIXHFAILURE;
20652 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020653 case XML_SCHEMA_EXTRA_QNAMEREF:
20654 if ((WXS_QNAME_CAST item)->itemType ==
20655 XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20656 {
20657 xmlSchemaResolveAttrGroupReferences(
20658 WXS_QNAME_CAST item, pctxt);
20659 }
20660 FIXHFAILURE;
20661 break;
20662 case XML_SCHEMA_TYPE_SEQUENCE:
20663 case XML_SCHEMA_TYPE_CHOICE:
20664 case XML_SCHEMA_TYPE_ALL:
20665 xmlSchemaResolveModelGroupParticleReferences(pctxt,
20666 WXS_MODEL_GROUP_CAST item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020667 FIXHFAILURE;
20668 break;
20669 case XML_SCHEMA_TYPE_IDC_KEY:
20670 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20671 case XML_SCHEMA_TYPE_IDC_KEYREF:
20672 xmlSchemaResolveIDCKeyReferences(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020673 (xmlSchemaIDCPtr) item, pctxt);
20674 FIXHFAILURE;
20675 break;
20676 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20677 /*
20678 * Handle attribue prohibition which had a
20679 * "ref" attribute.
20680 */
20681 xmlSchemaResolveAttrUseProhibReferences(
20682 WXS_ATTR_PROHIB_CAST item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020683 FIXHFAILURE;
20684 break;
20685 default:
20686 break;
20687 }
20688 }
20689 if (pctxt->nberrors != 0)
20690 goto exit_error;
20691
20692 /*
20693 * Now that all references are resolved we
20694 * can check for circularity of...
20695 * 1. the base axis of type definitions
20696 * 2. nested model group definitions
20697 * 3. nested attribute group definitions
20698 * TODO: check for circual substitution groups.
20699 */
20700 for (i = 0; i < nbItems; i++) {
20701 item = items[i];
20702 /*
20703 * Let's better stop on the first error here.
20704 */
20705 switch (item->type) {
20706 case XML_SCHEMA_TYPE_COMPLEX:
20707 case XML_SCHEMA_TYPE_SIMPLE:
20708 xmlSchemaCheckTypeDefCircular(
20709 (xmlSchemaTypePtr) item, pctxt);
20710 FIXHFAILURE;
20711 if (pctxt->nberrors != 0)
20712 goto exit_error;
20713 break;
20714 case XML_SCHEMA_TYPE_GROUP:
20715 xmlSchemaCheckGroupDefCircular(
20716 (xmlSchemaModelGroupDefPtr) item, pctxt);
20717 FIXHFAILURE;
20718 if (pctxt->nberrors != 0)
20719 goto exit_error;
20720 break;
20721 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20722 xmlSchemaCheckAttrGroupCircular(
20723 (xmlSchemaAttributeGroupPtr) item, pctxt);
20724 FIXHFAILURE;
20725 if (pctxt->nberrors != 0)
20726 goto exit_error;
20727 break;
20728 default:
20729 break;
20730 }
20731 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020732 if (pctxt->nberrors != 0)
20733 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020734 /*
20735 * Model group definition references:
20736 * Such a reference is reflected by a particle at the component
20737 * level. Until now the 'term' of such particles pointed
20738 * to the model group definition; this was done, in order to
20739 * ease circularity checks. Now we need to set the 'term' of
20740 * such particles to the model group of the model group definition.
20741 */
20742 for (i = 0; i < nbItems; i++) {
20743 item = items[i];
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020744 switch (item->type) {
20745 case XML_SCHEMA_TYPE_SEQUENCE:
20746 case XML_SCHEMA_TYPE_CHOICE:
20747 xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
20748 WXS_MODEL_GROUP_CAST item);
20749 break;
20750 default:
20751 break;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020752 }
20753 }
20754 if (pctxt->nberrors != 0)
20755 goto exit_error;
20756 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020757 * Expand attribute group references of attribute group definitions.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020758 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020759 for (i = 0; i < nbItems; i++) {
20760 item = items[i];
20761 switch (item->type) {
20762 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20763 if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
20764 WXS_ATTR_GROUP_HAS_REFS(item))
20765 {
20766 xmlSchemaAttributeGroupExpandRefs(pctxt,
20767 WXS_ATTR_GROUP_CAST item);
20768 FIXHFAILURE;
20769 }
20770 break;
20771 default:
20772 break;
20773 }
20774 }
20775 if (pctxt->nberrors != 0)
20776 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020777 /*
20778 * First compute the variety of simple types. This is needed as
20779 * a seperate step, since otherwise we won't be able to detect
20780 * circular union types in all cases.
20781 */
20782 for (i = 0; i < nbItems; i++) {
20783 item = items[i];
20784 switch (item->type) {
20785 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020786 if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020787 xmlSchemaFixupSimpleTypeStageOne(pctxt,
20788 (xmlSchemaTypePtr) item);
20789 FIXHFAILURE;
20790 }
20791 break;
20792 default:
20793 break;
20794 }
20795 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020796 if (pctxt->nberrors != 0)
20797 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020798 /*
20799 * Detect circular union types. Note that this needs the variety to
20800 * be already computed.
20801 */
20802 for (i = 0; i < nbItems; i++) {
20803 item = items[i];
20804 switch (item->type) {
20805 case XML_SCHEMA_TYPE_SIMPLE:
20806 if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
20807 xmlSchemaCheckUnionTypeDefCircular(pctxt,
20808 (xmlSchemaTypePtr) item);
20809 FIXHFAILURE;
20810 }
20811 break;
20812 default:
20813 break;
20814 }
20815 }
20816 if (pctxt->nberrors != 0)
20817 goto exit_error;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020818
20819 /*
20820 * Do the complete type fixup for simple types.
20821 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020822 for (i = 0; i < nbItems; i++) {
20823 item = items[i];
20824 switch (item->type) {
20825 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020826 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
20827 xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
20828 FIXHFAILURE;
20829 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020830 break;
20831 default:
20832 break;
20833 }
20834 }
20835 if (pctxt->nberrors != 0)
20836 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020837 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020838 * At this point we need all simple types to be builded and checked.
20839 */
20840 /*
20841 * Apply contraints for attribute declarations.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020842 */
20843 for (i = 0; i < nbItems; i++) {
20844 item = items[i];
20845 switch (item->type) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020846 case XML_SCHEMA_TYPE_ATTRIBUTE:
20847 xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
20848 FIXHFAILURE;
20849 break;
20850 default:
20851 break;
20852 }
20853 }
20854 if (pctxt->nberrors != 0)
20855 goto exit_error;
20856 /*
20857 * Apply constraints for attribute uses.
20858 */
20859 for (i = 0; i < nbItems; i++) {
20860 item = items[i];
20861 switch (item->type) {
20862 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20863 if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
20864 xmlSchemaCheckAttrUsePropsCorrect(pctxt,
20865 WXS_ATTR_USE_CAST item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020866 FIXHFAILURE;
20867 }
20868 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020869 default:
20870 break;
20871 }
20872 }
20873 if (pctxt->nberrors != 0)
20874 goto exit_error;
20875
20876 /*
20877 * Apply constraints for attribute group definitions.
20878 */
20879 for (i = 0; i < nbItems; i++) {
20880 item = items[i];
20881 switch (item->type) {
20882 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20883 if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
20884 ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
20885 {
20886 xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
20887 FIXHFAILURE;
20888 }
20889 break;
20890 default:
20891 break;
20892 }
20893 }
20894 if (pctxt->nberrors != 0)
20895 goto exit_error;
20896
20897 /*
20898 * Apply constraints for redefinitions.
20899 */
20900 if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
20901 xmlSchemaCheckSRCRedefineSecond(pctxt);
20902 if (pctxt->nberrors != 0)
20903 goto exit_error;
20904
20905 /*
20906 * Fixup complex types.
20907 */
20908 for (i = 0; i < nbItems; i++) {
20909 item = con->pending->items[i];
20910 switch (item->type) {
20911 case XML_SCHEMA_TYPE_COMPLEX:
20912 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
20913 xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
20914 FIXHFAILURE;
20915 }
20916 break;
20917 default:
20918 break;
20919 }
20920 }
20921 if (pctxt->nberrors != 0)
20922 goto exit_error;
20923
20924 /*
20925 * The list could have changed, since xmlSchemaFixupComplexType()
20926 * will create particles and model groups in some cases.
20927 */
20928 items = (xmlSchemaTreeItemPtr *) con->pending->items;
20929 nbItems = con->pending->nbItems;
20930
20931 /*
20932 * At this point all complex types need to be builded and checked.
20933 */
20934 /*
20935 * Apply some constraints for element declarations.
20936 */
20937 for (i = 0; i < nbItems; i++) {
20938 item = items[i];
20939 switch (item->type) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020940 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020941
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020942 if ((((xmlSchemaElementPtr) item)->flags &
20943 XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0) {
20944 xmlSchemaCheckElementDeclComponent(
20945 (xmlSchemaElementPtr) item, pctxt);
20946 FIXHFAILURE;
20947 }
20948 break;
20949 default:
20950 break;
20951 }
20952 }
20953 if (pctxt->nberrors != 0)
20954 goto exit_error;
20955 /*
20956 * Finally we can build the automaton from the content model of
20957 * complex types.
20958 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020959
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020960 for (i = 0; i < nbItems; i++) {
20961 item = items[i];
20962 switch (item->type) {
20963 case XML_SCHEMA_TYPE_COMPLEX:
20964 xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020965 /* FIXHFAILURE; */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020966 break;
20967 default:
20968 break;
20969 }
20970 }
20971 if (pctxt->nberrors != 0)
20972 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020973 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020974 * URGENT TODO: cos-element-consistent
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020975 */
20976 goto exit;
20977
20978exit_error:
20979 ret = pctxt->err;
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000020980 goto exit;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020981
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020982exit_failure:
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020983 ret = -1;
20984
20985exit:
20986 /*
20987 * Reset the constructor. This is needed for XSI acquisition, since
20988 * those items will be processed over and over again for every XSI
20989 * if not cleared here.
20990 */
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000020991 con->bucket = oldbucket;
20992 con->pending->nbItems = 0;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020993 if (con->substGroups != NULL) {
20994 xmlHashFree(con->substGroups,
20995 (xmlHashDeallocator) xmlSchemaSubstGroupFree);
20996 con->substGroups = NULL;
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000020997 }
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020998 if (con->redefs != NULL) {
20999 xmlSchemaRedefListFree(con->redefs);
21000 con->redefs = NULL;
21001 }
21002 return(ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021003}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021004/**
Daniel Veillard4255d502002-04-16 15:50:10 +000021005 * xmlSchemaParse:
21006 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000021007 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000021008 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000021009 * XML Shema struture which can be used to validate instances.
Daniel Veillard4255d502002-04-16 15:50:10 +000021010 *
21011 * Returns the internal XML Schema structure built from the resource or
21012 * NULL in case of error
21013 */
21014xmlSchemaPtr
21015xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21016{
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021017 xmlSchemaPtr mainSchema = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021018 xmlSchemaBucketPtr bucket = NULL;
21019 int res;
Daniel Veillard4255d502002-04-16 15:50:10 +000021020
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021021 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021022 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021023 * the API; i.e. not automatically by the validated instance document.
21024 */
21025
Daniel Veillard4255d502002-04-16 15:50:10 +000021026 xmlSchemaInitTypes();
21027
Daniel Veillard6045c902002-10-09 21:13:59 +000021028 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000021029 return (NULL);
21030
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021031 /* TODO: Init the context. Is this all we need?*/
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000021032 ctxt->nberrors = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021033 ctxt->err = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000021034 ctxt->counter = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000021035
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021036 /* Create the *main* schema. */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021037 mainSchema = xmlSchemaNewSchema(ctxt);
21038 if (mainSchema == NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021039 goto exit_failure;
Daniel Veillard4255d502002-04-16 15:50:10 +000021040 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021041 * Create the schema constructor.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021042 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021043 if (ctxt->constructor == NULL) {
21044 ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21045 if (ctxt->constructor == NULL)
21046 return(NULL);
21047 /* Take ownership of the constructor to be able to free it. */
21048 ctxt->ownsConstructor = 1;
21049 }
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021050 ctxt->constructor->mainSchema = mainSchema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021051 /*
21052 * Locate and add the schema document.
21053 */
21054 res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21055 ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21056 NULL, NULL, &bucket);
21057 if (res == -1)
21058 goto exit_failure;
21059 if (res != 0)
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000021060 goto exit;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021061
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021062 if (bucket == NULL) {
21063 /* TODO: Error code, actually we failed to *locate* the schema. */
21064 if (ctxt->URL)
21065 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21066 NULL, NULL,
21067 "Failed to locate the main schema resource at '%s'",
21068 ctxt->URL, NULL);
21069 else
21070 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21071 NULL, NULL,
21072 "Failed to locate the main schema resource",
21073 NULL, NULL);
21074 goto exit;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021075 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021076 /* Then do the parsing for good. */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021077 if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021078 goto exit_failure;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021079 if (ctxt->nberrors != 0)
21080 goto exit;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021081
21082 mainSchema->doc = bucket->doc;
21083 mainSchema->preserve = ctxt->preserve;
21084
21085 ctxt->schema = mainSchema;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021086
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021087 if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021088 goto exit_failure;
21089
21090 /*
21091 * TODO: This is not nice, since we cannot distinguish from the
21092 * result if there was an internal error or not.
21093 */
21094exit:
21095 if (ctxt->nberrors != 0) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021096 if (mainSchema) {
21097 xmlSchemaFree(mainSchema);
21098 mainSchema = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021099 }
21100 if (ctxt->constructor) {
21101 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21102 ctxt->constructor = NULL;
21103 ctxt->ownsConstructor = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021104 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021105 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021106 ctxt->schema = NULL;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021107 return(mainSchema);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021108exit_failure:
21109 /*
21110 * Quite verbose, but should catch internal errors, which were
21111 * not communitated.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021112 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021113 if (mainSchema) {
21114 xmlSchemaFree(mainSchema);
21115 mainSchema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021116 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021117 if (ctxt->constructor) {
21118 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21119 ctxt->constructor = NULL;
21120 ctxt->ownsConstructor = 0;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000021121 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021122 PERROR_INT2("xmlSchemaParse",
21123 "An internal error occured");
21124 ctxt->schema = NULL;
21125 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000021126}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021127
Daniel Veillard4255d502002-04-16 15:50:10 +000021128/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000021129 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000021130 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000021131 * @err: the error callback
21132 * @warn: the warning callback
21133 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000021134 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000021135 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000021136 */
21137void
21138xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021139 xmlSchemaValidityErrorFunc err,
21140 xmlSchemaValidityWarningFunc warn, void *ctx)
21141{
Daniel Veillard4255d502002-04-16 15:50:10 +000021142 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021143 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000021144 ctxt->error = err;
21145 ctxt->warning = warn;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021146 ctxt->errCtxt = ctx;
21147 if (ctxt->vctxt != NULL)
21148 xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21149}
21150
21151/**
21152 * xmlSchemaSetParserStructuredErrors:
21153 * @ctxt: a schema parser context
21154 * @serror: the structured error function
21155 * @ctx: the functions context
21156 *
21157 * Set the structured error callback
21158 */
21159void
21160xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21161 xmlStructuredErrorFunc serror,
21162 void *ctx)
21163{
21164 if (ctxt == NULL)
21165 return;
21166 ctxt->serror = serror;
21167 ctxt->errCtxt = ctx;
21168 if (ctxt->vctxt != NULL)
21169 xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000021170}
21171
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021172/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000021173 * xmlSchemaGetParserErrors:
21174 * @ctxt: a XMl-Schema parser context
21175 * @err: the error callback result
21176 * @warn: the warning callback result
21177 * @ctx: contextual data for the callbacks result
21178 *
21179 * Get the callback information used to handle errors for a parser context
21180 *
21181 * Returns -1 in case of failure, 0 otherwise
21182 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021183int
Daniel Veillard259f0df2004-08-18 09:13:18 +000021184xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021185 xmlSchemaValidityErrorFunc * err,
21186 xmlSchemaValidityWarningFunc * warn, void **ctx)
Daniel Veillard259f0df2004-08-18 09:13:18 +000021187{
21188 if (ctxt == NULL)
21189 return(-1);
21190 if (err != NULL)
21191 *err = ctxt->error;
21192 if (warn != NULL)
21193 *warn = ctxt->warning;
21194 if (ctx != NULL)
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021195 *ctx = ctxt->errCtxt;
Daniel Veillard259f0df2004-08-18 09:13:18 +000021196 return(0);
21197}
21198
21199/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021200 * xmlSchemaFacetTypeToString:
21201 * @type: the facet type
21202 *
21203 * Convert the xmlSchemaTypeType to a char string.
21204 *
21205 * Returns the char string representation of the facet type if the
21206 * type is a facet and an "Internal Error" string otherwise.
21207 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021208static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021209xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21210{
21211 switch (type) {
21212 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021213 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021214 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021215 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021216 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021217 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021218 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021219 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021220 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021221 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021222 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021223 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021224 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021225 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021226 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021227 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021228 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021229 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021230 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021231 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021232 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021233 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021234 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021235 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021236 default:
21237 break;
21238 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021239 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021240}
21241
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021242static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000021243xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21244{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021245 /*
21246 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000021247 * from xsd:string.
21248 */
21249 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021250 /*
21251 * Note that we assume a whitespace of preserve for anySimpleType.
21252 */
21253 if ((type->builtInType == XML_SCHEMAS_STRING) ||
21254 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21255 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000021256 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021257 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021258 else {
21259 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021260 * For all ·atomic· datatypes other than string (and types ·derived·
21261 * by ·restriction· from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000021262 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021263 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000021264 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021265 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021266 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021267 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021268 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021269 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021270 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021271 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021272 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021273 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021274 } else if (WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021275 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21276 return (XML_SCHEMA_WHITESPACE_PRESERVE);
21277 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21278 return (XML_SCHEMA_WHITESPACE_REPLACE);
21279 else
21280 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021281 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021282 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021283}
21284
Daniel Veillard4255d502002-04-16 15:50:10 +000021285/************************************************************************
21286 * *
21287 * Simple type validation *
21288 * *
21289 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000021290
Daniel Veillard4255d502002-04-16 15:50:10 +000021291
21292/************************************************************************
21293 * *
21294 * DOM Validation code *
21295 * *
21296 ************************************************************************/
21297
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021298/**
21299 * xmlSchemaAssembleByLocation:
21300 * @pctxt: a schema parser context
21301 * @vctxt: a schema validation context
21302 * @schema: the existing schema
21303 * @node: the node that fired the assembling
21304 * @nsName: the namespace name of the new schema
21305 * @location: the location of the schema
21306 *
21307 * Expands an existing schema by an additional schema.
21308 *
21309 * Returns 0 if the new schema is correct, a positive error code
21310 * number otherwise and -1 in case of an internal or API error.
21311 */
21312static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021313xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021314 xmlSchemaPtr schema,
21315 xmlNodePtr node,
21316 const xmlChar *nsName,
21317 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021318{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021319 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021320 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021321 xmlSchemaBucketPtr bucket = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021322
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021323 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021324 return (-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021325
21326 if (vctxt->pctxt == NULL) {
21327 VERROR_INT("xmlSchemaAssembleByLocation",
21328 "no parser context available");
21329 return(-1);
21330 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021331 pctxt = vctxt->pctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021332 if (pctxt->constructor == NULL) {
21333 PERROR_INT("xmlSchemaAssembleByLocation",
21334 "no constructor");
21335 return(-1);
21336 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021337 /*
21338 * Acquire the schema document.
21339 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021340 location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21341 location, node);
21342 /*
21343 * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21344 * the process will automatically change this to
21345 * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21346 */
21347 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21348 location, NULL, NULL, 0, node, NULL, nsName,
21349 &bucket);
21350 if (ret != 0)
21351 return(ret);
21352 if (bucket == NULL) {
21353 PERROR_INT("xmlSchemaAssembleByLocation",
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021354 "no schema bucket acquired");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021355 return(-1);
21356 }
21357 /*
21358 * The first located schema will be handled as if all other
21359 * schemas imported by XSI were imported by this first schema.
21360 */
21361 if ((bucket != NULL) &&
21362 (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21363 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21364 /*
21365 * TODO: Is this handled like an import? I.e. is it not an error
21366 * if the schema cannot be located?
21367 */
21368 if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21369 return(0);
21370 /*
21371 * We will reuse the parser context for every schema imported
21372 * directly via XSI. So reset the context.
21373 */
21374 pctxt->nberrors = 0;
21375 pctxt->err = 0;
21376 pctxt->doc = bucket->doc;
21377
21378 ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21379 if (ret == -1) {
21380 pctxt->doc = NULL;
21381 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021382 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021383 /* Paranoid error channelling. */
21384 if ((ret == 0) && (pctxt->nberrors != 0))
21385 ret = pctxt->err;
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000021386 if (pctxt->nberrors == 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021387 /*
21388 * Only bother to fixup pending components, if there was
21389 * no error yet.
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021390 * For every XSI acquired schema (and its sub-schemata) we will
21391 * fixup the components.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021392 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021393 xmlSchemaFixupComponents(pctxt, bucket);
Kasimier T. Buchcik215406f2005-12-07 12:14:09 +000021394 ret = pctxt->err;
21395 /*
21396 * Not nice, but we need somehow to channel the schema parser
21397 * error to the validation context.
21398 */
21399 if ((ret != 0) && (vctxt->err == 0))
21400 vctxt->err = ret;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021401 vctxt->nberrors += pctxt->nberrors;
21402 } else {
21403 /* Add to validation error sum. */
21404 vctxt->nberrors += pctxt->nberrors;
21405 }
21406 pctxt->doc = NULL;
21407 return(ret);
21408exit_failure:
21409 pctxt->doc = NULL;
21410 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021411}
21412
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021413static xmlSchemaAttrInfoPtr
21414xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21415 int metaType)
21416{
21417 if (vctxt->nbAttrInfos == 0)
21418 return (NULL);
21419 {
21420 int i;
21421 xmlSchemaAttrInfoPtr iattr;
21422
21423 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21424 iattr = vctxt->attrInfos[i];
21425 if (iattr->metaType == metaType)
21426 return (iattr);
21427 }
21428
21429 }
21430 return (NULL);
21431}
21432
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021433/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021434 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021435 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021436 *
21437 * Expands an existing schema by an additional schema using
21438 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21439 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21440 * must be set to 1.
21441 *
21442 * Returns 0 if the new schema is correct, a positive error code
21443 * number otherwise and -1 in case of an internal or API error.
21444 */
21445static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021446xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021447{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021448 const xmlChar *cur, *end;
21449 const xmlChar *nsname = NULL, *location;
21450 int count = 0;
21451 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021452 xmlSchemaAttrInfoPtr iattr;
21453
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021454 /*
21455 * Parse the value; we will assume an even number of values
21456 * to be given (this is how Xerces and XSV work).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021457 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021458 * URGENT TODO: !! This needs to work for both
21459 * @noNamespaceSchemaLocation AND @schemaLocation on the same
21460 * element !!
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021461 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021462 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21463 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21464 if (iattr == NULL)
Kasimier T. Buchcik81755ea2005-11-23 16:39:27 +000021465 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021466 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21467 if (iattr == NULL)
21468 return (0);
21469 cur = iattr->value;
21470 do {
21471 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021472 /*
21473 * Get the namespace name.
21474 */
21475 while (IS_BLANK_CH(*cur))
21476 cur++;
21477 end = cur;
21478 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21479 end++;
21480 if (end == cur)
21481 break;
21482 count++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021483 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021484 cur = end;
21485 }
21486 /*
21487 * Get the URI.
21488 */
21489 while (IS_BLANK_CH(*cur))
21490 cur++;
21491 end = cur;
21492 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21493 end++;
21494 if (end == cur)
21495 break;
21496 count++;
21497 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021498 cur = end;
21499 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21500 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021501 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021502 VERROR_INT("xmlSchemaAssembleByXSI",
21503 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021504 return (-1);
21505 }
21506 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021507 return (ret);
21508}
21509
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021510static const xmlChar *
21511xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21512 const xmlChar *prefix)
21513{
21514 if (vctxt->sax != NULL) {
21515 int i, j;
21516 xmlSchemaNodeInfoPtr inode;
21517
21518 for (i = vctxt->depth; i >= 0; i--) {
21519 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21520 inode = vctxt->elemInfos[i];
21521 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21522 if (((prefix == NULL) &&
21523 (inode->nsBindings[j] == NULL)) ||
21524 ((prefix != NULL) && xmlStrEqual(prefix,
21525 inode->nsBindings[j]))) {
21526
21527 /*
21528 * Note that the namespace bindings are already
21529 * in a string dict.
21530 */
21531 return (inode->nsBindings[j+1]);
21532 }
21533 }
21534 }
21535 }
21536 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000021537#ifdef LIBXML_WRITER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021538 } else if (vctxt->reader != NULL) {
21539 xmlChar *nsName;
21540
21541 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21542 if (nsName != NULL) {
21543 const xmlChar *ret;
21544
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021545 ret = xmlDictLookup(vctxt->dict, nsName, -1);
21546 xmlFree(nsName);
21547 return (ret);
21548 } else
21549 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000021550#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021551 } else {
21552 xmlNsPtr ns;
21553
21554 if ((vctxt->inode->node == NULL) ||
21555 (vctxt->inode->node->doc == NULL)) {
21556 VERROR_INT("xmlSchemaLookupNamespace",
21557 "no node or node's doc avaliable");
21558 return (NULL);
21559 }
21560 ns = xmlSearchNs(vctxt->inode->node->doc,
21561 vctxt->inode->node, prefix);
21562 if (ns != NULL)
21563 return (ns->href);
21564 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021565 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021566}
21567
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021568/*
21569* This one works on the schema of the validation context.
21570*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021571static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021572xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21573 xmlSchemaPtr schema,
21574 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021575 const xmlChar *value,
21576 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021577 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021578{
21579 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021580
21581 if (vctxt && (vctxt->schema == NULL)) {
21582 VERROR_INT("xmlSchemaValidateNotation",
21583 "a schema is needed on the validation context");
21584 return (-1);
21585 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021586 ret = xmlValidateQName(value, 1);
21587 if (ret != 0)
21588 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021589 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021590 xmlChar *localName = NULL;
21591 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021592
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021593 localName = xmlSplitQName2(value, &prefix);
21594 if (prefix != NULL) {
21595 const xmlChar *nsName = NULL;
21596
21597 if (vctxt != NULL)
21598 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21599 else if (node != NULL) {
21600 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21601 if (ns != NULL)
21602 nsName = ns->href;
21603 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021604 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021605 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021606 return (1);
21607 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021608 if (nsName == NULL) {
21609 xmlFree(prefix);
21610 xmlFree(localName);
21611 return (1);
21612 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021613 if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021614 if (valNeeded && (val != NULL)) {
21615 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
21616 BAD_CAST xmlStrdup(nsName));
21617 if (*val == NULL)
21618 ret = -1;
21619 }
21620 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021621 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021622 xmlFree(prefix);
21623 xmlFree(localName);
21624 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021625 if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021626 if (valNeeded && (val != NULL)) {
21627 (*val) = xmlSchemaNewNOTATIONValue(
21628 BAD_CAST xmlStrdup(value), NULL);
21629 if (*val == NULL)
21630 ret = -1;
21631 }
21632 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021633 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021634 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021635 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021636 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021637}
21638
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000021639static int
21640xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21641 const xmlChar* lname,
21642 const xmlChar* nsname)
21643{
21644 int i;
21645
21646 lname = xmlDictLookup(vctxt->dict, lname, -1);
21647 if (lname == NULL)
21648 return(-1);
21649 if (nsname != NULL) {
21650 nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21651 if (nsname == NULL)
21652 return(-1);
21653 }
21654 for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21655 if ((vctxt->nodeQNames->items [i] == lname) &&
21656 (vctxt->nodeQNames->items[i +1] == nsname))
21657 /* Already there */
21658 return(i);
21659 }
21660 /* Add new entry. */
21661 i = vctxt->nodeQNames->nbItems;
21662 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21663 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21664 return(i);
21665}
21666
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021667/************************************************************************
21668 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021669 * Validation of identity-constraints (IDC) *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021670 * *
21671 ************************************************************************/
21672
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021673/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021674 * xmlSchemaAugmentIDC:
21675 * @idcDef: the IDC definition
21676 *
21677 * Creates an augmented IDC definition item.
21678 *
21679 * Returns the item, or NULL on internal errors.
21680 */
21681static void
21682xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
21683 xmlSchemaValidCtxtPtr vctxt)
21684{
21685 xmlSchemaIDCAugPtr aidc;
21686
21687 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21688 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021689 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021690 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21691 NULL);
21692 return;
21693 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021694 aidc->keyrefDepth = -1;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021695 aidc->def = idcDef;
21696 aidc->next = NULL;
21697 if (vctxt->aidcs == NULL)
21698 vctxt->aidcs = aidc;
21699 else {
21700 aidc->next = vctxt->aidcs;
21701 vctxt->aidcs = aidc;
21702 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021703 /*
21704 * Save if we have keyrefs at all.
21705 */
21706 if ((vctxt->hasKeyrefs == 0) &&
21707 (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
21708 vctxt->hasKeyrefs = 1;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021709}
21710
21711/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021712 * xmlSchemaIDCNewBinding:
21713 * @idcDef: the IDC definition of this binding
21714 *
21715 * Creates a new IDC binding.
21716 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021717 * Returns the new IDC binding, NULL on internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021718 */
21719static xmlSchemaPSVIIDCBindingPtr
21720xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
21721{
21722 xmlSchemaPSVIIDCBindingPtr ret;
21723
21724 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
21725 sizeof(xmlSchemaPSVIIDCBinding));
21726 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021727 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021728 "allocating a PSVI IDC binding item", NULL);
21729 return (NULL);
21730 }
21731 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
21732 ret->definition = idcDef;
21733 return (ret);
21734}
21735
21736/**
21737 * xmlSchemaIDCStoreNodeTableItem:
21738 * @vctxt: the WXS validation context
21739 * @item: the IDC node table item
21740 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021741 * The validation context is used to store IDC node table items.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021742 * They are stored to avoid copying them if IDC node-tables are merged
21743 * with corresponding parent IDC node-tables (bubbling).
21744 *
21745 * Returns 0 if succeeded, -1 on internal errors.
21746 */
21747static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021748xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021749 xmlSchemaPSVIIDCNodePtr item)
21750{
21751 /*
21752 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021753 */
21754 if (vctxt->idcNodes == NULL) {
21755 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021756 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
21757 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021758 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021759 "allocating the IDC node table item list", NULL);
21760 return (-1);
21761 }
21762 vctxt->sizeIdcNodes = 20;
21763 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
21764 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021765 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
21766 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021767 sizeof(xmlSchemaPSVIIDCNodePtr));
21768 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021769 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021770 "re-allocating the IDC node table item list", NULL);
21771 return (-1);
21772 }
21773 }
21774 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021775
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021776 return (0);
21777}
21778
21779/**
21780 * xmlSchemaIDCStoreKey:
21781 * @vctxt: the WXS validation context
21782 * @item: the IDC key
21783 *
21784 * The validation context is used to store an IDC key.
21785 *
21786 * Returns 0 if succeeded, -1 on internal errors.
21787 */
21788static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021789xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021790 xmlSchemaPSVIIDCKeyPtr key)
21791{
21792 /*
21793 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021794 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021795 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021796 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021797 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
21798 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021799 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021800 "allocating the IDC key storage list", NULL);
21801 return (-1);
21802 }
21803 vctxt->sizeIdcKeys = 40;
21804 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
21805 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021806 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
21807 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021808 sizeof(xmlSchemaPSVIIDCKeyPtr));
21809 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021810 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021811 "re-allocating the IDC key storage list", NULL);
21812 return (-1);
21813 }
21814 }
21815 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021816
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021817 return (0);
21818}
21819
21820/**
21821 * xmlSchemaIDCAppendNodeTableItem:
21822 * @bind: the IDC binding
21823 * @ntItem: the node-table item
21824 *
21825 * Appends the IDC node-table item to the binding.
21826 *
21827 * Returns 0 on success and -1 on internal errors.
21828 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021829static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021830xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
21831 xmlSchemaPSVIIDCNodePtr ntItem)
21832{
21833 if (bind->nodeTable == NULL) {
21834 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021835 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021836 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
21837 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021838 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021839 "allocating an array of IDC node-table items", NULL);
21840 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021841 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021842 } else if (bind->sizeNodes <= bind->nbNodes) {
21843 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021844 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
21845 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021846 sizeof(xmlSchemaPSVIIDCNodePtr));
21847 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021848 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021849 "re-allocating an array of IDC node-table items", NULL);
21850 return(-1);
21851 }
21852 }
21853 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021854 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021855}
21856
21857/**
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021858 * xmlSchemaIDCAcquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021859 * @vctxt: the WXS validation context
21860 * @matcher: the IDC matcher
21861 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021862 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021863 * of the given matcher. If none found, a new one is created
21864 * and added to the IDC table.
21865 *
21866 * Returns an IDC binding or NULL on internal errors.
21867 */
21868static xmlSchemaPSVIIDCBindingPtr
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021869xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021870 xmlSchemaIDCMatcherPtr matcher)
21871{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021872 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021873
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021874 ielem = vctxt->elemInfos[matcher->depth];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021875
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021876 if (ielem->idcTable == NULL) {
21877 ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
21878 if (ielem->idcTable == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021879 return (NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021880 return(ielem->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021881 } else {
21882 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021883
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021884 bind = ielem->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021885 do {
21886 if (bind->definition == matcher->aidc->def)
21887 return(bind);
21888 if (bind->next == NULL) {
21889 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
21890 if (bind->next == NULL)
21891 return (NULL);
21892 return(bind->next);
21893 }
21894 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021895 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021896 }
21897 return (NULL);
21898}
21899
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021900static xmlSchemaItemListPtr
21901xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
21902 xmlSchemaIDCMatcherPtr matcher)
21903{
21904 if (matcher->targets == NULL)
21905 matcher->targets = xmlSchemaItemListCreate();
21906 return(matcher->targets);
21907}
21908
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021909/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021910 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021911 * @key: the IDC key
21912 *
21913 * Frees an IDC key together with its compiled value.
21914 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021915static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021916xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
21917{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021918 if (key->val != NULL)
21919 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021920 xmlFree(key);
21921}
21922
21923/**
21924 * xmlSchemaIDCFreeBinding:
21925 *
21926 * Frees an IDC binding. Note that the node table-items
21927 * are not freed.
21928 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021929static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021930xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
21931{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021932 if (bind->nodeTable != NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021933 xmlFree(bind->nodeTable);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021934 if (bind->dupls != NULL)
21935 xmlSchemaItemListFree(bind->dupls);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021936 xmlFree(bind);
21937}
21938
21939/**
21940 * xmlSchemaIDCFreeIDCTable:
21941 * @bind: the first IDC binding in the list
21942 *
21943 * Frees an IDC table, i.e. all the IDC bindings in the list.
21944 */
21945static void
21946xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
21947{
21948 xmlSchemaPSVIIDCBindingPtr prev;
21949
21950 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021951 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021952 bind = bind->next;
21953 xmlSchemaIDCFreeBinding(prev);
21954 }
21955}
21956
21957/**
21958 * xmlSchemaIDCFreeMatcherList:
21959 * @matcher: the first IDC matcher in the list
21960 *
21961 * Frees a list of IDC matchers.
21962 */
21963static void
21964xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
21965{
21966 xmlSchemaIDCMatcherPtr next;
21967
21968 while (matcher != NULL) {
21969 next = matcher->next;
21970 if (matcher->keySeqs != NULL) {
21971 int i;
21972 for (i = 0; i < matcher->sizeKeySeqs; i++)
21973 if (matcher->keySeqs[i] != NULL)
21974 xmlFree(matcher->keySeqs[i]);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021975 xmlFree(matcher->keySeqs);
21976 }
21977 if (matcher->targets != NULL) {
21978 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
21979 int i;
21980 xmlSchemaPSVIIDCNodePtr idcNode;
21981 /*
21982 * Node-table items for keyrefs are not stored globally
21983 * to the validation context, since they are not bubbled.
21984 * We need to free them here.
21985 */
21986 for (i = 0; i < matcher->targets->nbItems; i++) {
21987 idcNode =
21988 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
21989 xmlFree(idcNode->keys);
21990 xmlFree(idcNode);
21991 }
21992 }
21993 xmlSchemaItemListFree(matcher->targets);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021994 }
21995 xmlFree(matcher);
21996 matcher = next;
21997 }
21998}
21999
22000/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022001 * xmlSchemaIDCAddStateObject:
22002 * @vctxt: the WXS validation context
22003 * @matcher: the IDC matcher
22004 * @sel: the XPath information
22005 * @parent: the parent "selector" state object if any
22006 * @type: "selector" or "field"
22007 *
22008 * Creates/reuses and activates state objects for the given
22009 * XPath information; if the XPath expression consists of unions,
22010 * multiple state objects are created for every unioned expression.
22011 *
22012 * Returns 0 on success and -1 on internal errors.
22013 */
22014static int
22015xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22016 xmlSchemaIDCMatcherPtr matcher,
22017 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022018 int type)
22019{
22020 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022021
22022 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022023 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022024 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022025 if (vctxt->xpathStatePool != NULL) {
22026 sto = vctxt->xpathStatePool;
22027 vctxt->xpathStatePool = sto->next;
22028 sto->next = NULL;
22029 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022030 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022031 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022032 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022033 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22034 if (sto == NULL) {
22035 xmlSchemaVErrMemory(NULL,
22036 "allocating an IDC state object", NULL);
22037 return (-1);
22038 }
22039 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22040 }
22041 /*
22042 * Add to global list.
22043 */
22044 if (vctxt->xpathStates != NULL)
22045 sto->next = vctxt->xpathStates;
22046 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022047
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022048 /*
22049 * Free the old xpath validation context.
22050 */
22051 if (sto->xpathCtxt != NULL)
22052 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22053
22054 /*
22055 * Create a new XPath (pattern) validation context.
22056 */
22057 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22058 (xmlPatternPtr) sel->xpathComp);
22059 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022060 VERROR_INT("xmlSchemaIDCAddStateObject",
22061 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022062 return (-1);
22063 }
22064 sto->type = type;
22065 sto->depth = vctxt->depth;
22066 sto->matcher = matcher;
22067 sto->sel = sel;
22068 sto->nbHistory = 0;
22069
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022070#ifdef DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022071 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
22072 sto->sel->xpath);
22073#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022074 return (0);
22075}
22076
22077/**
22078 * xmlSchemaXPathEvaluate:
22079 * @vctxt: the WXS validation context
22080 * @nodeType: the nodeType of the current node
22081 *
22082 * Evaluates all active XPath state objects.
22083 *
22084 * Returns the number of IC "field" state objects which resolved to
22085 * this node, 0 if none resolved and -1 on internal errors.
22086 */
22087static int
22088xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022089 xmlElementType nodeType)
22090{
22091 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022092 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022093
22094 if (vctxt->xpathStates == NULL)
22095 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022096
22097 if (nodeType == XML_ATTRIBUTE_NODE)
22098 depth++;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022099#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022100 {
22101 xmlChar *str = NULL;
22102 xmlGenericError(xmlGenericErrorContext,
22103 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022104 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22105 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022106 FREE_AND_NULL(str)
22107 }
22108#endif
22109 /*
22110 * Process all active XPath state objects.
22111 */
22112 first = vctxt->xpathStates;
22113 sto = first;
22114 while (sto != head) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022115#ifdef DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022116 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022117 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
22118 sto->matcher->aidc->def->name, sto->sel->xpath);
22119 else
22120 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
22121 sto->matcher->aidc->def->name, sto->sel->xpath);
22122#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022123 if (nodeType == XML_ELEMENT_NODE)
22124 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022125 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022126 else
22127 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022128 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022129
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022130 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022131 VERROR_INT("xmlSchemaXPathEvaluate",
22132 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022133 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022134 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022135 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022136 goto next_sto;
22137 /*
22138 * Full match.
22139 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022140#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022141 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022142 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022143#endif
22144 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022145 * Register a match in the state object history.
22146 */
22147 if (sto->history == NULL) {
22148 sto->history = (int *) xmlMalloc(5 * sizeof(int));
22149 if (sto->history == NULL) {
22150 xmlSchemaVErrMemory(NULL,
22151 "allocating the state object history", NULL);
22152 return(-1);
22153 }
22154 sto->sizeHistory = 10;
22155 } else if (sto->sizeHistory <= sto->nbHistory) {
22156 sto->sizeHistory *= 2;
22157 sto->history = (int *) xmlRealloc(sto->history,
22158 sto->sizeHistory * sizeof(int));
22159 if (sto->history == NULL) {
22160 xmlSchemaVErrMemory(NULL,
22161 "re-allocating the state object history", NULL);
22162 return(-1);
22163 }
22164 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022165 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022166
22167#ifdef DEBUG_IDC
22168 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
22169 vctxt->depth);
22170#endif
22171
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022172 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22173 xmlSchemaIDCSelectPtr sel;
22174 /*
22175 * Activate state objects for the IDC fields of
22176 * the IDC selector.
22177 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022178#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022179 xmlGenericError(xmlGenericErrorContext, "IDC: "
22180 "activating field states\n");
22181#endif
22182 sel = sto->matcher->aidc->def->fields;
22183 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022184 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22185 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22186 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022187 sel = sel->next;
22188 }
22189 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22190 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022191 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022192 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022193#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022194 xmlGenericError(xmlGenericErrorContext,
22195 "IDC: key found\n");
22196#endif
22197 /*
22198 * Notify that the character value of this node is
22199 * needed.
22200 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022201 if (resolved == 0) {
22202 if ((vctxt->inode->flags &
22203 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22204 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22205 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022206 resolved++;
22207 }
22208next_sto:
22209 if (sto->next == NULL) {
22210 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022211 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022212 */
22213 head = first;
22214 sto = vctxt->xpathStates;
22215 } else
22216 sto = sto->next;
22217 }
22218 return (resolved);
22219}
22220
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022221static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022222xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022223 xmlChar **buf,
22224 xmlSchemaPSVIIDCKeyPtr *seq,
22225 int count)
22226{
22227 int i, res;
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022228 xmlChar *value = NULL;
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022229
22230 *buf = xmlStrdup(BAD_CAST "[");
22231 for (i = 0; i < count; i++) {
22232 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022233 res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22234 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22235 &value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022236 if (res == 0)
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022237 *buf = xmlStrcat(*buf, BAD_CAST value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022238 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022239 VERROR_INT("xmlSchemaFormatIDCKeySequence",
22240 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022241 *buf = xmlStrcat(*buf, BAD_CAST "???");
22242 }
22243 if (i < count -1)
22244 *buf = xmlStrcat(*buf, BAD_CAST "', ");
22245 else
22246 *buf = xmlStrcat(*buf, BAD_CAST "'");
22247 if (value != NULL) {
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022248 xmlFree(value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022249 value = NULL;
22250 }
22251 }
22252 *buf = xmlStrcat(*buf, BAD_CAST "]");
22253
22254 return (BAD_CAST *buf);
22255}
22256
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022257/**
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000022258 * xmlSchemaXPathPop:
22259 * @vctxt: the WXS validation context
22260 *
22261 * Pops all XPath states.
22262 *
22263 * Returns 0 on success and -1 on internal errors.
22264 */
22265static int
22266xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22267{
22268 xmlSchemaIDCStateObjPtr sto;
22269 int res;
22270
22271 if (vctxt->xpathStates == NULL)
22272 return(0);
22273 sto = vctxt->xpathStates;
22274 do {
22275 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22276 if (res == -1)
22277 return (-1);
22278 sto = sto->next;
22279 } while (sto != NULL);
22280 return(0);
22281}
22282
22283/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022284 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022285 * @vctxt: the WXS validation context
22286 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022287 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022288 *
22289 * Processes and pops the history items of the IDC state objects.
22290 * IDC key-sequences are validated/created on IDC bindings.
22291 *
22292 * Returns 0 on success and -1 on internal errors.
22293 */
22294static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022295xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022296 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022297{
22298 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022299 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022300 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022301 xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022302
22303 if (vctxt->xpathStates == NULL)
22304 return (0);
22305 sto = vctxt->xpathStates;
22306
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022307#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022308 {
22309 xmlChar *str = NULL;
22310 xmlGenericError(xmlGenericErrorContext,
22311 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022312 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22313 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022314 FREE_AND_NULL(str)
22315 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022316#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022317 /*
22318 * Evaluate the state objects.
22319 */
22320 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000022321 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22322 if (res == -1) {
22323 VERROR_INT("xmlSchemaXPathProcessHistory",
22324 "calling xmlStreamPop()");
22325 return (-1);
22326 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022327#ifdef DEBUG_IDC
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022328 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
22329 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022330#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022331 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022332 goto deregister_check;
22333
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022334 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022335
22336 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022337 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022338 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022339 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022340 sto = sto->next;
22341 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022342 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022343 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022344 /*
22345 * NOTE: According to
22346 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22347 * ... the simple-content of complex types is also allowed.
22348 */
22349
22350 if (WXS_IS_COMPLEX(type)) {
22351 if (WXS_HAS_SIMPLE_CONTENT(type)) {
22352 /*
22353 * Sanity check for complex types with simple content.
22354 */
22355 simpleType = type->contentTypeDef;
22356 if (simpleType == NULL) {
22357 VERROR_INT("xmlSchemaXPathProcessHistory",
22358 "field resolves to a CT with simple content "
22359 "but the CT is missing the ST definition");
22360 return (-1);
22361 }
22362 } else
22363 simpleType = NULL;
22364 } else
22365 simpleType = type;
22366 if (simpleType == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022367 xmlChar *str = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022368
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022369 /*
22370 * Not qualified if the field resolves to a node of non
22371 * simple type.
22372 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022373 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022374 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022375 WXS_BASIC_CAST sto->matcher->aidc->def,
22376 "The XPath '%s' of a field of %s does evaluate to a node of "
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022377 "non-simple type",
22378 sto->sel->xpath,
22379 xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22380 FREE_AND_NULL(str);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022381 sto->nbHistory--;
22382 goto deregister_check;
22383 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022384
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022385 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022386 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022387 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022388 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022389 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022390 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022391 WXS_BASIC_CAST sto->matcher->aidc->def,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000022392 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022393 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022394 sto->nbHistory--;
22395 goto deregister_check;
22396 } else {
22397 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22398 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022399 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022400
22401 /*
22402 * The key will be anchored on the matcher's list of
22403 * key-sequences. The position in this list is determined
22404 * by the target node's depth relative to the matcher's
22405 * depth of creation (i.e. the depth of the scope element).
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022406 *
22407 * Element Depth Pos List-entries
22408 * <scope> 0 NULL
22409 * <bar> 1 NULL
22410 * <target/> 2 2 target
22411 * <bar>
22412 * </scope>
22413 *
22414 * The size of the list is only dependant on the depth of
22415 * the tree.
22416 * An entry will be NULLed in selector_leave, i.e. when
22417 * we hit the target's
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022418 */
22419 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022420 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022421
22422 /*
22423 * Create/grow the array of key-sequences.
22424 */
22425 if (matcher->keySeqs == NULL) {
22426 if (pos > 9)
22427 matcher->sizeKeySeqs = pos * 2;
22428 else
22429 matcher->sizeKeySeqs = 10;
22430 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22431 xmlMalloc(matcher->sizeKeySeqs *
22432 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22433 if (matcher->keySeqs == NULL) {
22434 xmlSchemaVErrMemory(NULL,
22435 "allocating an array of key-sequences",
22436 NULL);
22437 return(-1);
22438 }
22439 memset(matcher->keySeqs, 0,
22440 matcher->sizeKeySeqs *
22441 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22442 } else if (pos >= matcher->sizeKeySeqs) {
22443 int i = matcher->sizeKeySeqs;
22444
22445 matcher->sizeKeySeqs *= 2;
22446 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22447 xmlRealloc(matcher->keySeqs,
22448 matcher->sizeKeySeqs *
22449 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022450 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022451 xmlSchemaVErrMemory(NULL,
22452 "reallocating an array of key-sequences",
22453 NULL);
22454 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022455 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022456 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022457 * The array needs to be NULLed.
22458 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022459 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022460 for (; i < matcher->sizeKeySeqs; i++)
22461 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022462 }
22463
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022464 /*
22465 * Get/create the key-sequence.
22466 */
22467 keySeq = matcher->keySeqs[pos];
22468 if (keySeq == NULL) {
22469 goto create_sequence;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022470 } else if (keySeq[idx] != NULL) {
22471 xmlChar *str = NULL;
22472 /*
22473 * cvc-identity-constraint:
22474 * 3 For each node in the ·target node set· all
22475 * of the {fields}, with that node as the context
22476 * node, evaluate to either an empty node-set or
22477 * a node-set with exactly one member, which must
22478 * have a simple type.
22479 *
22480 * The key was already set; report an error.
22481 */
22482 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22483 XML_SCHEMAV_CVC_IDC, NULL,
22484 WXS_BASIC_CAST matcher->aidc->def,
22485 "The XPath '%s' of a field of %s evaluates to a "
22486 "node-set with more than one member",
22487 sto->sel->xpath,
22488 xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22489 FREE_AND_NULL(str);
22490 sto->nbHistory--;
22491 goto deregister_check;
22492 } else
22493 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022494
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022495create_sequence:
22496 /*
22497 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022498 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022499 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22500 matcher->aidc->def->nbFields *
22501 sizeof(xmlSchemaPSVIIDCKeyPtr));
22502 if (keySeq == NULL) {
22503 xmlSchemaVErrMemory(NULL,
22504 "allocating an IDC key-sequence", NULL);
22505 return(-1);
22506 }
22507 memset(keySeq, 0, matcher->aidc->def->nbFields *
22508 sizeof(xmlSchemaPSVIIDCKeyPtr));
22509 matcher->keySeqs[pos] = keySeq;
22510create_key:
22511 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022512 * Create a key once per node only.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022513 */
22514 if (key == NULL) {
22515 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22516 sizeof(xmlSchemaPSVIIDCKey));
22517 if (key == NULL) {
22518 xmlSchemaVErrMemory(NULL,
22519 "allocating a IDC key", NULL);
22520 xmlFree(keySeq);
22521 matcher->keySeqs[pos] = NULL;
22522 return(-1);
22523 }
22524 /*
22525 * Consume the compiled value.
22526 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022527 key->type = simpleType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022528 key->val = vctxt->inode->val;
22529 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022530 /*
22531 * Store the key in a global list.
22532 */
22533 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22534 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022535 return (-1);
22536 }
22537 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022538 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022539 }
22540 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022541
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022542 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022543 /* xmlSchemaPSVIIDCBindingPtr bind; */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022544 xmlSchemaPSVIIDCNodePtr ntItem;
22545 xmlSchemaIDCMatcherPtr matcher;
22546 xmlSchemaIDCPtr idc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022547 xmlSchemaItemListPtr targets;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022548 int pos, i, j, nbKeys;
22549 /*
22550 * Here we have the following scenario:
22551 * An IDC 'selector' state object resolved to a target node,
22552 * during the time this target node was in the
22553 * ancestor-or-self axis, the 'field' state object(s) looked
22554 * out for matching nodes to create a key-sequence for this
22555 * target node. Now we are back to this target node and need
22556 * to put the key-sequence, together with the target node
22557 * itself, into the node-table of the corresponding IDC
22558 * binding.
22559 */
22560 matcher = sto->matcher;
22561 idc = matcher->aidc->def;
22562 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022563 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022564 /*
22565 * Check if the matcher has any key-sequences at all, plus
22566 * if it has a key-sequence for the current target node.
22567 */
22568 if ((matcher->keySeqs == NULL) ||
22569 (matcher->sizeKeySeqs <= pos)) {
22570 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22571 goto selector_key_error;
22572 else
22573 goto selector_leave;
22574 }
22575
22576 keySeq = &(matcher->keySeqs[pos]);
22577 if (*keySeq == NULL) {
22578 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22579 goto selector_key_error;
22580 else
22581 goto selector_leave;
22582 }
22583
22584 for (i = 0; i < nbKeys; i++) {
22585 if ((*keySeq)[i] == NULL) {
22586 /*
22587 * Not qualified, if not all fields did resolve.
22588 */
22589 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22590 /*
22591 * All fields of a "key" IDC must resolve.
22592 */
22593 goto selector_key_error;
22594 }
22595 goto selector_leave;
22596 }
22597 }
22598 /*
22599 * All fields did resolve.
22600 */
22601
22602 /*
22603 * 4.1 If the {identity-constraint category} is unique(/key),
22604 * then no two members of the ·qualified node set· have
22605 * ·key-sequences· whose members are pairwise equal, as
22606 * defined by Equal in [XML Schemas: Datatypes].
22607 *
22608 * Get the IDC binding from the matcher and check for
22609 * duplicate key-sequences.
22610 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022611#if 0
22612 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22613#endif
22614 targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022615 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022616 (targets->nbItems != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022617 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022618
22619 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022620 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022621 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022622 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022623 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022624 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022625 bkeySeq =
22626 ((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022627 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022628 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022629 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022630 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022631 if (res == -1) {
22632 return (-1);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022633 } else if (res == 0) {
22634 /*
22635 * One of the keys differs, so the key-sequence
22636 * won't be equal; get out.
22637 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022638 break;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022639 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022640 }
22641 if (res == 1) {
22642 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022643 * Duplicate key-sequence found.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022644 */
22645 break;
22646 }
22647 i++;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022648 } while (i < targets->nbItems);
22649 if (i != targets->nbItems) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022650 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022651 /*
22652 * TODO: Try to report the key-sequence.
22653 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022654 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022655 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022656 WXS_BASIC_CAST idc,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022657 "Duplicate key-sequence %s in %s",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022658 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022659 (*keySeq), nbKeys),
22660 xmlSchemaGetIDCDesignation(&strB, idc));
22661 FREE_AND_NULL(str);
22662 FREE_AND_NULL(strB);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022663 goto selector_leave;
22664 }
22665 }
22666 /*
22667 * Add a node-table item to the IDC binding.
22668 */
22669 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
22670 sizeof(xmlSchemaPSVIIDCNode));
22671 if (ntItem == NULL) {
22672 xmlSchemaVErrMemory(NULL,
22673 "allocating an IDC node-table item", NULL);
22674 xmlFree(*keySeq);
22675 *keySeq = NULL;
22676 return(-1);
22677 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022678 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022679
22680 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022681 * Store the node-table item in a global list.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022682 */
22683 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
22684 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
22685 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022686 xmlFree(*keySeq);
22687 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022688 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022689 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022690 ntItem->nodeQNameID = -1;
22691 } else {
22692 /*
22693 * Save a cached QName for this node on the IDC node, to be
22694 * able to report it, even if the node is not saved.
22695 */
22696 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
22697 vctxt->inode->localName, vctxt->inode->nsName);
22698 if (ntItem->nodeQNameID == -1) {
22699 xmlFree(ntItem);
22700 xmlFree(*keySeq);
22701 *keySeq = NULL;
22702 return (-1);
22703 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022704 }
22705 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022706 * Init the node-table item: Save the node, position and
22707 * consume the key-sequence.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022708 */
22709 ntItem->node = vctxt->node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022710 ntItem->nodeLine = vctxt->inode->nodeLine;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022711 ntItem->keys = *keySeq;
22712 *keySeq = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022713#if 0
22714 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
22715#endif
22716 if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022717 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
22718 /*
22719 * Free the item, since keyref items won't be
22720 * put on a global list.
22721 */
22722 xmlFree(ntItem->keys);
22723 xmlFree(ntItem);
22724 }
22725 return (-1);
22726 }
22727
22728 goto selector_leave;
22729selector_key_error:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022730 {
22731 xmlChar *str = NULL;
22732 /*
22733 * 4.2.1 (KEY) The ·target node set· and the
22734 * ·qualified node set· are equal, that is, every
22735 * member of the ·target node set· is also a member
22736 * of the ·qualified node set· and vice versa.
22737 */
22738 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22739 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022740 WXS_BASIC_CAST idc,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022741 "Not all fields of %s evaluate to a node",
22742 xmlSchemaGetIDCDesignation(&str, idc), NULL);
22743 FREE_AND_NULL(str);
22744 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022745selector_leave:
22746 /*
22747 * Free the key-sequence if not added to the IDC table.
22748 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022749 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022750 xmlFree(*keySeq);
22751 *keySeq = NULL;
22752 }
22753 } /* if selector */
22754
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022755 sto->nbHistory--;
22756
22757deregister_check:
22758 /*
22759 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022760 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022761 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022762#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022763 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
22764 sto->sel->xpath);
22765#endif
22766 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022767 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022768 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022769 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022770 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022771 nextsto = sto->next;
22772 /*
22773 * Unlink from the list of active XPath state objects.
22774 */
22775 vctxt->xpathStates = sto->next;
22776 sto->next = vctxt->xpathStatePool;
22777 /*
22778 * Link it to the pool of reusable state objects.
22779 */
22780 vctxt->xpathStatePool = sto;
22781 sto = nextsto;
22782 } else
22783 sto = sto->next;
22784 } /* while (sto != NULL) */
22785 return (0);
22786}
22787
22788/**
22789 * xmlSchemaIDCRegisterMatchers:
22790 * @vctxt: the WXS validation context
22791 * @elemDecl: the element declaration
22792 *
22793 * Creates helper objects to evaluate IDC selectors/fields
22794 * successively.
22795 *
22796 * Returns 0 if OK and -1 on internal errors.
22797 */
22798static int
22799xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
22800 xmlSchemaElementPtr elemDecl)
22801{
22802 xmlSchemaIDCMatcherPtr matcher, last = NULL;
22803 xmlSchemaIDCPtr idc, refIdc;
22804 xmlSchemaIDCAugPtr aidc;
22805
22806 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
22807 if (idc == NULL)
22808 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022809
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022810#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022811 {
22812 xmlChar *str = NULL;
22813 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022814 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022815 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22816 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022817 FREE_AND_NULL(str)
22818 }
22819#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022820 if (vctxt->inode->idcMatchers != NULL) {
22821 VERROR_INT("xmlSchemaIDCRegisterMatchers",
22822 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022823 return (-1);
22824 }
22825 do {
22826 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
22827 /*
22828 * Since IDCs bubbles are expensive we need to know the
22829 * depth at which the bubbles should stop; this will be
22830 * the depth of the top-most keyref IDC. If no keyref
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022831 * references a key/unique IDC, the keyrefDepth will
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022832 * be -1, indicating that no bubbles are needed.
22833 */
22834 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
22835 if (refIdc != NULL) {
22836 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022837 * Remember that we have keyrefs on this node.
22838 */
22839 vctxt->inode->hasKeyrefs = 1;
22840 /*
22841 * Lookup the referenced augmented IDC info.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022842 */
22843 aidc = vctxt->aidcs;
22844 while (aidc != NULL) {
22845 if (aidc->def == refIdc)
22846 break;
22847 aidc = aidc->next;
22848 }
22849 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022850 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022851 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022852 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022853 return (-1);
22854 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022855 if ((aidc->keyrefDepth == -1) ||
22856 (vctxt->depth < aidc->keyrefDepth))
22857 aidc->keyrefDepth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022858 }
22859 }
22860 /*
22861 * Lookup the augmented IDC item for the IDC definition.
22862 */
22863 aidc = vctxt->aidcs;
22864 while (aidc != NULL) {
22865 if (aidc->def == idc)
22866 break;
22867 aidc = aidc->next;
22868 }
22869 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022870 VERROR_INT("xmlSchemaIDCRegisterMatchers",
22871 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022872 return (-1);
22873 }
22874 /*
22875 * Create an IDC matcher for every IDC definition.
22876 */
22877 matcher = (xmlSchemaIDCMatcherPtr)
22878 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
22879 if (matcher == NULL) {
22880 xmlSchemaVErrMemory(vctxt,
22881 "allocating an IDC matcher", NULL);
22882 return (-1);
22883 }
22884 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
22885 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022886 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022887 else
22888 last->next = matcher;
22889 last = matcher;
22890
22891 matcher->type = IDC_MATCHER;
22892 matcher->depth = vctxt->depth;
22893 matcher->aidc = aidc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022894 matcher->idcType = aidc->def->type;
22895#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022896 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
22897#endif
22898 /*
22899 * Init the automaton state object.
22900 */
22901 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022902 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022903 return (-1);
22904
22905 idc = idc->next;
22906 } while (idc != NULL);
22907 return (0);
22908}
22909
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022910static int
22911xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
22912 xmlSchemaNodeInfoPtr ielem)
22913{
22914 xmlSchemaPSVIIDCBindingPtr bind;
22915 int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
22916 xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
22917 xmlSchemaPSVIIDCNodePtr *targets, *dupls;
22918
22919 xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
22920 /* vctxt->createIDCNodeTables */
22921 while (matcher != NULL) {
22922 /*
22923 * Skip keyref IDCs and empty IDC target-lists.
22924 */
22925 if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
22926 WXS_ILIST_IS_EMPTY(matcher->targets))
22927 {
22928 matcher = matcher->next;
22929 continue;
22930 }
22931 /*
22932 * If we _want_ the IDC node-table to be created in any case
22933 * then do so. Otherwise create them only if keyrefs need them.
22934 */
22935 if ((! vctxt->createIDCNodeTables) &&
22936 ((matcher->aidc->keyrefDepth == -1) ||
22937 (matcher->aidc->keyrefDepth > vctxt->depth)))
22938 {
22939 matcher = matcher->next;
22940 continue;
22941 }
22942 /*
22943 * Get/create the IDC binding on this element for the IDC definition.
22944 */
22945 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22946
22947 if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
22948 dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
22949 nbDupls = bind->dupls->nbItems;
22950 } else {
22951 dupls = NULL;
22952 nbDupls = 0;
22953 }
22954 if (bind->nodeTable != NULL) {
22955 nbNodeTable = bind->nbNodes;
22956 } else {
22957 nbNodeTable = 0;
22958 }
22959
22960 if ((nbNodeTable == 0) && (nbDupls == 0)) {
22961 /*
22962 * Transfer all IDC target-nodes to the IDC node-table.
22963 */
22964 bind->nodeTable =
22965 (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
22966 bind->sizeNodes = matcher->targets->sizeItems;
22967 bind->nbNodes = matcher->targets->nbItems;
22968
22969 matcher->targets->items = NULL;
22970 matcher->targets->sizeItems = 0;
22971 matcher->targets->nbItems = 0;
22972 } else {
22973 /*
22974 * Compare the key-sequences and add to the IDC node-table.
22975 */
22976 nbTargets = matcher->targets->nbItems;
22977 targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
22978 nbFields = matcher->aidc->def->nbFields;
22979 i = 0;
22980 do {
22981 keys = targets[i]->keys;
22982 if (nbDupls) {
22983 /*
22984 * Search in already found duplicates first.
22985 */
22986 j = 0;
22987 do {
22988 if (nbFields == 1) {
22989 res = xmlSchemaAreValuesEqual(keys[0]->val,
22990 dupls[j]->keys[0]->val);
22991 if (res == -1)
22992 goto internal_error;
22993 if (res == 1) {
22994 /*
22995 * Equal key-sequence.
22996 */
22997 goto next_target;
22998 }
22999 } else {
23000 res = 0;
23001 ntkeys = dupls[j]->keys;
23002 for (k = 0; k < nbFields; k++) {
23003 res = xmlSchemaAreValuesEqual(keys[k]->val,
23004 ntkeys[k]->val);
23005 if (res == -1)
23006 goto internal_error;
23007 if (res == 0) {
23008 /*
23009 * One of the keys differs.
23010 */
23011 break;
23012 }
23013 }
23014 if (res == 1) {
23015 /*
23016 * Equal key-sequence found.
23017 */
23018 goto next_target;
23019 }
23020 }
23021 j++;
23022 } while (j < nbDupls);
23023 }
23024 if (nbNodeTable) {
23025 j = 0;
23026 do {
23027 if (nbFields == 1) {
23028 res = xmlSchemaAreValuesEqual(keys[0]->val,
23029 bind->nodeTable[j]->keys[0]->val);
23030 if (res == -1)
23031 goto internal_error;
23032 if (res == 0) {
23033 /*
23034 * The key-sequence differs.
23035 */
23036 goto next_node_table_entry;
23037 }
23038 } else {
23039 res = 0;
23040 ntkeys = bind->nodeTable[j]->keys;
23041 for (k = 0; k < nbFields; k++) {
23042 res = xmlSchemaAreValuesEqual(keys[k]->val,
23043 ntkeys[k]->val);
23044 if (res == -1)
23045 goto internal_error;
23046 if (res == 0) {
23047 /*
23048 * One of the keys differs.
23049 */
23050 goto next_node_table_entry;
23051 }
23052 }
23053 }
23054 /*
23055 * Add the duplicate to the list of duplicates.
23056 */
23057 if (bind->dupls == NULL) {
23058 bind->dupls = xmlSchemaItemListCreate();
23059 if (bind->dupls == NULL)
23060 goto internal_error;
23061 }
23062 if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23063 goto internal_error;
23064 /*
23065 * Remove the duplicate entry from the IDC node-table.
23066 */
23067 bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23068 bind->nbNodes--;
23069
23070 goto next_target;
23071
23072next_node_table_entry:
23073 j++;
23074 } while (j < nbNodeTable);
23075 }
23076 /*
23077 * If everything is fine, then add the IDC target-node to
23078 * the IDC node-table.
23079 */
23080 if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23081 goto internal_error;
23082
23083next_target:
23084 i++;
23085 } while (i < nbTargets);
23086 }
23087 matcher = matcher->next;
23088 }
23089 return(0);
23090
23091internal_error:
23092 return(-1);
23093}
23094
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023095/**
23096 * xmlSchemaBubbleIDCNodeTables:
23097 * @depth: the current tree depth
23098 *
23099 * Merges IDC bindings of an element at @depth into the corresponding IDC
23100 * bindings of its parent element. If a duplicate note-table entry is found,
23101 * both, the parent node-table entry and child entry are discarded from the
23102 * node-table of the parent.
23103 *
23104 * Returns 0 if OK and -1 on internal errors.
23105 */
23106static int
23107xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23108{
23109 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023110 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23111 xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023112 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023113 int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023114
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023115 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023116 if (bind == NULL) {
23117 /* Fine, no table, no bubbles. */
23118 return (0);
23119 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000023120
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023121 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23122 /*
23123 * Walk all bindings; create new or add to existing bindings.
23124 * Remove duplicate key-sequences.
23125 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023126 while (bind != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023127
23128 if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23129 goto next_binding;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023130 /*
23131 * Check if the key/unique IDC table needs to be bubbled.
23132 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023133 if (! vctxt->createIDCNodeTables) {
23134 aidc = vctxt->aidcs;
23135 do {
23136 if (aidc->def == bind->definition) {
23137 if ((aidc->keyrefDepth == -1) ||
23138 (aidc->keyrefDepth >= vctxt->depth)) {
23139 goto next_binding;
23140 }
23141 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023142 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023143 aidc = aidc->next;
23144 } while (aidc != NULL);
23145 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023146
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023147 if (parTable != NULL)
23148 parBind = *parTable;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023149 /*
23150 * Search a matching parent binding for the
23151 * IDC definition.
23152 */
23153 while (parBind != NULL) {
23154 if (parBind->definition == bind->definition)
23155 break;
23156 parBind = parBind->next;
23157 }
23158
23159 if (parBind != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023160 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023161 * Compare every node-table entry of the child node,
23162 * i.e. the key-sequence within, ...
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023163 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023164 oldNum = parBind->nbNodes; /* Skip newly added items. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023165
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023166 if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23167 oldDupls = parBind->dupls->nbItems;
23168 dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23169 } else {
23170 dupls = NULL;
23171 oldDupls = 0;
23172 }
23173
23174 parNodes = parBind->nodeTable;
23175 nbFields = bind->definition->nbFields;
23176
23177 for (i = 0; i < bind->nbNodes; i++) {
23178 node = bind->nodeTable[i];
23179 if (node == NULL)
23180 continue;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023181 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023182 * ...with every key-sequence of the parent node, already
23183 * evaluated to be a duplicate key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023184 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023185 if (oldDupls) {
23186 j = 0;
23187 while (j < oldDupls) {
23188 if (nbFields == 1) {
23189 ret = xmlSchemaAreValuesEqual(
23190 node->keys[0]->val,
23191 dupls[j]->keys[0]->val);
23192 if (ret == -1)
23193 goto internal_error;
23194 if (ret == 0) {
23195 j++;
23196 continue;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023197 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023198 } else {
23199 parNode = dupls[j];
23200 for (k = 0; k < nbFields; k++) {
23201 ret = xmlSchemaAreValuesEqual(
23202 node->keys[k]->val,
23203 parNode->keys[k]->val);
23204 if (ret == -1)
23205 goto internal_error;
23206 if (ret == 0)
23207 break;
23208 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023209 }
23210 if (ret == 1)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023211 /* Duplicate found. */
23212 break;
23213 j++;
23214 }
23215 if (j != oldDupls) {
23216 /* Duplicate found. Skip this entry. */
23217 continue;
23218 }
23219 }
23220 /*
23221 * ... and with every key-sequence of the parent node.
23222 */
23223 if (oldNum) {
23224 j = 0;
23225 while (j < oldNum) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +000023226 parNode = parNodes[j];
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023227 if (nbFields == 1) {
23228 ret = xmlSchemaAreValuesEqual(
23229 node->keys[0]->val,
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +000023230 parNode->keys[0]->val);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023231 if (ret == -1)
23232 goto internal_error;
23233 if (ret == 0) {
23234 j++;
23235 continue;
23236 }
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +000023237 } else {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023238 for (k = 0; k < nbFields; k++) {
23239 ret = xmlSchemaAreValuesEqual(
23240 node->keys[k]->val,
23241 parNode->keys[k]->val);
23242 if (ret == -1)
23243 goto internal_error;
23244 if (ret == 0)
23245 break;
23246 }
23247 }
23248 if (ret == 1)
23249 /* Duplicate found. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023250 break;
23251 j++;
23252 }
23253 if (j != oldNum) {
23254 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023255 * Handle duplicates. Move the duplicate in
23256 * the parent's node-table to the list of
23257 * duplicates.
23258 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023259 oldNum--;
23260 parBind->nbNodes--;
23261 /*
23262 * Move last old item to pos of duplicate.
23263 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023264 parNodes[j] = parNodes[oldNum];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023265
23266 if (parBind->nbNodes != oldNum) {
23267 /*
23268 * If new items exist, move last new item to
23269 * last of old items.
23270 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023271 parNodes[oldNum] =
23272 parNodes[parBind->nbNodes];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023273 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023274 if (parBind->dupls == NULL) {
23275 parBind->dupls = xmlSchemaItemListCreate();
23276 if (parBind->dupls == NULL)
23277 goto internal_error;
23278 }
23279 xmlSchemaItemListAdd(parBind->dupls, parNode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023280 } else {
23281 /*
23282 * Add the node-table entry (node and key-sequence) of
23283 * the child node to the node table of the parent node.
23284 */
23285 if (parBind->nodeTable == NULL) {
23286 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000023287 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023288 if (parBind->nodeTable == NULL) {
23289 xmlSchemaVErrMemory(NULL,
23290 "allocating IDC list of node-table items", NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023291 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023292 }
23293 parBind->sizeNodes = 1;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023294 } else if (parBind->nbNodes >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000023295 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023296 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23297 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23298 sizeof(xmlSchemaPSVIIDCNodePtr));
23299 if (parBind->nodeTable == NULL) {
23300 xmlSchemaVErrMemory(NULL,
23301 "re-allocating IDC list of node-table items", NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023302 goto internal_error;
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000023303 }
23304 }
23305 parNodes = parBind->nodeTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023306 /*
23307 * Append the new node-table entry to the 'new node-table
23308 * entries' section.
23309 */
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000023310 parNodes[parBind->nbNodes++] = node;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023311 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023312
23313 }
23314
23315 }
23316 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023317 /*
23318 * No binding for the IDC was found: create a new one and
23319 * copy all node-tables.
23320 */
23321 parBind = xmlSchemaIDCNewBinding(bind->definition);
23322 if (parBind == NULL)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023323 goto internal_error;
23324
23325 /*
23326 * TODO: Hmm, how to optimize the initial number of
23327 * allocated entries?
23328 */
23329 if (bind->nbNodes != 0) {
23330 /*
23331 * Add all IDC node-table entries.
23332 */
23333 if (! vctxt->psviExposeIDCNodeTables) {
23334 /*
23335 * Just move the entries.
23336 * NOTE: this is quite save here, since
23337 * all the keyref lookups have already been
23338 * performed.
23339 */
23340 parBind->nodeTable = bind->nodeTable;
23341 bind->nodeTable = NULL;
23342 parBind->sizeNodes = bind->sizeNodes;
23343 bind->sizeNodes = 0;
23344 parBind->nbNodes = bind->nbNodes;
23345 bind->nbNodes = 0;
23346 } else {
23347 /*
23348 * Copy the entries.
23349 */
23350 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23351 xmlMalloc(bind->nbNodes *
23352 sizeof(xmlSchemaPSVIIDCNodePtr));
23353 if (parBind->nodeTable == NULL) {
23354 xmlSchemaVErrMemory(NULL,
23355 "allocating an array of IDC node-table "
23356 "items", NULL);
23357 xmlSchemaIDCFreeBinding(parBind);
23358 goto internal_error;
23359 }
23360 parBind->sizeNodes = bind->nbNodes;
23361 parBind->nbNodes = bind->nbNodes;
23362 memcpy(parBind->nodeTable, bind->nodeTable,
23363 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23364 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023365 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023366 if (bind->dupls) {
23367 /*
23368 * Move the duplicates.
23369 */
23370 if (parBind->dupls != NULL)
23371 xmlSchemaItemListFree(parBind->dupls);
23372 parBind->dupls = bind->dupls;
23373 bind->dupls = NULL;
23374 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023375 if (*parTable == NULL)
23376 *parTable = parBind;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023377 else {
23378 parBind->next = *parTable;
23379 *parTable = parBind;
23380 }
23381 }
23382
23383next_binding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023384 bind = bind->next;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023385 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023386 return (0);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023387
23388internal_error:
23389 return(-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023390}
23391
23392/**
23393 * xmlSchemaCheckCVCIDCKeyRef:
23394 * @vctxt: the WXS validation context
23395 * @elemDecl: the element declaration
23396 *
23397 * Check the cvc-idc-keyref constraints.
23398 */
23399static int
23400xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23401{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023402 xmlSchemaIDCMatcherPtr matcher;
23403 xmlSchemaPSVIIDCBindingPtr bind;
23404
23405 matcher = vctxt->inode->idcMatchers;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023406 /*
23407 * Find a keyref.
23408 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023409 while (matcher != NULL) {
23410 if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23411 matcher->targets &&
23412 matcher->targets->nbItems)
23413 {
23414 int i, j, k, res, nbFields, hasDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023415 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023416 xmlSchemaPSVIIDCNodePtr refNode = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023417
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023418 nbFields = matcher->aidc->def->nbFields;
23419
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023420 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023421 * Find the IDC node-table for the referenced IDC key/unique.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023422 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023423 bind = vctxt->inode->idcTable;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023424 while (bind != NULL) {
23425 if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023426 bind->definition)
23427 break;
23428 bind = bind->next;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023429 }
23430 hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023431 /*
23432 * Search for a matching key-sequences.
23433 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023434 for (i = 0; i < matcher->targets->nbItems; i++) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023435 res = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023436 refNode = matcher->targets->items[i];
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023437 if (bind != NULL) {
23438 refKeys = refNode->keys;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023439 for (j = 0; j < bind->nbNodes; j++) {
23440 keys = bind->nodeTable[j]->keys;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023441 for (k = 0; k < nbFields; k++) {
23442 res = xmlSchemaAreValuesEqual(keys[k]->val,
23443 refKeys[k]->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023444 if (res == 0)
23445 break;
23446 else if (res == -1) {
23447 return (-1);
23448 }
23449 }
23450 if (res == 1) {
23451 /*
23452 * Match found.
23453 */
23454 break;
23455 }
23456 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023457 if ((res == 0) && hasDupls) {
23458 /*
23459 * Search in duplicates
23460 */
23461 for (j = 0; j < bind->dupls->nbItems; j++) {
23462 keys = ((xmlSchemaPSVIIDCNodePtr)
23463 bind->dupls->items[j])->keys;
23464 for (k = 0; k < nbFields; k++) {
23465 res = xmlSchemaAreValuesEqual(keys[k]->val,
23466 refKeys[k]->val);
23467 if (res == 0)
23468 break;
23469 else if (res == -1) {
23470 return (-1);
23471 }
23472 }
23473 if (res == 1) {
23474 /*
23475 * Match in duplicates found.
23476 */
23477 xmlChar *str = NULL, *strB = NULL;
23478 xmlSchemaKeyrefErr(vctxt,
23479 XML_SCHEMAV_CVC_IDC, refNode,
23480 (xmlSchemaTypePtr) matcher->aidc->def,
23481 "More than one match found for "
23482 "key-sequence %s of keyref '%s'",
23483 xmlSchemaFormatIDCKeySequence(vctxt, &str,
23484 refNode->keys, nbFields),
23485 xmlSchemaGetComponentQName(&strB,
23486 matcher->aidc->def));
23487 FREE_AND_NULL(str);
23488 FREE_AND_NULL(strB);
23489 break;
23490 }
23491 }
23492 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023493 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023494
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023495 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023496 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023497 xmlSchemaKeyrefErr(vctxt,
23498 XML_SCHEMAV_CVC_IDC, refNode,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023499 (xmlSchemaTypePtr) matcher->aidc->def,
23500 "No match found for key-sequence %s of keyref '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000023501 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023502 refNode->keys, nbFields),
23503 xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023504 FREE_AND_NULL(str);
23505 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023506 }
23507 }
23508 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023509 matcher = matcher->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023510 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023511 /* TODO: Return an error if any error encountered. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023512 return (0);
23513}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023514
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023515/************************************************************************
23516 * *
23517 * XML Reader validation code *
23518 * *
23519 ************************************************************************/
23520
23521static xmlSchemaAttrInfoPtr
23522xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023523{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023524 xmlSchemaAttrInfoPtr iattr;
23525 /*
23526 * Grow/create list of attribute infos.
23527 */
23528 if (vctxt->attrInfos == NULL) {
23529 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23530 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23531 vctxt->sizeAttrInfos = 1;
23532 if (vctxt->attrInfos == NULL) {
23533 xmlSchemaVErrMemory(vctxt,
23534 "allocating attribute info list", NULL);
23535 return (NULL);
23536 }
23537 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23538 vctxt->sizeAttrInfos++;
23539 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23540 xmlRealloc(vctxt->attrInfos,
23541 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23542 if (vctxt->attrInfos == NULL) {
23543 xmlSchemaVErrMemory(vctxt,
23544 "re-allocating attribute info list", NULL);
23545 return (NULL);
23546 }
23547 } else {
23548 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23549 if (iattr->localName != NULL) {
23550 VERROR_INT("xmlSchemaGetFreshAttrInfo",
23551 "attr info not cleared");
23552 return (NULL);
23553 }
23554 iattr->nodeType = XML_ATTRIBUTE_NODE;
23555 return (iattr);
23556 }
23557 /*
23558 * Create an attribute info.
23559 */
23560 iattr = (xmlSchemaAttrInfoPtr)
23561 xmlMalloc(sizeof(xmlSchemaAttrInfo));
23562 if (iattr == NULL) {
23563 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23564 return (NULL);
23565 }
23566 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23567 iattr->nodeType = XML_ATTRIBUTE_NODE;
23568 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23569
23570 return (iattr);
23571}
23572
23573static int
23574xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23575 xmlNodePtr attrNode,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023576 int nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023577 const xmlChar *localName,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023578 const xmlChar *nsName,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023579 int ownedNames,
23580 xmlChar *value,
23581 int ownedValue)
23582{
23583 xmlSchemaAttrInfoPtr attr;
23584
23585 attr = xmlSchemaGetFreshAttrInfo(vctxt);
23586 if (attr == NULL) {
23587 VERROR_INT("xmlSchemaPushAttribute",
23588 "calling xmlSchemaGetFreshAttrInfo()");
23589 return (-1);
23590 }
23591 attr->node = attrNode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023592 attr->nodeLine = nodeLine;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023593 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23594 attr->localName = localName;
23595 attr->nsName = nsName;
23596 if (ownedNames)
23597 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23598 /*
23599 * Evaluate if it's an XSI attribute.
23600 */
23601 if (nsName != NULL) {
23602 if (xmlStrEqual(localName, BAD_CAST "nil")) {
23603 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23604 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23605 }
23606 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
23607 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23608 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23609 }
23610 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23611 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23612 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23613 }
23614 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23615 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23616 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23617 }
23618 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
23619 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
23620 }
23621 }
23622 attr->value = value;
23623 if (ownedValue)
23624 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23625 if (attr->metaType != 0)
23626 attr->state = XML_SCHEMAS_ATTR_META;
23627 return (0);
23628}
23629
23630static void
23631xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
23632{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023633 ielem->hasKeyrefs = 0;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000023634 ielem->appliedXPath = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023635 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
23636 FREE_AND_NULL(ielem->localName);
23637 FREE_AND_NULL(ielem->nsName);
23638 } else {
23639 ielem->localName = NULL;
23640 ielem->nsName = NULL;
23641 }
23642 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
23643 FREE_AND_NULL(ielem->value);
23644 } else {
23645 ielem->value = NULL;
23646 }
23647 if (ielem->val != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023648 /*
23649 * PSVI TODO: Be careful not to free it when the value is
23650 * exposed via PSVI.
23651 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023652 xmlSchemaFreeValue(ielem->val);
23653 ielem->val = NULL;
23654 }
23655 if (ielem->idcMatchers != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023656 /*
23657 * URGENT OPTIMIZE TODO: Use a pool of IDC matchers.
23658 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023659 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
23660 ielem->idcMatchers = NULL;
23661 }
23662 if (ielem->idcTable != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023663 /*
23664 * OPTIMIZE TODO: Use a pool of IDC tables??.
23665 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023666 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
23667 ielem->idcTable = NULL;
23668 }
23669 if (ielem->regexCtxt != NULL) {
23670 xmlRegFreeExecCtxt(ielem->regexCtxt);
23671 ielem->regexCtxt = NULL;
23672 }
23673 if (ielem->nsBindings != NULL) {
23674 xmlFree((xmlChar **)ielem->nsBindings);
23675 ielem->nsBindings = NULL;
23676 ielem->nbNsBindings = 0;
23677 ielem->sizeNsBindings = 0;
23678 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023679}
23680
23681/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023682 * xmlSchemaGetFreshElemInfo:
23683 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023684 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023685 * Creates/reuses and initializes the element info item for
23686 * the currect tree depth.
23687 *
23688 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023689 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023690static xmlSchemaNodeInfoPtr
23691xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023692{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023693 xmlSchemaNodeInfoPtr info = NULL;
23694
23695 if (vctxt->depth > vctxt->sizeElemInfos) {
23696 VERROR_INT("xmlSchemaGetFreshElemInfo",
23697 "inconsistent depth encountered");
23698 return (NULL);
23699 }
23700 if (vctxt->elemInfos == NULL) {
23701 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
23702 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
23703 if (vctxt->elemInfos == NULL) {
23704 xmlSchemaVErrMemory(vctxt,
23705 "allocating the element info array", NULL);
23706 return (NULL);
23707 }
23708 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
23709 vctxt->sizeElemInfos = 10;
23710 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
23711 int i = vctxt->sizeElemInfos;
23712
23713 vctxt->sizeElemInfos *= 2;
23714 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
23715 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
23716 sizeof(xmlSchemaNodeInfoPtr));
23717 if (vctxt->elemInfos == NULL) {
23718 xmlSchemaVErrMemory(vctxt,
23719 "re-allocating the element info array", NULL);
23720 return (NULL);
23721 }
23722 /*
23723 * We need the new memory to be NULLed.
23724 * TODO: Use memset instead?
23725 */
23726 for (; i < vctxt->sizeElemInfos; i++)
23727 vctxt->elemInfos[i] = NULL;
23728 } else
23729 info = vctxt->elemInfos[vctxt->depth];
23730
23731 if (info == NULL) {
23732 info = (xmlSchemaNodeInfoPtr)
23733 xmlMalloc(sizeof(xmlSchemaNodeInfo));
23734 if (info == NULL) {
23735 xmlSchemaVErrMemory(vctxt,
23736 "allocating an element info", NULL);
23737 return (NULL);
23738 }
23739 vctxt->elemInfos[vctxt->depth] = info;
23740 } else {
23741 if (info->localName != NULL) {
23742 VERROR_INT("xmlSchemaGetFreshElemInfo",
23743 "elem info has not been cleared");
23744 return (NULL);
23745 }
23746 }
23747 memset(info, 0, sizeof(xmlSchemaNodeInfo));
23748 info->nodeType = XML_ELEMENT_NODE;
23749 info->depth = vctxt->depth;
23750
23751 return (info);
23752}
23753
23754#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
23755#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
23756#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
23757
23758static int
23759xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
23760 xmlNodePtr node,
23761 xmlSchemaTypePtr type,
23762 xmlSchemaValType valType,
23763 const xmlChar * value,
23764 xmlSchemaValPtr val,
23765 unsigned long length,
23766 int fireErrors)
23767{
23768 int ret, error = 0;
23769
23770 xmlSchemaTypePtr tmpType;
23771 xmlSchemaFacetLinkPtr facetLink;
23772 xmlSchemaFacetPtr facet;
23773 unsigned long len = 0;
23774 xmlSchemaWhitespaceValueType ws;
23775
23776 /*
23777 * In Libxml2, derived built-in types have currently no explicit facets.
23778 */
23779 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023780 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023781
23782 /*
23783 * NOTE: Do not jump away, if the facetSet of the given type is
23784 * empty: until now, "pattern" and "enumeration" facets of the
23785 * *base types* need to be checked as well.
23786 */
23787 if (type->facetSet == NULL)
23788 goto pattern_and_enum;
23789
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023790 if (! WXS_IS_ATOMIC(type)) {
23791 if (WXS_IS_LIST(type))
23792 goto WXS_IS_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023793 else
23794 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023795 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023796 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023797 * Whitespace handling is only of importance for string-based
23798 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023799 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023800 tmpType = xmlSchemaGetPrimitiveType(type);
23801 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023802 WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023803 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
23804 } else
23805 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
23806 /*
23807 * If the value was not computed (for string or
23808 * anySimpleType based types), then use the provided
23809 * type.
23810 */
23811 if (val == NULL)
23812 valType = valType;
23813 else
23814 valType = xmlSchemaGetValType(val);
23815
23816 ret = 0;
23817 for (facetLink = type->facetSet; facetLink != NULL;
23818 facetLink = facetLink->next) {
23819 /*
23820 * Skip the pattern "whiteSpace": it is used to
23821 * format the character content beforehand.
23822 */
23823 switch (facetLink->facet->type) {
23824 case XML_SCHEMA_FACET_WHITESPACE:
23825 case XML_SCHEMA_FACET_PATTERN:
23826 case XML_SCHEMA_FACET_ENUMERATION:
23827 continue;
23828 case XML_SCHEMA_FACET_LENGTH:
23829 case XML_SCHEMA_FACET_MINLENGTH:
23830 case XML_SCHEMA_FACET_MAXLENGTH:
23831 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
23832 valType, value, val, &len, ws);
23833 break;
23834 default:
23835 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
23836 valType, value, val, ws);
23837 break;
23838 }
23839 if (ret < 0) {
23840 AERROR_INT("xmlSchemaValidateFacets",
23841 "validating against a atomic type facet");
23842 return (-1);
23843 } else if (ret > 0) {
23844 if (fireErrors)
23845 xmlSchemaFacetErr(actxt, ret, node,
23846 value, len, type, facetLink->facet, NULL, NULL, NULL);
23847 else
23848 return (ret);
23849 if (error == 0)
23850 error = ret;
23851 }
23852 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023853 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023854
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023855WXS_IS_LIST:
23856 if (! WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023857 goto pattern_and_enum;
23858 /*
23859 * "length", "minLength" and "maxLength" of list types.
23860 */
23861 ret = 0;
23862 for (facetLink = type->facetSet; facetLink != NULL;
23863 facetLink = facetLink->next) {
23864
23865 switch (facetLink->facet->type) {
23866 case XML_SCHEMA_FACET_LENGTH:
23867 case XML_SCHEMA_FACET_MINLENGTH:
23868 case XML_SCHEMA_FACET_MAXLENGTH:
23869 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
23870 value, length, NULL);
23871 break;
23872 default:
23873 continue;
23874 }
23875 if (ret < 0) {
23876 AERROR_INT("xmlSchemaValidateFacets",
23877 "validating against a list type facet");
23878 return (-1);
23879 } else if (ret > 0) {
23880 if (fireErrors)
23881 xmlSchemaFacetErr(actxt, ret, node,
23882 value, length, type, facetLink->facet, NULL, NULL, NULL);
23883 else
23884 return (ret);
23885 if (error == 0)
23886 error = ret;
23887 }
23888 ret = 0;
23889 }
23890
23891pattern_and_enum:
23892 if (error >= 0) {
23893 int found = 0;
23894 /*
23895 * Process enumerations. Facet values are in the value space
23896 * of the defining type's base type. This seems to be a bug in the
23897 * XML Schema 1.0 spec. Use the whitespace type of the base type.
23898 * Only the first set of enumerations in the ancestor-or-self axis
23899 * is used for validation.
23900 */
23901 ret = 0;
23902 tmpType = type;
23903 do {
23904 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
23905 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
23906 continue;
23907 found = 1;
23908 ret = xmlSchemaAreValuesEqual(facet->val, val);
23909 if (ret == 1)
23910 break;
23911 else if (ret < 0) {
23912 AERROR_INT("xmlSchemaValidateFacets",
23913 "validating against an enumeration facet");
23914 return (-1);
23915 }
23916 }
23917 if (ret != 0)
23918 break;
23919 tmpType = tmpType->baseType;
23920 } while ((tmpType != NULL) &&
23921 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
23922 if (found && (ret == 0)) {
23923 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
23924 if (fireErrors) {
23925 xmlSchemaFacetErr(actxt, ret, node,
23926 value, 0, type, NULL, NULL, NULL, NULL);
23927 } else
23928 return (ret);
23929 if (error == 0)
23930 error = ret;
23931 }
23932 }
23933
23934 if (error >= 0) {
23935 int found;
23936 /*
23937 * Process patters. Pattern facets are ORed at type level
23938 * and ANDed if derived. Walk the base type axis.
23939 */
23940 tmpType = type;
23941 facet = NULL;
23942 do {
23943 found = 0;
23944 for (facetLink = tmpType->facetSet; facetLink != NULL;
23945 facetLink = facetLink->next) {
23946 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
23947 continue;
23948 found = 1;
23949 /*
23950 * NOTE that for patterns, @value needs to be the
23951 * normalized vaule.
23952 */
23953 ret = xmlRegexpExec(facetLink->facet->regexp, value);
23954 if (ret == 1)
23955 break;
23956 else if (ret < 0) {
23957 AERROR_INT("xmlSchemaValidateFacets",
23958 "validating against a pattern facet");
23959 return (-1);
23960 } else {
23961 /*
23962 * Save the last non-validating facet.
23963 */
23964 facet = facetLink->facet;
23965 }
23966 }
23967 if (found && (ret != 1)) {
23968 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
23969 if (fireErrors) {
23970 xmlSchemaFacetErr(actxt, ret, node,
23971 value, 0, type, facet, NULL, NULL, NULL);
23972 } else
23973 return (ret);
23974 if (error == 0)
23975 error = ret;
23976 break;
23977 }
23978 tmpType = tmpType->baseType;
23979 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
23980 }
23981
23982 return (error);
23983}
23984
23985static xmlChar *
23986xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
23987 const xmlChar *value)
23988{
23989 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
23990 case XML_SCHEMA_WHITESPACE_COLLAPSE:
23991 return (xmlSchemaCollapseString(value));
23992 case XML_SCHEMA_WHITESPACE_REPLACE:
23993 return (xmlSchemaWhiteSpaceReplace(value));
23994 default:
23995 return (NULL);
23996 }
23997}
23998
23999static int
24000xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24001 const xmlChar *value,
24002 xmlSchemaValPtr *val,
24003 int valNeeded)
24004{
24005 int ret;
24006 const xmlChar *nsName;
24007 xmlChar *local, *prefix = NULL;
24008
24009 ret = xmlValidateQName(value, 1);
24010 if (ret != 0) {
24011 if (ret == -1) {
24012 VERROR_INT("xmlSchemaValidateQName",
24013 "calling xmlValidateQName()");
24014 return (-1);
24015 }
24016 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24017 }
24018 /*
24019 * NOTE: xmlSplitQName2 will always return a duplicated
24020 * strings.
24021 */
24022 local = xmlSplitQName2(value, &prefix);
24023 if (local == NULL)
24024 local = xmlStrdup(value);
24025 /*
24026 * OPTIMIZE TODO: Use flags for:
24027 * - is there any namespace binding?
24028 * - is there a default namespace?
24029 */
24030 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24031
24032 if (prefix != NULL) {
24033 xmlFree(prefix);
24034 /*
24035 * A namespace must be found if the prefix is
24036 * NOT NULL.
24037 */
24038 if (nsName == NULL) {
24039 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024040 xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024041 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024042 "The QName value '%s' has no "
24043 "corresponding namespace declaration in "
24044 "scope", value, NULL);
24045 if (local != NULL)
24046 xmlFree(local);
24047 return (ret);
24048 }
24049 }
24050 if (valNeeded && val) {
24051 if (nsName != NULL)
24052 *val = xmlSchemaNewQNameValue(
24053 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24054 else
24055 *val = xmlSchemaNewQNameValue(NULL,
24056 BAD_CAST local);
24057 } else
24058 xmlFree(local);
24059 return (0);
24060}
24061
24062/*
24063* cvc-simple-type
24064*/
24065static int
24066xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24067 xmlNodePtr node,
24068 xmlSchemaTypePtr type,
24069 const xmlChar *value,
24070 xmlSchemaValPtr *retVal,
24071 int fireErrors,
24072 int normalize,
24073 int isNormalized)
24074{
24075 int ret = 0, valNeeded = (retVal) ? 1 : 0;
24076 xmlSchemaValPtr val = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024077 /* xmlSchemaWhitespaceValueType ws; */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024078 xmlChar *normValue = NULL;
24079
24080#define NORMALIZE(atype) \
24081 if ((! isNormalized) && \
24082 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24083 normValue = xmlSchemaNormalizeValue(atype, value); \
24084 if (normValue != NULL) \
24085 value = normValue; \
24086 isNormalized = 1; \
24087 }
24088
24089 if ((retVal != NULL) && (*retVal != NULL)) {
24090 xmlSchemaFreeValue(*retVal);
24091 *retVal = NULL;
24092 }
24093 /*
24094 * 3.14.4 Simple Type Definition Validation Rules
24095 * Validation Rule: String Valid
24096 */
24097 /*
24098 * 1 It is schema-valid with respect to that definition as defined
24099 * by Datatype Valid in [XML Schemas: Datatypes].
24100 */
24101 /*
24102 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24103 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
24104 * the string must be a ·declared entity name·.
24105 */
24106 /*
24107 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24108 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
24109 * then every whitespace-delimited substring of the string must be a ·declared
24110 * entity name·.
24111 */
24112 /*
24113 * 2.3 otherwise no further condition applies.
24114 */
24115 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24116 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000024117 if (value == NULL)
24118 value = BAD_CAST "";
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024119 if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024120 xmlSchemaTypePtr biType; /* The built-in type. */
24121 /*
24122 * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match·
24123 * a literal in the ·lexical space· of {base type definition}"
24124 */
24125 /*
24126 * Whitespace-normalize.
24127 */
24128 NORMALIZE(type);
24129 if (type->type != XML_SCHEMA_TYPE_BASIC) {
24130 /*
24131 * Get the built-in type.
24132 */
24133 biType = type->baseType;
24134 while ((biType != NULL) &&
24135 (biType->type != XML_SCHEMA_TYPE_BASIC))
24136 biType = biType->baseType;
24137
24138 if (biType == NULL) {
24139 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24140 "could not get the built-in type");
24141 goto internal_error;
24142 }
24143 } else
24144 biType = type;
24145 /*
24146 * NOTATIONs need to be processed here, since they need
24147 * to lookup in the hashtable of NOTATION declarations of the schema.
24148 */
24149 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24150 switch (biType->builtInType) {
24151 case XML_SCHEMAS_NOTATION:
24152 ret = xmlSchemaValidateNotation(
24153 (xmlSchemaValidCtxtPtr) actxt,
24154 ((xmlSchemaValidCtxtPtr) actxt)->schema,
24155 NULL, value, &val, valNeeded);
24156 break;
24157 case XML_SCHEMAS_QNAME:
24158 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24159 value, &val, valNeeded);
24160 break;
24161 default:
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024162 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024163 if (valNeeded)
24164 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24165 value, &val, NULL);
24166 else
24167 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24168 value, NULL, NULL);
24169 break;
24170 }
24171 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24172 switch (biType->builtInType) {
24173 case XML_SCHEMAS_NOTATION:
24174 ret = xmlSchemaValidateNotation(NULL,
24175 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24176 value, &val, valNeeded);
24177 break;
24178 default:
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024179 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024180 if (valNeeded)
24181 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24182 value, &val, node);
24183 else
24184 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24185 value, NULL, node);
24186 break;
24187 }
24188 } else {
24189 /*
24190 * Validation via a public API is not implemented yet.
24191 */
24192 TODO
24193 goto internal_error;
24194 }
24195 if (ret != 0) {
24196 if (ret < 0) {
24197 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24198 "validating against a built-in 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 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24207 /*
24208 * Check facets.
24209 */
24210 ret = xmlSchemaValidateFacets(actxt, node, type,
24211 (xmlSchemaValType) biType->builtInType, value, val,
24212 0, fireErrors);
24213 if (ret != 0) {
24214 if (ret < 0) {
24215 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24216 "validating facets of atomic simple type");
24217 goto internal_error;
24218 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024219 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024220 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24221 else
24222 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24223 }
24224 }
24225 if (fireErrors && (ret > 0))
24226 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024227 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024228
24229 xmlSchemaTypePtr itemType;
24230 const xmlChar *cur, *end;
24231 xmlChar *tmpValue = NULL;
24232 unsigned long len = 0;
24233 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24234 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
24235 * of white space separated tokens, each of which ·match·es a literal
24236 * in the ·lexical space· of {item type definition}
24237 */
24238 /*
24239 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24240 * the list type has an enum or pattern facet.
24241 */
24242 NORMALIZE(type);
24243 /*
24244 * VAL TODO: Optimize validation of empty values.
24245 * VAL TODO: We do not have computed values for lists.
24246 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024247 itemType = WXS_LIST_ITEMTYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024248 cur = value;
24249 do {
24250 while (IS_BLANK_CH(*cur))
24251 cur++;
24252 end = cur;
24253 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24254 end++;
24255 if (end == cur)
24256 break;
24257 tmpValue = xmlStrndup(cur, end - cur);
24258 len++;
24259
24260 if (valNeeded)
24261 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24262 tmpValue, &curVal, fireErrors, 0, 1);
24263 else
24264 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24265 tmpValue, NULL, fireErrors, 0, 1);
24266 FREE_AND_NULL(tmpValue);
24267 if (curVal != NULL) {
24268 /*
24269 * Add to list of computed values.
24270 */
24271 if (val == NULL)
24272 val = curVal;
24273 else
24274 xmlSchemaValueAppend(prevVal, curVal);
24275 prevVal = curVal;
24276 curVal = NULL;
24277 }
24278 if (ret != 0) {
24279 if (ret < 0) {
24280 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24281 "validating an item of list simple type");
24282 goto internal_error;
24283 }
24284 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24285 break;
24286 }
24287 cur = end;
24288 } while (*cur != 0);
24289 FREE_AND_NULL(tmpValue);
24290 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24291 /*
24292 * Apply facets (pattern, enumeration).
24293 */
24294 ret = xmlSchemaValidateFacets(actxt, node, type,
24295 XML_SCHEMAS_UNKNOWN, value, val,
24296 len, fireErrors);
24297 if (ret != 0) {
24298 if (ret < 0) {
24299 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24300 "validating facets of list simple type");
24301 goto internal_error;
24302 }
24303 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24304 }
24305 }
24306 if (fireErrors && (ret > 0)) {
24307 /*
24308 * Report the normalized value.
24309 */
24310 normalize = 1;
24311 NORMALIZE(type);
24312 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24313 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024314 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024315 xmlSchemaTypeLinkPtr memberLink;
24316 /*
24317 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
24318 * not apply directly; however, the normalization behavior of ·union·
24319 * types is controlled by the value of whiteSpace on that one of the
24320 * ·memberTypes· against which the ·union· is successfully validated.
24321 *
24322 * This means that the value is normalized by the first validating
24323 * member type, then the facets of the union type are applied. This
24324 * needs changing of the value!
24325 */
24326
24327 /*
24328 * 1.2.3 if {variety} is ·union· then the string must ·match· a
24329 * literal in the ·lexical space· of at least one member of
24330 * {member type definitions}
24331 */
24332 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24333 if (memberLink == NULL) {
24334 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24335 "union simple type has no member types");
24336 goto internal_error;
24337 }
24338 /*
24339 * Always normalize union type values, since we currently
24340 * cannot store the whitespace information with the value
24341 * itself; otherwise a later value-comparison would be
24342 * not possible.
24343 */
24344 while (memberLink != NULL) {
24345 if (valNeeded)
24346 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24347 memberLink->type, value, &val, 0, 1, 0);
24348 else
24349 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24350 memberLink->type, value, NULL, 0, 1, 0);
24351 if (ret <= 0)
24352 break;
24353 memberLink = memberLink->next;
24354 }
24355 if (ret != 0) {
24356 if (ret < 0) {
24357 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24358 "validating members of union simple type");
24359 goto internal_error;
24360 }
24361 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24362 }
24363 /*
24364 * Apply facets (pattern, enumeration).
24365 */
24366 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24367 /*
24368 * The normalization behavior of ·union· types is controlled by
24369 * the value of whiteSpace on that one of the ·memberTypes·
24370 * against which the ·union· is successfully validated.
24371 */
24372 NORMALIZE(memberLink->type);
24373 ret = xmlSchemaValidateFacets(actxt, node, type,
24374 XML_SCHEMAS_UNKNOWN, value, val,
24375 0, fireErrors);
24376 if (ret != 0) {
24377 if (ret < 0) {
24378 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24379 "validating facets of union simple type");
24380 goto internal_error;
24381 }
24382 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24383 }
24384 }
24385 if (fireErrors && (ret > 0))
24386 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24387 }
24388
24389 if (normValue != NULL)
24390 xmlFree(normValue);
24391 if (ret == 0) {
24392 if (retVal != NULL)
24393 *retVal = val;
24394 else if (val != NULL)
24395 xmlSchemaFreeValue(val);
24396 } else if (val != NULL)
24397 xmlSchemaFreeValue(val);
24398 return (ret);
24399internal_error:
24400 if (normValue != NULL)
24401 xmlFree(normValue);
24402 if (val != NULL)
24403 xmlSchemaFreeValue(val);
24404 return (-1);
24405}
24406
24407static int
24408xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24409 const xmlChar *value,
24410 const xmlChar **nsName,
24411 const xmlChar **localName)
24412{
24413 int ret = 0;
24414
24415 if ((nsName == NULL) || (localName == NULL))
24416 return (-1);
24417 *nsName = NULL;
24418 *localName = NULL;
24419
24420 ret = xmlValidateQName(value, 1);
24421 if (ret == -1)
24422 return (-1);
24423 if (ret > 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024424 xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024425 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24426 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24427 return (1);
24428 }
24429 {
24430 xmlChar *local = NULL;
24431 xmlChar *prefix;
24432
24433 /*
24434 * NOTE: xmlSplitQName2 will return a duplicated
24435 * string.
24436 */
24437 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024438 if (local == NULL)
24439 *localName = xmlDictLookup(vctxt->dict, value, -1);
24440 else {
24441 *localName = xmlDictLookup(vctxt->dict, local, -1);
24442 xmlFree(local);
24443 }
24444
24445 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24446
24447 if (prefix != NULL) {
24448 xmlFree(prefix);
24449 /*
24450 * A namespace must be found if the prefix is NOT NULL.
24451 */
24452 if (*nsName == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024453 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024454 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024455 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024456 "The QName value '%s' has no "
24457 "corresponding namespace declaration in scope",
24458 value, NULL);
24459 return (2);
24460 }
24461 }
24462 }
24463 return (0);
24464}
24465
24466static int
24467xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24468 xmlSchemaAttrInfoPtr iattr,
24469 xmlSchemaTypePtr *localType,
24470 xmlSchemaElementPtr elemDecl)
24471{
24472 int ret = 0;
24473 /*
24474 * cvc-elt (3.3.4) : (4)
24475 * AND
24476 * Schema-Validity Assessment (Element) (cvc-assess-elt)
24477 * (1.2.1.2.1) - (1.2.1.2.4)
24478 * Handle 'xsi:type'.
24479 */
24480 if (localType == NULL)
24481 return (-1);
24482 *localType = NULL;
24483 if (iattr == NULL)
24484 return (0);
24485 else {
24486 const xmlChar *nsName = NULL, *local = NULL;
24487 /*
24488 * TODO: We should report a *warning* that the type was overriden
24489 * by the instance.
24490 */
24491 ACTIVATE_ATTRIBUTE(iattr);
24492 /*
24493 * (cvc-elt) (3.3.4) : (4.1)
24494 * (cvc-assess-elt) (1.2.1.2.2)
24495 */
24496 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24497 &nsName, &local);
24498 if (ret != 0) {
24499 if (ret < 0) {
24500 VERROR_INT("xmlSchemaValidateElementByDeclaration",
24501 "calling xmlSchemaQNameExpand() to validate the "
24502 "attribute 'xsi:type'");
24503 goto internal_error;
24504 }
24505 goto exit;
24506 }
24507 /*
24508 * (cvc-elt) (3.3.4) : (4.2)
24509 * (cvc-assess-elt) (1.2.1.2.3)
24510 */
24511 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24512 if (*localType == NULL) {
24513 xmlChar *str = NULL;
24514
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024515 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024516 XML_SCHEMAV_CVC_ELT_4_2, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024517 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024518 "The QName value '%s' of the xsi:type attribute does not "
24519 "resolve to a type definition",
24520 xmlSchemaFormatQName(&str, nsName, local), NULL);
24521 FREE_AND_NULL(str);
24522 ret = vctxt->err;
24523 goto exit;
24524 }
24525 if (elemDecl != NULL) {
24526 int set = 0;
24527
24528 /*
24529 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24530 * "The ·local type definition· must be validly
24531 * derived from the {type definition} given the union of
24532 * the {disallowed substitutions} and the {type definition}'s
24533 * {prohibited substitutions}, as defined in
24534 * Type Derivation OK (Complex) (§3.4.6)
24535 * (if it is a complex type definition),
24536 * or given {disallowed substitutions} as defined in Type
24537 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
24538 * definition)."
24539 *
24540 * {disallowed substitutions}: the "block" on the element decl.
24541 * {prohibited substitutions}: the "block" on the type def.
24542 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000024543 /*
24544 * OPTIMIZE TODO: We could map types already evaluated
24545 * to be validly derived from other types to avoid checking
24546 * this over and over for the same types.
24547 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024548 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24549 (elemDecl->subtypes->flags &
24550 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24551 set |= SUBSET_EXTENSION;
24552
24553 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24554 (elemDecl->subtypes->flags &
24555 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24556 set |= SUBSET_RESTRICTION;
24557
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000024558 /*
24559 * REMOVED and CHANGED since this produced a parser context
24560 * which adds to the string dict of the schema. So this would
24561 * change the schema and we don't want this. We don't need
24562 * the parser context anymore.
24563 *
24564 * if ((vctxt->pctxt == NULL) &&
24565 * (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24566 * return (-1);
24567 */
24568
24569 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024570 elemDecl->subtypes, set) != 0) {
24571 xmlChar *str = NULL;
24572
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024573 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024574 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24575 "The type definition '%s', specified by xsi:type, is "
24576 "blocked or not validly derived from the type definition "
24577 "of the element declaration",
24578 xmlSchemaFormatQName(&str,
24579 (*localType)->targetNamespace,
24580 (*localType)->name),
24581 NULL);
24582 FREE_AND_NULL(str);
24583 ret = vctxt->err;
24584 *localType = NULL;
24585 }
24586 }
24587 }
24588exit:
24589 ACTIVATE_ELEM;
24590 return (ret);
24591internal_error:
24592 ACTIVATE_ELEM;
24593 return (-1);
24594}
24595
24596static int
24597xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24598{
24599 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
Daniel Veillard14b56432006-03-09 18:41:40 +000024600 xmlSchemaTypePtr actualType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024601
24602 /*
24603 * cvc-elt (3.3.4) : 1
24604 */
24605 if (elemDecl == NULL) {
24606 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
24607 "No matching declaration available");
24608 return (vctxt->err);
24609 }
Daniel Veillard14b56432006-03-09 18:41:40 +000024610 actualType = WXS_ELEM_TYPEDEF(elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024611 /*
24612 * cvc-elt (3.3.4) : 2
24613 */
24614 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
24615 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
24616 "The element declaration is abstract");
24617 return (vctxt->err);
24618 }
24619 if (actualType == NULL) {
24620 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24621 "The type definition is absent");
24622 return (XML_SCHEMAV_CVC_TYPE_1);
24623 }
24624 if (vctxt->nbAttrInfos != 0) {
24625 int ret;
24626 xmlSchemaAttrInfoPtr iattr;
24627 /*
24628 * cvc-elt (3.3.4) : 3
24629 * Handle 'xsi:nil'.
24630 */
24631 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24632 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
24633 if (iattr) {
24634 ACTIVATE_ATTRIBUTE(iattr);
24635 /*
24636 * Validate the value.
24637 */
24638 ret = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024639 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024640 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
24641 iattr->value, &(iattr->val), 1, 0, 0);
24642 ACTIVATE_ELEM;
24643 if (ret < 0) {
24644 VERROR_INT("xmlSchemaValidateElemDecl",
24645 "calling xmlSchemaVCheckCVCSimpleType() to "
24646 "validate the attribute 'xsi:nil'");
24647 return (-1);
24648 }
24649 if (ret == 0) {
24650 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
24651 /*
24652 * cvc-elt (3.3.4) : 3.1
24653 */
24654 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
24655 "The element is not 'nillable'");
24656 /* Does not return an error on purpose. */
24657 } else {
24658 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
24659 /*
24660 * cvc-elt (3.3.4) : 3.2.2
24661 */
24662 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
24663 (elemDecl->value != NULL)) {
24664 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
24665 "The element cannot be 'nilled' because "
24666 "there is a fixed value constraint defined "
24667 "for it");
24668 /* Does not return an error on purpose. */
24669 } else
24670 vctxt->inode->flags |=
24671 XML_SCHEMA_ELEM_INFO_NILLED;
24672 }
24673 }
24674 }
24675 }
24676 /*
24677 * cvc-elt (3.3.4) : 4
24678 * Handle 'xsi:type'.
24679 */
24680 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24681 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
24682 if (iattr) {
24683 xmlSchemaTypePtr localType = NULL;
24684
24685 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
24686 elemDecl);
24687 if (ret != 0) {
24688 if (ret == -1) {
24689 VERROR_INT("xmlSchemaValidateElemDecl",
24690 "calling xmlSchemaProcessXSIType() to "
24691 "process the attribute 'xsi:type'");
24692 return (-1);
24693 }
24694 /* Does not return an error on purpose. */
24695 }
24696 if (localType != NULL) {
24697 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
24698 actualType = localType;
24699 }
24700 }
24701 }
24702 /*
24703 * IDC: Register identity-constraint XPath matchers.
24704 */
24705 if ((elemDecl->idcs != NULL) &&
24706 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
24707 return (-1);
24708 /*
24709 * No actual type definition.
24710 */
24711 if (actualType == NULL) {
24712 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24713 "The type definition is absent");
24714 return (XML_SCHEMAV_CVC_TYPE_1);
24715 }
24716 /*
24717 * Remember the actual type definition.
24718 */
24719 vctxt->inode->typeDef = actualType;
24720
24721 return (0);
24722}
24723
24724static int
24725xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
24726{
24727 xmlSchemaAttrInfoPtr iattr;
24728 int ret = 0, i;
24729
24730 /*
24731 * SPEC cvc-type (3.1.1)
24732 * "The attributes of must be empty, excepting those whose namespace
24733 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
24734 * whose local name is one of type, nil, schemaLocation or
24735 * noNamespaceSchemaLocation."
24736 */
24737 if (vctxt->nbAttrInfos == 0)
24738 return (0);
24739 for (i = 0; i < vctxt->nbAttrInfos; i++) {
24740 iattr = vctxt->attrInfos[i];
24741 if (! iattr->metaType) {
24742 ACTIVATE_ATTRIBUTE(iattr)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024743 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024744 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
24745 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
24746 }
24747 }
24748 ACTIVATE_ELEM
24749 return (ret);
24750}
24751
24752/*
24753* Cleanup currently used attribute infos.
24754*/
24755static void
24756xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
24757{
24758 int i;
24759 xmlSchemaAttrInfoPtr attr;
24760
24761 if (vctxt->nbAttrInfos == 0)
24762 return;
24763 for (i = 0; i < vctxt->nbAttrInfos; i++) {
24764 attr = vctxt->attrInfos[i];
24765 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24766 if (attr->localName != NULL)
24767 xmlFree((xmlChar *) attr->localName);
24768 if (attr->nsName != NULL)
24769 xmlFree((xmlChar *) attr->nsName);
24770 }
24771 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24772 if (attr->value != NULL)
24773 xmlFree((xmlChar *) attr->value);
24774 }
24775 if (attr->val != NULL) {
24776 xmlSchemaFreeValue(attr->val);
24777 attr->val = NULL;
24778 }
24779 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
24780 }
24781 vctxt->nbAttrInfos = 0;
24782}
24783
24784/*
24785* 3.4.4 Complex Type Definition Validation Rules
24786* Element Locally Valid (Complex Type) (cvc-complex-type)
24787* 3.2.4 Attribute Declaration Validation Rules
24788* Validation Rule: Attribute Locally Valid (cvc-attribute)
24789* Attribute Locally Valid (Use) (cvc-au)
24790*
24791* Only "assessed" attribute information items will be visible to
24792* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
24793*/
24794static int
24795xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
24796{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024797 xmlSchemaTypePtr type = vctxt->inode->typeDef;
24798 xmlSchemaItemListPtr attrUseList;
24799 xmlSchemaAttributeUsePtr attrUse = NULL;
24800 xmlSchemaAttributePtr attrDecl = NULL;
24801 xmlSchemaAttrInfoPtr iattr, tmpiattr;
24802 int i, j, found, nbAttrs, nbUses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024803 int xpathRes = 0, res, wildIDs = 0, fixed;
24804
24805 /*
24806 * SPEC (cvc-attribute)
24807 * (1) "The declaration must not be ·absent· (see Missing
24808 * Sub-components (§5.3) for how this can fail to be
24809 * the case)."
24810 * (2) "Its {type definition} must not be absent."
24811 *
24812 * NOTE (1) + (2): This is not handled here, since we currently do not
24813 * allow validation against schemas which have missing sub-components.
24814 *
24815 * SPEC (cvc-complex-type)
24816 * (3) "For each attribute information item in the element information
24817 * item's [attributes] excepting those whose [namespace name] is
24818 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
24819 * [local name] is one of type, nil, schemaLocation or
24820 * noNamespaceSchemaLocation, the appropriate case among the following
24821 * must be true:
24822 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024823 */
24824 attrUseList = (xmlSchemaItemListPtr) type->attrUses;
24825 /*
24826 * @nbAttrs is the number of attributes present in the instance.
24827 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024828 nbAttrs = vctxt->nbAttrInfos;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024829 if (attrUseList != NULL)
24830 nbUses = attrUseList->nbItems;
24831 else
24832 nbUses = 0;
24833 for (i = 0; i < nbUses; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024834 found = 0;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024835 attrUse = attrUseList->items[i];
24836 attrDecl = WXS_ATTRUSE_DECL(attrUse);
24837 for (j = 0; j < nbAttrs; j++) {
24838 iattr = vctxt->attrInfos[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024839 /*
24840 * SPEC (cvc-complex-type) (3)
24841 * Skip meta attributes.
24842 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024843 if (iattr->metaType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024844 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024845 if (iattr->localName[0] != attrDecl->name[0])
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024846 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024847 if (!xmlStrEqual(iattr->localName, attrDecl->name))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024848 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024849 if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024850 continue;
24851 found = 1;
24852 /*
24853 * SPEC (cvc-complex-type)
24854 * (3.1) "If there is among the {attribute uses} an attribute
24855 * use with an {attribute declaration} whose {name} matches
24856 * the attribute information item's [local name] and whose
24857 * {target namespace} is identical to the attribute information
24858 * item's [namespace name] (where an ·absent· {target namespace}
24859 * is taken to be identical to a [namespace name] with no value),
24860 * then the attribute information must be ·valid· with respect
24861 * to that attribute use as per Attribute Locally Valid (Use)
24862 * (§3.5.4). In this case the {attribute declaration} of that
24863 * attribute use is the ·context-determined declaration· for the
24864 * attribute information item with respect to Schema-Validity
24865 * Assessment (Attribute) (§3.2.4) and
24866 * Assessment Outcome (Attribute) (§3.2.5).
24867 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024868 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
24869 iattr->use = attrUse;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024870 /*
24871 * Context-determined declaration.
24872 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024873 iattr->decl = attrDecl;
24874 iattr->typeDef = attrDecl->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024875 break;
24876 }
24877
24878 if (found)
24879 continue;
24880
24881 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
24882 /*
24883 * Handle non-existent, required attributes.
24884 *
24885 * SPEC (cvc-complex-type)
24886 * (4) "The {attribute declaration} of each attribute use in
24887 * the {attribute uses} whose {required} is true matches one
24888 * of the attribute information items in the element information
24889 * item's [attributes] as per clause 3.1 above."
24890 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024891 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
24892 if (tmpiattr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024893 VERROR_INT(
24894 "xmlSchemaVAttributesComplex",
24895 "calling xmlSchemaGetFreshAttrInfo()");
24896 return (-1);
24897 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024898 tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
24899 tmpiattr->use = attrUse;
24900 tmpiattr->decl = attrDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024901 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
24902 ((attrUse->defValue != NULL) ||
24903 (attrDecl->defValue != NULL))) {
24904 /*
24905 * Handle non-existent, optional, default/fixed attributes.
24906 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024907 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
24908 if (tmpiattr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024909 VERROR_INT(
24910 "xmlSchemaVAttributesComplex",
24911 "calling xmlSchemaGetFreshAttrInfo()");
24912 return (-1);
24913 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024914 tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
24915 tmpiattr->use = attrUse;
24916 tmpiattr->decl = attrDecl;
24917 tmpiattr->typeDef = attrDecl->subtypes;
24918 tmpiattr->localName = attrDecl->name;
24919 tmpiattr->nsName = attrDecl->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024920 }
24921 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024922
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024923 if (vctxt->nbAttrInfos == 0)
24924 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024925 nbUses = vctxt->nbAttrInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024926 /*
24927 * Validate against the wildcard.
24928 */
24929 if (type->attributeWildcard != NULL) {
24930 /*
24931 * SPEC (cvc-complex-type)
24932 * (3.2.1) "There must be an {attribute wildcard}."
24933 */
24934 for (i = 0; i < nbAttrs; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024935 iattr = vctxt->attrInfos[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024936 /*
24937 * SPEC (cvc-complex-type) (3)
24938 * Skip meta attributes.
24939 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024940 if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024941 continue;
24942 /*
24943 * SPEC (cvc-complex-type)
24944 * (3.2.2) "The attribute information item must be ·valid· with
24945 * respect to it as defined in Item Valid (Wildcard) (§3.10.4)."
24946 *
24947 * SPEC Item Valid (Wildcard) (cvc-wildcard)
24948 * "... its [namespace name] must be ·valid· with respect to
24949 * the wildcard constraint, as defined in Wildcard allows
24950 * Namespace Name (§3.10.4)."
24951 */
24952 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024953 iattr->nsName) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024954 /*
24955 * Handle processContents.
24956 *
24957 * SPEC (cvc-wildcard):
24958 * processContents | context-determined declaration:
24959 * "strict" "mustFind"
24960 * "lax" "none"
24961 * "skip" "skip"
24962 */
24963 if (type->attributeWildcard->processContents ==
24964 XML_SCHEMAS_ANY_SKIP) {
24965 /*
24966 * context-determined declaration = "skip"
24967 *
24968 * SPEC PSVI Assessment Outcome (Attribute)
24969 * [validity] = "notKnown"
24970 * [validation attempted] = "none"
24971 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024972 iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024973 continue;
24974 }
24975 /*
24976 * Find an attribute declaration.
24977 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024978 iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
24979 iattr->localName, iattr->nsName);
24980 if (iattr->decl != NULL) {
24981 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024982 /*
24983 * SPEC (cvc-complex-type)
24984 * (5) "Let [Definition:] the wild IDs be the set of
24985 * all attribute information item to which clause 3.2
24986 * applied and whose ·validation· resulted in a
24987 * ·context-determined declaration· of mustFind or no
24988 * ·context-determined declaration· at all, and whose
24989 * [local name] and [namespace name] resolve (as
24990 * defined by QName resolution (Instance) (§3.15.4)) to
24991 * an attribute declaration whose {type definition} is
24992 * or is derived from ID. Then all of the following
24993 * must be true:"
24994 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024995 iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024996 if (xmlSchemaIsDerivedFromBuiltInType(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024997 iattr->typeDef, XML_SCHEMAS_ID)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024998 /*
24999 * SPEC (5.1) "There must be no more than one
25000 * item in ·wild IDs·."
25001 */
25002 if (wildIDs != 0) {
25003 /* VAL TODO */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025004 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025005 TODO
25006 continue;
25007 }
25008 wildIDs++;
25009 /*
25010 * SPEC (cvc-complex-type)
25011 * (5.2) "If ·wild IDs· is non-empty, there must not
25012 * be any attribute uses among the {attribute uses}
25013 * whose {attribute declaration}'s {type definition}
25014 * is or is derived from ID."
25015 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025016 for (j = 0; j < attrUseList->nbItems; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025017 if (xmlSchemaIsDerivedFromBuiltInType(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025018 WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025019 XML_SCHEMAS_ID)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025020 /* URGENT VAL TODO: implement */
25021 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025022 TODO
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025023 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025024 }
25025 }
25026 }
25027 } else if (type->attributeWildcard->processContents ==
25028 XML_SCHEMAS_ANY_LAX) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025029 iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025030 /*
25031 * SPEC PSVI Assessment Outcome (Attribute)
25032 * [validity] = "notKnown"
25033 * [validation attempted] = "none"
25034 */
25035 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025036 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025037 }
25038 }
25039 }
25040 }
25041
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025042 if (vctxt->nbAttrInfos == 0)
25043 return (0);
25044
25045 /*
25046 * Validate values, create default attributes, evaluate IDCs.
25047 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025048 for (i = 0; i < vctxt->nbAttrInfos; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025049 iattr = vctxt->attrInfos[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025050 /*
25051 * VAL TODO: Note that we won't try to resolve IDCs to
25052 * "lax" and "skip" validated attributes. Check what to
25053 * do in this case.
25054 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025055 if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25056 (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025057 continue;
25058 /*
25059 * VAL TODO: What to do if the type definition is missing?
25060 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025061 if (iattr->typeDef == NULL) {
25062 iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025063 continue;
25064 }
25065
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025066 ACTIVATE_ATTRIBUTE(iattr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000025067 fixed = 0;
25068 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025069
25070 if (vctxt->xpathStates != NULL) {
25071 /*
25072 * Evaluate IDCs.
25073 */
25074 xpathRes = xmlSchemaXPathEvaluate(vctxt,
25075 XML_ATTRIBUTE_NODE);
25076 if (xpathRes == -1) {
25077 VERROR_INT("xmlSchemaVAttributesComplex",
25078 "calling xmlSchemaXPathEvaluate()");
25079 goto internal_error;
25080 }
25081 }
25082
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025083 if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025084 /*
25085 * Default/fixed attributes.
25086 */
25087 if (xpathRes) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025088 if (iattr->use->defValue != NULL) {
25089 iattr->value = (xmlChar *) iattr->use->defValue;
25090 iattr->val = iattr->use->defVal;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025091 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025092 iattr->value = (xmlChar *) iattr->decl->defValue;
25093 iattr->val = iattr->decl->defVal;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025094 }
25095 /*
25096 * IDCs will consume the precomputed default value,
25097 * so we need to clone it.
25098 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025099 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025100 VERROR_INT("xmlSchemaVAttributesComplex",
25101 "default/fixed value on an attribute use was "
25102 "not precomputed");
25103 goto internal_error;
25104 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025105 iattr->val = xmlSchemaCopyValue(iattr->val);
25106 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025107 VERROR_INT("xmlSchemaVAttributesComplex",
25108 "calling xmlSchemaCopyValue()");
25109 goto internal_error;
25110 }
25111 }
25112 /*
25113 * PSVI: Add the default attribute to the current element.
25114 * VAL TODO: Should we use the *normalized* value? This currently
25115 * uses the *initial* value.
25116 */
25117 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025118 (iattr->node != NULL) && (iattr->node->doc != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025119 xmlChar *normValue;
25120 const xmlChar *value;
25121
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025122 value = iattr->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025123 /*
25124 * Normalize the value.
25125 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025126 normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25127 iattr->value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025128 if (normValue != NULL)
25129 value = BAD_CAST normValue;
25130
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025131 if (iattr->nsName == NULL) {
25132 if (xmlNewProp(iattr->node->parent,
25133 iattr->localName, value) == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025134 VERROR_INT("xmlSchemaVAttributesComplex",
25135 "callling xmlNewProp()");
25136 if (normValue != NULL)
25137 xmlFree(normValue);
25138 goto internal_error;
25139 }
25140 } else {
25141 xmlNsPtr ns;
25142
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025143 ns = xmlSearchNsByHref(iattr->node->doc,
25144 iattr->node->parent, iattr->nsName);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025145 if (ns == NULL) {
25146 xmlChar prefix[12];
25147 int counter = 0;
25148
25149 /*
25150 * Create a namespace declaration on the validation
25151 * root node if no namespace declaration is in scope.
25152 */
25153 do {
25154 snprintf((char *) prefix, 12, "p%d", counter++);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025155 ns = xmlSearchNs(iattr->node->doc,
25156 iattr->node->parent, BAD_CAST prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025157 if (counter > 1000) {
25158 VERROR_INT(
25159 "xmlSchemaVAttributesComplex",
25160 "could not compute a ns prefix for a "
25161 "default/fixed attribute");
25162 if (normValue != NULL)
25163 xmlFree(normValue);
25164 goto internal_error;
25165 }
25166 } while (ns != NULL);
25167 ns = xmlNewNs(vctxt->validationRoot,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025168 iattr->nsName, BAD_CAST prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025169 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025170 /*
25171 * TODO:
25172 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25173 * If we have QNames: do we need to ensure there's a
25174 * prefix defined for the QName?
25175 */
25176 xmlNewNsProp(iattr->node->parent, ns,
25177 iattr->localName, value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025178 }
25179 if (normValue != NULL)
25180 xmlFree(normValue);
25181 }
25182 /*
25183 * Go directly to IDC evaluation.
25184 */
25185 goto eval_idcs;
25186 }
25187 /*
25188 * Validate the value.
25189 */
25190 if (vctxt->value != NULL) {
25191 /*
25192 * Free last computed value; just for safety reasons.
25193 */
25194 xmlSchemaFreeValue(vctxt->value);
25195 vctxt->value = NULL;
25196 }
25197 /*
25198 * Note that the attribute *use* can be unavailable, if
25199 * the attribute was a wild attribute.
25200 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025201 if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25202 ((iattr->use != NULL) &&
25203 (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025204 fixed = 1;
25205 else
25206 fixed = 0;
25207 /*
25208 * SPEC (cvc-attribute)
25209 * (3) "The item's ·normalized value· must be locally ·valid·
25210 * with respect to that {type definition} as per
25211 * String Valid (§3.14.4)."
25212 *
25213 * VAL TODO: Do we already have the
25214 * "normalized attribute value" here?
25215 */
25216 if (xpathRes || fixed) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025217 iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025218 /*
25219 * Request a computed value.
25220 */
25221 res = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025222 ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025223 iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025224 1, 1, 0);
25225 } else {
25226 res = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025227 ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025228 iattr->node, iattr->typeDef, iattr->value, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025229 1, 0, 0);
25230 }
25231
25232 if (res != 0) {
25233 if (res == -1) {
25234 VERROR_INT("xmlSchemaVAttributesComplex",
25235 "calling xmlSchemaStreamValidateSimpleTypeValue()");
25236 goto internal_error;
25237 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025238 iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025239 /*
25240 * SPEC PSVI Assessment Outcome (Attribute)
25241 * [validity] = "invalid"
25242 */
25243 goto eval_idcs;
25244 }
25245
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025246 if (fixed) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025247 /*
25248 * SPEC Attribute Locally Valid (Use) (cvc-au)
25249 * "For an attribute information item to be·valid·
25250 * with respect to an attribute use its *normalized*
25251 * value· must match the *canonical* lexical
25252 * representation of the attribute use's {value
25253 * constraint}value, if it is present and fixed."
25254 *
25255 * VAL TODO: The requirement for the *canonical* value
25256 * will be removed in XML Schema 1.1.
25257 */
25258 /*
25259 * SPEC Attribute Locally Valid (cvc-attribute)
25260 * (4) "The item's *actual* value· must match the *value* of
25261 * the {value constraint}, if it is present and fixed."
25262 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025263 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025264 /* VAL TODO: A value was not precomputed. */
25265 TODO
25266 goto eval_idcs;
25267 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025268 if ((iattr->use != NULL) &&
25269 (iattr->use->defValue != NULL)) {
25270 if (iattr->use->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025271 /* VAL TODO: A default value was not precomputed. */
25272 TODO
25273 goto eval_idcs;
25274 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025275 iattr->vcValue = iattr->use->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025276 /*
25277 if (xmlSchemaCompareValuesWhtsp(attr->val,
25278 (xmlSchemaWhitespaceValueType) ws,
25279 attr->use->defVal,
25280 (xmlSchemaWhitespaceValueType) ws) != 0) {
25281 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025282 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25283 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025284 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025285 if (iattr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025286 /* VAL TODO: A default value was not precomputed. */
25287 TODO
25288 goto eval_idcs;
25289 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025290 iattr->vcValue = iattr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025291 /*
25292 if (xmlSchemaCompareValuesWhtsp(attr->val,
25293 (xmlSchemaWhitespaceValueType) ws,
25294 attrDecl->defVal,
25295 (xmlSchemaWhitespaceValueType) ws) != 0) {
25296 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025297 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25298 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025299 }
25300 /*
25301 * [validity] = "valid"
25302 */
25303 }
25304eval_idcs:
25305 /*
25306 * Evaluate IDCs.
25307 */
25308 if (xpathRes) {
25309 if (xmlSchemaXPathProcessHistory(vctxt,
25310 vctxt->depth +1) == -1) {
25311 VERROR_INT("xmlSchemaVAttributesComplex",
25312 "calling xmlSchemaXPathEvaluate()");
25313 goto internal_error;
25314 }
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000025315 } else if (vctxt->xpathStates != NULL)
25316 xmlSchemaXPathPop(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025317 }
25318
25319 /*
25320 * Report errors.
25321 */
25322 for (i = 0; i < vctxt->nbAttrInfos; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025323 iattr = vctxt->attrInfos[i];
25324 if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25325 (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25326 (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25327 (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025328 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025329 ACTIVATE_ATTRIBUTE(iattr);
25330 switch (iattr->state) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025331 case XML_SCHEMAS_ATTR_ERR_MISSING: {
25332 xmlChar *str = NULL;
25333 ACTIVATE_ELEM;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025334 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025335 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25336 "The attribute '%s' is required but missing",
25337 xmlSchemaFormatQName(&str,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025338 iattr->decl->targetNamespace,
25339 iattr->decl->name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025340 NULL);
25341 FREE_AND_NULL(str)
25342 break;
25343 }
25344 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25345 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25346 "The type definition is absent");
25347 break;
25348 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025349 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025350 XML_SCHEMAV_CVC_AU, NULL, NULL,
25351 "The value '%s' does not match the fixed "
25352 "value constraint '%s'",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025353 iattr->value, iattr->vcValue);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025354 break;
25355 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25356 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25357 "No matching global attribute declaration available, but "
25358 "demanded by the strict wildcard");
25359 break;
25360 case XML_SCHEMAS_ATTR_UNKNOWN:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025361 if (iattr->metaType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025362 break;
25363 /*
25364 * MAYBE VAL TODO: One might report different error messages
25365 * for the following errors.
25366 */
25367 if (type->attributeWildcard == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025368 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025369 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025370 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025371 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025372 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025373 }
25374 break;
25375 default:
25376 break;
25377 }
25378 }
25379
25380 ACTIVATE_ELEM;
25381 return (0);
25382internal_error:
25383 ACTIVATE_ELEM;
25384 return (-1);
25385}
25386
25387static int
25388xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25389 int *skip)
25390{
25391 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25392 /*
25393 * The namespace of the element was already identified to be
25394 * matching the wildcard.
25395 */
25396 if ((skip == NULL) || (wild == NULL) ||
25397 (wild->type != XML_SCHEMA_TYPE_ANY)) {
25398 VERROR_INT("xmlSchemaValidateElemWildcard",
25399 "bad arguments");
25400 return (-1);
25401 }
25402 *skip = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025403 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25404 /*
25405 * URGENT VAL TODO: Either we need to position the stream to the
25406 * next sibling, or walk the whole subtree.
25407 */
25408 *skip = 1;
25409 return (0);
25410 }
25411 {
25412 xmlSchemaElementPtr decl = NULL;
25413
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025414 decl = xmlSchemaGetElem(vctxt->schema,
25415 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025416 if (decl != NULL) {
25417 vctxt->inode->decl = decl;
25418 return (0);
25419 }
25420 }
25421 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25422 /* VAL TODO: Change to proper error code. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025423 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025424 "No matching global element declaration available, but "
25425 "demanded by the strict wildcard");
25426 return (vctxt->err);
25427 }
25428 if (vctxt->nbAttrInfos != 0) {
25429 xmlSchemaAttrInfoPtr iattr;
25430 /*
25431 * SPEC Validation Rule: Schema-Validity Assessment (Element)
25432 * (1.2.1.2.1) - (1.2.1.2.3 )
25433 *
25434 * Use the xsi:type attribute for the type definition.
25435 */
25436 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25437 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25438 if (iattr != NULL) {
25439 if (xmlSchemaProcessXSIType(vctxt, iattr,
25440 &(vctxt->inode->typeDef), NULL) == -1) {
25441 VERROR_INT("xmlSchemaValidateElemWildcard",
25442 "calling xmlSchemaProcessXSIType() to "
25443 "process the attribute 'xsi:nil'");
25444 return (-1);
25445 }
25446 /*
25447 * Don't return an error on purpose.
25448 */
25449 return (0);
25450 }
25451 }
25452 /*
25453 * SPEC Validation Rule: Schema-Validity Assessment (Element)
25454 *
25455 * Fallback to "anyType".
25456 */
25457 vctxt->inode->typeDef =
25458 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25459 return (0);
25460}
25461
25462/*
25463* xmlSchemaCheckCOSValidDefault:
25464*
25465* This will be called if: not nilled, no content and a default/fixed
25466* value is provided.
25467*/
25468
25469static int
25470xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25471 const xmlChar *value,
25472 xmlSchemaValPtr *val)
25473{
25474 int ret = 0;
25475 xmlSchemaNodeInfoPtr inode = vctxt->inode;
25476
25477 /*
25478 * cos-valid-default:
25479 * Schema Component Constraint: Element Default Valid (Immediate)
25480 * For a string to be a valid default with respect to a type
25481 * definition the appropriate case among the following must be true:
25482 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025483 if WXS_IS_COMPLEX(inode->typeDef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025484 /*
25485 * Complex type.
25486 *
25487 * SPEC (2.1) "its {content type} must be a simple type definition
25488 * or mixed."
25489 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
25490 * type}'s particle must be ·emptiable· as defined by
25491 * Particle Emptiable (§3.9.6)."
25492 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025493 if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25494 ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25495 (! WXS_EMPTIABLE(inode->typeDef)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025496 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25497 /* NOTE that this covers (2.2.2) as well. */
25498 VERROR(ret, NULL,
25499 "For a string to be a valid default, the type definition "
25500 "must be a simple type or a complex type with simple content "
25501 "or mixed content and a particle emptiable");
25502 return(ret);
25503 }
25504 }
25505 /*
25506 * 1 If the type definition is a simple type definition, then the string
25507 * must be ·valid· with respect to that definition as defined by String
25508 * Valid (§3.14.4).
25509 *
25510 * AND
25511 *
25512 * 2.2.1 If the {content type} is a simple type definition, then the
25513 * string must be ·valid· with respect to that simple type definition
25514 * as defined by String Valid (§3.14.4).
25515 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025516 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025517
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025518 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025519 NULL, inode->typeDef, value, val, 1, 1, 0);
25520
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025521 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025522
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025523 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025524 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25525 }
25526 if (ret < 0) {
25527 VERROR_INT("xmlSchemaCheckCOSValidDefault",
25528 "calling xmlSchemaVCheckCVCSimpleType()");
25529 }
25530 return (ret);
25531}
25532
25533static void
25534xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25535 const xmlChar * name ATTRIBUTE_UNUSED,
25536 xmlSchemaElementPtr item,
25537 xmlSchemaNodeInfoPtr inode)
25538{
25539 inode->decl = item;
25540#ifdef DEBUG_CONTENT
25541 {
25542 xmlChar *str = NULL;
25543
25544 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25545 xmlGenericError(xmlGenericErrorContext,
25546 "AUTOMATON callback for '%s' [declaration]\n",
25547 xmlSchemaFormatQName(&str,
25548 inode->localName, inode->nsName));
25549 } else {
25550 xmlGenericError(xmlGenericErrorContext,
25551 "AUTOMATON callback for '%s' [wildcard]\n",
25552 xmlSchemaFormatQName(&str,
25553 inode->localName, inode->nsName));
25554
25555 }
25556 FREE_AND_NULL(str)
25557 }
25558#endif
25559}
25560
25561static int
25562xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000025563{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025564 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25565 if (vctxt->inode == NULL) {
25566 VERROR_INT("xmlSchemaValidatorPushElem",
25567 "calling xmlSchemaGetFreshElemInfo()");
25568 return (-1);
25569 }
25570 vctxt->nbAttrInfos = 0;
25571 return (0);
25572}
25573
25574static int
25575xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25576 xmlSchemaNodeInfoPtr inode,
25577 xmlSchemaTypePtr type,
25578 const xmlChar *value)
25579{
25580 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25581 return (xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025582 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025583 type, value, &(inode->val), 1, 1, 0));
25584 else
25585 return (xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025586 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025587 type, value, NULL, 1, 0, 0));
25588}
25589
25590
25591
25592/*
25593* Process END of element.
25594*/
25595static int
25596xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
25597{
25598 int ret = 0;
25599 xmlSchemaNodeInfoPtr inode = vctxt->inode;
25600
25601 if (vctxt->nbAttrInfos != 0)
25602 xmlSchemaClearAttrInfos(vctxt);
25603 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
25604 /*
25605 * This element was not expected;
25606 * we will not validate child elements of broken parents.
25607 * Skip validation of all content of the parent.
25608 */
25609 vctxt->skipDepth = vctxt->depth -1;
25610 goto end_elem;
25611 }
25612 if ((inode->typeDef == NULL) ||
25613 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
25614 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000025615 * 1. the type definition might be missing if the element was
25616 * error prone
25617 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025618 */
25619 goto end_elem;
25620 }
25621 /*
25622 * Check the content model.
25623 */
25624 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
25625 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
25626
25627 /*
25628 * Workaround for "anyType".
25629 */
25630 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
25631 goto character_content;
25632
25633 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
25634 xmlChar *values[10];
25635 int terminal, nbval = 10, nbneg;
25636
25637 if (inode->regexCtxt == NULL) {
25638 /*
25639 * Create the regex context.
25640 */
25641 inode->regexCtxt =
25642 xmlRegNewExecCtxt(inode->typeDef->contModel,
25643 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
25644 vctxt);
25645 if (inode->regexCtxt == NULL) {
25646 VERROR_INT("xmlSchemaValidatorPopElem",
25647 "failed to create a regex context");
25648 goto internal_error;
25649 }
25650#ifdef DEBUG_AUTOMATA
25651 xmlGenericError(xmlGenericErrorContext,
25652 "AUTOMATON create on '%s'\n", inode->localName);
25653#endif
25654 }
25655 /*
25656 * Get hold of the still expected content, since a further
25657 * call to xmlRegExecPushString() will loose this information.
25658 */
25659 xmlRegExecNextValues(inode->regexCtxt,
25660 &nbval, &nbneg, &values[0], &terminal);
25661 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
25662 if (ret <= 0) {
25663 /*
25664 * Still missing something.
25665 */
25666 ret = 1;
25667 inode->flags |=
25668 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025669 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025670 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
25671 "Missing child element(s)",
25672 nbval, nbneg, values);
25673#ifdef DEBUG_AUTOMATA
25674 xmlGenericError(xmlGenericErrorContext,
25675 "AUTOMATON missing ERROR on '%s'\n",
25676 inode->localName);
25677#endif
25678 } else {
25679 /*
25680 * Content model is satisfied.
25681 */
25682 ret = 0;
25683#ifdef DEBUG_AUTOMATA
25684 xmlGenericError(xmlGenericErrorContext,
25685 "AUTOMATON succeeded on '%s'\n",
25686 inode->localName);
25687#endif
25688 }
25689
25690 }
25691 }
25692 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
25693 goto end_elem;
25694
25695character_content:
25696
25697 if (vctxt->value != NULL) {
25698 xmlSchemaFreeValue(vctxt->value);
25699 vctxt->value = NULL;
25700 }
25701 /*
25702 * Check character content.
25703 */
25704 if (inode->decl == NULL) {
25705 /*
25706 * Speedup if no declaration exists.
25707 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025708 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025709 ret = xmlSchemaVCheckINodeDataType(vctxt,
25710 inode, inode->typeDef, inode->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025711 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025712 ret = xmlSchemaVCheckINodeDataType(vctxt,
25713 inode, inode->typeDef->contentTypeDef,
25714 inode->value);
25715 }
25716 if (ret < 0) {
25717 VERROR_INT("xmlSchemaValidatorPopElem",
25718 "calling xmlSchemaVCheckCVCSimpleType()");
25719 goto internal_error;
25720 }
25721 goto end_elem;
25722 }
25723 /*
25724 * cvc-elt (3.3.4) : 5
25725 * The appropriate case among the following must be true:
25726 */
25727 /*
25728 * cvc-elt (3.3.4) : 5.1
25729 * If the declaration has a {value constraint},
25730 * the item has neither element nor character [children] and
25731 * clause 3.2 has not applied, then all of the following must be true:
25732 */
25733 if ((inode->decl->value != NULL) &&
25734 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
25735 (! INODE_NILLED(inode))) {
25736 /*
25737 * cvc-elt (3.3.4) : 5.1.1
25738 * If the ·actual type definition· is a ·local type definition·
25739 * then the canonical lexical representation of the {value constraint}
25740 * value must be a valid default for the ·actual type definition· as
25741 * defined in Element Default Valid (Immediate) (§3.3.6).
25742 */
25743 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025744 * NOTE: 'local' above means types acquired by xsi:type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025745 * NOTE: Although the *canonical* value is stated, it is not
25746 * relevant if canonical or not. Additionally XML Schema 1.1
25747 * will removed this requirement as well.
25748 */
25749 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
25750
25751 ret = xmlSchemaCheckCOSValidDefault(vctxt,
25752 inode->decl->value, &(inode->val));
25753 if (ret != 0) {
25754 if (ret < 0) {
25755 VERROR_INT("xmlSchemaValidatorPopElem",
25756 "calling xmlSchemaCheckCOSValidDefault()");
25757 goto internal_error;
25758 }
25759 goto end_elem;
25760 }
25761 /*
25762 * Stop here, to avoid redundant validation of the value
25763 * (see following).
25764 */
25765 goto default_psvi;
25766 }
25767 /*
25768 * cvc-elt (3.3.4) : 5.1.2
25769 * The element information item with the canonical lexical
25770 * representation of the {value constraint} value used as its
25771 * ·normalized value· must be ·valid· with respect to the
25772 * ·actual type definition· as defined by Element Locally Valid (Type)
25773 * (§3.3.4).
25774 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025775 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025776 ret = xmlSchemaVCheckINodeDataType(vctxt,
25777 inode, inode->typeDef, inode->decl->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025778 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025779 ret = xmlSchemaVCheckINodeDataType(vctxt,
25780 inode, inode->typeDef->contentTypeDef,
25781 inode->decl->value);
25782 }
25783 if (ret != 0) {
25784 if (ret < 0) {
25785 VERROR_INT("xmlSchemaValidatorPopElem",
25786 "calling xmlSchemaVCheckCVCSimpleType()");
25787 goto internal_error;
25788 }
25789 goto end_elem;
25790 }
25791
25792default_psvi:
25793 /*
25794 * PSVI: Create a text node on the instance element.
25795 */
25796 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
25797 (inode->node != NULL)) {
25798 xmlNodePtr textChild;
25799 xmlChar *normValue;
25800 /*
25801 * VAL TODO: Normalize the value.
25802 */
25803 normValue = xmlSchemaNormalizeValue(inode->typeDef,
25804 inode->decl->value);
25805 if (normValue != NULL) {
25806 textChild = xmlNewText(BAD_CAST normValue);
25807 xmlFree(normValue);
25808 } else
25809 textChild = xmlNewText(inode->decl->value);
25810 if (textChild == NULL) {
25811 VERROR_INT("xmlSchemaValidatorPopElem",
25812 "calling xmlNewText()");
25813 goto internal_error;
25814 } else
25815 xmlAddChild(inode->node, textChild);
25816 }
25817
25818 } else if (! INODE_NILLED(inode)) {
25819 /*
25820 * 5.2.1 The element information item must be ·valid· with respect
25821 * to the ·actual type definition· as defined by Element Locally
25822 * Valid (Type) (§3.3.4).
25823 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025824 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025825 /*
25826 * SPEC (cvc-type) (3.1)
25827 * "If the type definition is a simple type definition, ..."
25828 * (3.1.3) "If clause 3.2 of Element Locally Valid
25829 * (Element) (§3.3.4) did not apply, then the ·normalized value·
25830 * must be ·valid· with respect to the type definition as defined
25831 * by String Valid (§3.14.4).
25832 */
25833 ret = xmlSchemaVCheckINodeDataType(vctxt,
25834 inode, inode->typeDef, inode->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025835 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025836 /*
25837 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
25838 * definition, then the element information item must be
25839 * ·valid· with respect to the type definition as per
25840 * Element Locally Valid (Complex Type) (§3.4.4);"
25841 *
25842 * SPEC (cvc-complex-type) (2.2)
25843 * "If the {content type} is a simple type definition, ...
25844 * the ·normalized value· of the element information item is
25845 * ·valid· with respect to that simple type definition as
25846 * defined by String Valid (§3.14.4)."
25847 */
25848 ret = xmlSchemaVCheckINodeDataType(vctxt,
25849 inode, inode->typeDef->contentTypeDef, inode->value);
25850 }
25851 if (ret != 0) {
25852 if (ret < 0) {
25853 VERROR_INT("xmlSchemaValidatorPopElem",
25854 "calling xmlSchemaVCheckCVCSimpleType()");
25855 goto internal_error;
25856 }
25857 goto end_elem;
25858 }
25859 /*
25860 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
25861 * not applied, all of the following must be true:
25862 */
25863 if ((inode->decl->value != NULL) &&
25864 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
25865
25866 /*
25867 * TODO: We will need a computed value, when comparison is
25868 * done on computed values.
25869 */
25870 /*
25871 * 5.2.2.1 The element information item must have no element
25872 * information item [children].
25873 */
25874 if (inode->flags &
25875 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
25876 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
25877 VERROR(ret, NULL,
25878 "The content must not containt element nodes since "
25879 "there is a fixed value constraint");
25880 goto end_elem;
25881 } else {
25882 /*
25883 * 5.2.2.2 The appropriate case among the following must
25884 * be true:
25885 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025886 if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025887 /*
25888 * 5.2.2.2.1 If the {content type} of the ·actual type
25889 * definition· is mixed, then the *initial value* of the
25890 * item must match the canonical lexical representation
25891 * of the {value constraint} value.
25892 *
25893 * ... the *initial value* of an element information
25894 * item is the string composed of, in order, the
25895 * [character code] of each character information item in
25896 * the [children] of that element information item.
25897 */
25898 if (! xmlStrEqual(inode->value, inode->decl->value)){
25899 /*
25900 * VAL TODO: Report invalid & expected values as well.
25901 * VAL TODO: Implement the canonical stuff.
25902 */
25903 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025904 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025905 ret, NULL, NULL,
25906 "The initial value '%s' does not match the fixed "
25907 "value constraint '%s'",
25908 inode->value, inode->decl->value);
25909 goto end_elem;
25910 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025911 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025912 /*
25913 * 5.2.2.2.2 If the {content type} of the ·actual type
25914 * definition· is a simple type definition, then the
25915 * *actual value* of the item must match the canonical
25916 * lexical representation of the {value constraint} value.
25917 */
25918 /*
25919 * VAL TODO: *actual value* is the normalized value, impl.
25920 * this.
25921 * VAL TODO: Report invalid & expected values as well.
25922 * VAL TODO: Implement a comparison with the computed values.
25923 */
25924 if (! xmlStrEqual(inode->value,
25925 inode->decl->value)) {
25926 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025927 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025928 ret, NULL, NULL,
25929 "The actual value '%s' does not match the fixed "
25930 "value constraint '%s'",
25931 inode->value,
25932 inode->decl->value);
25933 goto end_elem;
25934 }
25935 }
25936 }
25937 }
25938 }
25939
25940end_elem:
25941 if (vctxt->depth < 0) {
25942 /* TODO: raise error? */
25943 return (0);
25944 }
25945 if (vctxt->depth == vctxt->skipDepth)
25946 vctxt->skipDepth = -1;
25947 /*
25948 * Evaluate the history of XPath state objects.
25949 */
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000025950 if (inode->appliedXPath &&
25951 (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025952 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025953 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025954 * MAYBE TODO:
25955 * SPEC (6) "The element information item must be ·valid· with
25956 * respect to each of the {identity-constraint definitions} as per
25957 * Identity-constraint Satisfied (§3.11.4)."
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025958 */
25959 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025960 * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
25961 * need to be built in any case.
25962 * We will currently build IDC node-tables and bubble them only if
25963 * keyrefs do exist.
25964 */
25965
25966 /*
25967 * Add the current IDC target-nodes to the IDC node-tables.
25968 */
25969 if ((inode->idcMatchers != NULL) &&
25970 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
25971 {
25972 if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
25973 goto internal_error;
25974 }
25975 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025976 * Validate IDC keyrefs.
25977 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025978 if (vctxt->inode->hasKeyrefs)
25979 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
25980 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025981 /*
25982 * Merge/free the IDC table.
25983 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025984 if (inode->idcTable != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025985#ifdef DEBUG_IDC_NODE_TABLE
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025986 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025987 inode->nsName,
25988 inode->localName,
25989 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025990#endif
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025991 if ((vctxt->depth > 0) &&
25992 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
25993 {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025994 /*
25995 * Merge the IDC node table with the table of the parent node.
25996 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025997 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
25998 goto internal_error;
25999 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026000 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026001 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026002 * Clear the current ielem.
26003 * VAL TODO: Don't free the PSVI IDC tables if they are
26004 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026005 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026006 xmlSchemaClearElemInfo(inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026007 /*
26008 * Skip further processing if we are on the validation root.
26009 */
26010 if (vctxt->depth == 0) {
26011 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026012 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000026013 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026014 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026015 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026016 * Reset the keyrefDepth if needed.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026017 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026018 if (vctxt->aidcs != NULL) {
26019 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26020 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026021 if (aidc->keyrefDepth == vctxt->depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026022 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026023 * A 'keyrefDepth' of a key/unique IDC matches the current
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026024 * depth, this means that we are leaving the scope of the
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026025 * top-most keyref IDC which refers to this IDC.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026026 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026027 aidc->keyrefDepth = -1;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026028 }
26029 aidc = aidc->next;
26030 } while (aidc != NULL);
26031 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026032 vctxt->depth--;
26033 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000026034 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026035 * VAL TODO: 7 If the element information item is the ·validation root·, it must be
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026036 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
26037 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026038 return (ret);
26039
26040internal_error:
26041 vctxt->err = -1;
26042 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000026043}
26044
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026045/*
26046* 3.4.4 Complex Type Definition Validation Rules
26047* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26048*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000026049static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026050xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000026051{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026052 xmlSchemaNodeInfoPtr pielem;
26053 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000026054 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000026055
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026056 if (vctxt->depth <= 0) {
26057 VERROR_INT("xmlSchemaValidateChildElem",
26058 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026059 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026060 }
26061 pielem = vctxt->elemInfos[vctxt->depth -1];
26062 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26063 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026064 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026065 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026066 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026067 if (INODE_NILLED(pielem)) {
26068 /*
26069 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
26070 */
26071 ACTIVATE_PARENT_ELEM;
26072 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26073 VERROR(ret, NULL,
26074 "Neither character nor element content is allowed, "
26075 "because the element was 'nilled'");
26076 ACTIVATE_ELEM;
26077 goto unexpected_elem;
26078 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026079
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026080 ptype = pielem->typeDef;
26081
26082 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26083 /*
26084 * Workaround for "anyType": we have currently no content model
26085 * assigned for "anyType", so handle it explicitely.
26086 * "anyType" has an unbounded, lax "any" wildcard.
26087 */
26088 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26089 vctxt->inode->localName,
26090 vctxt->inode->nsName);
26091
26092 if (vctxt->inode->decl == NULL) {
26093 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026094 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026095 * Process "xsi:type".
26096 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026097 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026098 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26099 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26100 if (iattr != NULL) {
26101 ret = xmlSchemaProcessXSIType(vctxt, iattr,
26102 &(vctxt->inode->typeDef), NULL);
26103 if (ret != 0) {
26104 if (ret == -1) {
26105 VERROR_INT("xmlSchemaValidateChildElem",
26106 "calling xmlSchemaProcessXSIType() to "
26107 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000026108 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000026109 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026110 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000026111 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026112 } else {
26113 /*
26114 * Fallback to "anyType".
26115 *
26116 * SPEC (cvc-assess-elt)
26117 * "If the item cannot be ·strictly assessed·, [...]
26118 * an element information item's schema validity may be laxly
26119 * assessed if its ·context-determined declaration· is not
26120 * skip by ·validating· with respect to the ·ur-type
26121 * definition· as per Element Locally Valid (Type) (§3.3.4)."
26122 */
26123 vctxt->inode->typeDef =
26124 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026125 }
26126 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026127 return (0);
26128 }
26129
26130 switch (ptype->contentType) {
26131 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026132 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026133 * SPEC (2.1) "If the {content type} is empty, then the
26134 * element information item has no character or element
26135 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026136 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026137 ACTIVATE_PARENT_ELEM
26138 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26139 VERROR(ret, NULL,
26140 "Element content is not allowed, "
26141 "because the content type is empty");
26142 ACTIVATE_ELEM
26143 goto unexpected_elem;
26144 break;
26145
26146 case XML_SCHEMA_CONTENT_MIXED:
26147 case XML_SCHEMA_CONTENT_ELEMENTS: {
26148 xmlRegExecCtxtPtr regexCtxt;
26149 xmlChar *values[10];
26150 int terminal, nbval = 10, nbneg;
26151
26152 /* VAL TODO: Optimized "anyType" validation.*/
26153
26154 if (ptype->contModel == NULL) {
26155 VERROR_INT("xmlSchemaValidateChildElem",
26156 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026157 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000026158 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026159 /*
26160 * Safety belf for evaluation if the cont. model was already
26161 * examined to be invalid.
26162 */
26163 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26164 VERROR_INT("xmlSchemaValidateChildElem",
26165 "validating elem, but elem content is already invalid");
26166 return (-1);
26167 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000026168
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026169 regexCtxt = pielem->regexCtxt;
26170 if (regexCtxt == NULL) {
26171 /*
26172 * Create the regex context.
26173 */
26174 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26175 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26176 vctxt);
26177 if (regexCtxt == NULL) {
26178 VERROR_INT("xmlSchemaValidateChildElem",
26179 "failed to create a regex context");
26180 return (-1);
26181 }
26182 pielem->regexCtxt = regexCtxt;
26183#ifdef DEBUG_AUTOMATA
26184 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26185 pielem->localName);
26186#endif
26187 }
26188
26189 /*
26190 * SPEC (2.4) "If the {content type} is element-only or mixed,
26191 * then the sequence of the element information item's
26192 * element information item [children], if any, taken in
26193 * order, is ·valid· with respect to the {content type}'s
26194 * particle, as defined in Element Sequence Locally Valid
26195 * (Particle) (§3.9.4)."
26196 */
26197 ret = xmlRegExecPushString2(regexCtxt,
26198 vctxt->inode->localName,
26199 vctxt->inode->nsName,
26200 vctxt->inode);
26201#ifdef DEBUG_AUTOMATA
26202 if (ret < 0)
26203 xmlGenericError(xmlGenericErrorContext,
26204 "AUTOMATON push ERROR for '%s' on '%s'\n",
26205 vctxt->inode->localName, pielem->localName);
26206 else
26207 xmlGenericError(xmlGenericErrorContext,
26208 "AUTOMATON push OK for '%s' on '%s'\n",
26209 vctxt->inode->localName, pielem->localName);
26210#endif
26211 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26212 VERROR_INT("xmlSchemaValidateChildElem",
26213 "calling xmlRegExecPushString2()");
26214 return (-1);
26215 }
26216 if (ret < 0) {
26217 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26218 &values[0], &terminal);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026219 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026220 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26221 "This element is not expected",
26222 nbval, nbneg, values);
26223 ret = vctxt->err;
26224 goto unexpected_elem;
26225 } else
26226 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000026227 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026228 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026229 case XML_SCHEMA_CONTENT_SIMPLE:
26230 case XML_SCHEMA_CONTENT_BASIC:
26231 ACTIVATE_PARENT_ELEM
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026232 if (WXS_IS_COMPLEX(ptype)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026233 /*
26234 * SPEC (cvc-complex-type) (2.2)
26235 * "If the {content type} is a simple type definition, then
26236 * the element information item has no element information
26237 * item [children], ..."
26238 */
26239 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26240 VERROR(ret, NULL, "Element content is not allowed, "
26241 "because the content type is a simple type definition");
26242 } else {
26243 /*
26244 * SPEC (cvc-type) (3.1.2) "The element information item must
26245 * have no element information item [children]."
26246 */
26247 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26248 VERROR(ret, NULL, "Element content is not allowed, "
26249 "because the type definition is simple");
26250 }
26251 ACTIVATE_ELEM
26252 ret = vctxt->err;
26253 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026254 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026255
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026256 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026257 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026258 }
26259 return (ret);
26260unexpected_elem:
26261 /*
26262 * Pop this element and set the skipDepth to skip
26263 * all further content of the parent element.
26264 */
26265 vctxt->skipDepth = vctxt->depth;
26266 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26267 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26268 return (ret);
26269}
26270
26271#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26272#define XML_SCHEMA_PUSH_TEXT_CREATED 2
26273#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26274
26275static int
26276xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26277 int nodeType, const xmlChar *value, int len,
26278 int mode, int *consumed)
26279{
26280 /*
26281 * Unfortunately we have to duplicate the text sometimes.
26282 * OPTIMIZE: Maybe we could skip it, if:
26283 * 1. content type is simple
26284 * 2. whitespace is "collapse"
26285 * 3. it consists of whitespace only
26286 *
26287 * Process character content.
26288 */
26289 if (consumed != NULL)
26290 *consumed = 0;
26291 if (INODE_NILLED(vctxt->inode)) {
26292 /*
26293 * SPEC cvc-elt (3.3.4 - 3.2.1)
26294 * "The element information item must have no character or
26295 * element information item [children]."
26296 */
26297 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26298 "Neither character nor element content is allowed "
26299 "because the element is 'nilled'");
26300 return (vctxt->err);
26301 }
26302 /*
26303 * SPEC (2.1) "If the {content type} is empty, then the
26304 * element information item has no character or element
26305 * information item [children]."
26306 */
26307 if (vctxt->inode->typeDef->contentType ==
26308 XML_SCHEMA_CONTENT_EMPTY) {
26309 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26310 "Character content is not allowed, "
26311 "because the content type is empty");
26312 return (vctxt->err);
26313 }
26314
26315 if (vctxt->inode->typeDef->contentType ==
26316 XML_SCHEMA_CONTENT_ELEMENTS) {
26317 if ((nodeType != XML_TEXT_NODE) ||
26318 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26319 /*
26320 * SPEC cvc-complex-type (2.3)
26321 * "If the {content type} is element-only, then the
26322 * element information item has no character information
26323 * item [children] other than those whose [character
26324 * code] is defined as a white space in [XML 1.0 (Second
26325 * Edition)]."
26326 */
26327 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26328 "Character content other than whitespace is not allowed "
26329 "because the content type is 'element-only'");
26330 return (vctxt->err);
26331 }
26332 return (0);
26333 }
26334
26335 if ((value == NULL) || (value[0] == 0))
26336 return (0);
26337 /*
26338 * Save the value.
26339 * NOTE that even if the content type is *mixed*, we need the
26340 * *initial value* for default/fixed value constraints.
26341 */
26342 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26343 ((vctxt->inode->decl == NULL) ||
26344 (vctxt->inode->decl->value == NULL)))
26345 return (0);
26346
26347 if (vctxt->inode->value == NULL) {
26348 /*
26349 * Set the value.
26350 */
26351 switch (mode) {
26352 case XML_SCHEMA_PUSH_TEXT_PERSIST:
26353 /*
26354 * When working on a tree.
26355 */
26356 vctxt->inode->value = value;
26357 break;
26358 case XML_SCHEMA_PUSH_TEXT_CREATED:
26359 /*
26360 * When working with the reader.
26361 * The value will be freed by the element info.
26362 */
26363 vctxt->inode->value = value;
26364 if (consumed != NULL)
26365 *consumed = 1;
26366 vctxt->inode->flags |=
26367 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26368 break;
26369 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26370 /*
26371 * When working with SAX.
26372 * The value will be freed by the element info.
26373 */
26374 if (len != -1)
26375 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26376 else
26377 vctxt->inode->value = BAD_CAST xmlStrdup(value);
26378 vctxt->inode->flags |=
26379 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26380 break;
26381 default:
26382 break;
26383 }
Kasimier T. Buchcik5bb0c082005-12-20 10:48:33 +000026384 } else {
26385 if (len < 0)
26386 len = xmlStrlen(value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026387 /*
26388 * Concat the value.
26389 */
26390 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000026391 vctxt->inode->value = BAD_CAST xmlStrncat(
26392 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026393 } else {
26394 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026395 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026396 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26397 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026398 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026399
26400 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000026401}
26402
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026403static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026404xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000026405{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026406 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000026407
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026408 if ((vctxt->skipDepth != -1) &&
26409 (vctxt->depth >= vctxt->skipDepth)) {
26410 VERROR_INT("xmlSchemaValidateElem",
26411 "in skip-state");
26412 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026413 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026414 if (vctxt->xsiAssemble) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026415 /*
Kasimier T. Buchcik215406f2005-12-07 12:14:09 +000026416 * We will stop validation if there was an error during
26417 * dynamic schema construction.
26418 * Note that we simply set @skipDepth to 0, this could
26419 * mean that a streaming document via SAX would be
26420 * still read to the end but it won't be validated any more.
26421 * TODO: If we are sure how to stop the validation at once
26422 * for all input scenarios, then this should be changed to
26423 * instantly stop the validation.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026424 */
Kasimier T. Buchcik215406f2005-12-07 12:14:09 +000026425 ret = xmlSchemaAssembleByXSI(vctxt);
26426 if (ret != 0) {
26427 if (ret == -1)
26428 goto internal_error;
26429 vctxt->skipDepth = 0;
26430 return(ret);
26431 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026432 }
26433 if (vctxt->depth > 0) {
26434 /*
26435 * Validate this element against the content model
26436 * of the parent.
26437 */
26438 ret = xmlSchemaValidateChildElem(vctxt);
26439 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026440 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026441 VERROR_INT("xmlSchemaValidateElem",
26442 "calling xmlSchemaStreamValidateChildElement()");
26443 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026444 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026445 goto exit;
26446 }
26447 if (vctxt->depth == vctxt->skipDepth)
26448 goto exit;
26449 if ((vctxt->inode->decl == NULL) &&
26450 (vctxt->inode->typeDef == NULL)) {
26451 VERROR_INT("xmlSchemaValidateElem",
26452 "the child element was valid but neither the "
26453 "declaration nor the type was set");
26454 goto internal_error;
26455 }
26456 } else {
26457 /*
26458 * Get the declaration of the validation root.
26459 */
26460 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26461 vctxt->inode->localName,
26462 vctxt->inode->nsName);
26463 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026464 ret = XML_SCHEMAV_CVC_ELT_1;
26465 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026466 "No matching global declaration available "
26467 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026468 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026469 }
26470 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026471
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026472 if (vctxt->inode->decl == NULL)
26473 goto type_validation;
26474
26475 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26476 int skip;
26477 /*
26478 * Wildcards.
26479 */
26480 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26481 if (ret != 0) {
26482 if (ret < 0) {
26483 VERROR_INT("xmlSchemaValidateElem",
26484 "calling xmlSchemaValidateElemWildcard()");
26485 goto internal_error;
26486 }
26487 goto exit;
26488 }
26489 if (skip) {
26490 vctxt->skipDepth = vctxt->depth;
26491 goto exit;
26492 }
26493 /*
26494 * The declaration might be set by the wildcard validation,
26495 * when the processContents is "lax" or "strict".
26496 */
26497 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26498 /*
26499 * Clear the "decl" field to not confuse further processing.
26500 */
26501 vctxt->inode->decl = NULL;
26502 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026503 }
Daniel Veillard4255d502002-04-16 15:50:10 +000026504 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026505 /*
26506 * Validate against the declaration.
26507 */
26508 ret = xmlSchemaValidateElemDecl(vctxt);
26509 if (ret != 0) {
26510 if (ret < 0) {
26511 VERROR_INT("xmlSchemaValidateElem",
26512 "calling xmlSchemaValidateElemDecl()");
26513 goto internal_error;
26514 }
26515 goto exit;
26516 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026517 /*
26518 * Validate against the type definition.
26519 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026520type_validation:
26521
26522 if (vctxt->inode->typeDef == NULL) {
26523 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26524 ret = XML_SCHEMAV_CVC_TYPE_1;
26525 VERROR(ret, NULL,
26526 "The type definition is absent");
26527 goto exit;
26528 }
26529 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26530 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26531 ret = XML_SCHEMAV_CVC_TYPE_2;
26532 VERROR(ret, NULL,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026533 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026534 goto exit;
26535 }
26536 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026537 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026538 * during validation against the declaration. This must be done
26539 * _before_ attribute validation.
26540 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026541 if (vctxt->xpathStates != NULL) {
26542 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000026543 vctxt->inode->appliedXPath = 1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026544 if (ret == -1) {
26545 VERROR_INT("xmlSchemaValidateElem",
26546 "calling xmlSchemaXPathEvaluate()");
26547 goto internal_error;
26548 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026549 }
26550 /*
26551 * Validate attributes.
26552 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026553 if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026554 if ((vctxt->nbAttrInfos != 0) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026555 (vctxt->inode->typeDef->attrUses != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026556
26557 ret = xmlSchemaVAttributesComplex(vctxt);
26558 }
26559 } else if (vctxt->nbAttrInfos != 0) {
26560
26561 ret = xmlSchemaVAttributesSimple(vctxt);
26562 }
26563 /*
26564 * Clear registered attributes.
26565 */
26566 if (vctxt->nbAttrInfos != 0)
26567 xmlSchemaClearAttrInfos(vctxt);
26568 if (ret == -1) {
26569 VERROR_INT("xmlSchemaValidateElem",
26570 "calling attributes validation");
26571 goto internal_error;
26572 }
26573 /*
26574 * Don't return an error if attributes are invalid on purpose.
26575 */
26576 ret = 0;
26577
26578exit:
26579 if (ret != 0)
26580 vctxt->skipDepth = vctxt->depth;
26581 return (ret);
26582internal_error:
26583 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000026584}
26585
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026586#ifdef XML_SCHEMA_READER_ENABLED
26587static int
26588xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000026589{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026590 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
26591 int depth, nodeType, ret = 0, consumed;
26592 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000026593
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026594 vctxt->depth = -1;
26595 ret = xmlTextReaderRead(vctxt->reader);
26596 /*
26597 * Move to the document element.
26598 */
26599 while (ret == 1) {
26600 nodeType = xmlTextReaderNodeType(vctxt->reader);
26601 if (nodeType == XML_ELEMENT_NODE)
26602 goto root_found;
26603 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026604 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026605 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026606
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026607root_found:
26608
26609 do {
26610 depth = xmlTextReaderDepth(vctxt->reader);
26611 nodeType = xmlTextReaderNodeType(vctxt->reader);
26612
26613 if (nodeType == XML_ELEMENT_NODE) {
26614
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026615 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026616 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26617 VERROR_INT("xmlSchemaVReaderWalk",
26618 "calling xmlSchemaValidatorPushElem()");
26619 goto internal_error;
26620 }
26621 ielem = vctxt->inode;
26622 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
26623 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
26624 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
26625 /*
26626 * Is the element empty?
26627 */
26628 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
26629 if (ret == -1) {
26630 VERROR_INT("xmlSchemaVReaderWalk",
26631 "calling xmlTextReaderIsEmptyElement()");
26632 goto internal_error;
26633 }
26634 if (ret) {
26635 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26636 }
26637 /*
26638 * Register attributes.
26639 */
26640 vctxt->nbAttrInfos = 0;
26641 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
26642 if (ret == -1) {
26643 VERROR_INT("xmlSchemaVReaderWalk",
26644 "calling xmlTextReaderMoveToFirstAttribute()");
26645 goto internal_error;
26646 }
26647 if (ret == 1) {
26648 do {
26649 /*
26650 * VAL TODO: How do we know that the reader works on a
26651 * node tree, to be able to pass a node here?
26652 */
26653 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
26654 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
26655 xmlTextReaderNamespaceUri(vctxt->reader), 1,
26656 xmlTextReaderValue(vctxt->reader), 1) == -1) {
26657
26658 VERROR_INT("xmlSchemaVReaderWalk",
26659 "calling xmlSchemaValidatorPushAttribute()");
26660 goto internal_error;
26661 }
26662 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
26663 if (ret == -1) {
26664 VERROR_INT("xmlSchemaVReaderWalk",
26665 "calling xmlTextReaderMoveToFirstAttribute()");
26666 goto internal_error;
26667 }
26668 } while (ret == 1);
26669 /*
26670 * Back to element position.
26671 */
26672 ret = xmlTextReaderMoveToElement(vctxt->reader);
26673 if (ret == -1) {
26674 VERROR_INT("xmlSchemaVReaderWalk",
26675 "calling xmlTextReaderMoveToElement()");
26676 goto internal_error;
26677 }
26678 }
26679 /*
26680 * Validate the element.
26681 */
26682 ret= xmlSchemaValidateElem(vctxt);
26683 if (ret != 0) {
26684 if (ret == -1) {
26685 VERROR_INT("xmlSchemaVReaderWalk",
26686 "calling xmlSchemaValidateElem()");
26687 goto internal_error;
26688 }
26689 goto exit;
26690 }
26691 if (vctxt->depth == vctxt->skipDepth) {
26692 int curDepth;
26693 /*
26694 * Skip all content.
26695 */
26696 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
26697 ret = xmlTextReaderRead(vctxt->reader);
26698 curDepth = xmlTextReaderDepth(vctxt->reader);
26699 while ((ret == 1) && (curDepth != depth)) {
26700 ret = xmlTextReaderRead(vctxt->reader);
26701 curDepth = xmlTextReaderDepth(vctxt->reader);
26702 }
26703 if (ret < 0) {
26704 /*
26705 * VAL TODO: A reader error occured; what to do here?
26706 */
26707 ret = 1;
26708 goto exit;
26709 }
26710 }
26711 goto leave_elem;
26712 }
26713 /*
26714 * READER VAL TODO: Is an END_ELEM really never called
26715 * if the elem is empty?
26716 */
26717 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26718 goto leave_elem;
26719 } else if (nodeType == END_ELEM) {
26720 /*
26721 * Process END of element.
26722 */
26723leave_elem:
26724 ret = xmlSchemaValidatorPopElem(vctxt);
26725 if (ret != 0) {
26726 if (ret < 0) {
26727 VERROR_INT("xmlSchemaVReaderWalk",
26728 "calling xmlSchemaValidatorPopElem()");
26729 goto internal_error;
26730 }
26731 goto exit;
26732 }
26733 if (vctxt->depth >= 0)
26734 ielem = vctxt->inode;
26735 else
26736 ielem = NULL;
26737 } else if ((nodeType == XML_TEXT_NODE) ||
26738 (nodeType == XML_CDATA_SECTION_NODE) ||
26739 (nodeType == WHTSP) ||
26740 (nodeType == SIGN_WHTSP)) {
26741 /*
26742 * Process character content.
26743 */
26744 xmlChar *value;
26745
26746 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
26747 nodeType = XML_TEXT_NODE;
26748
26749 value = xmlTextReaderValue(vctxt->reader);
26750 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
26751 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
26752 if (! consumed)
26753 xmlFree(value);
26754 if (ret == -1) {
26755 VERROR_INT("xmlSchemaVReaderWalk",
26756 "calling xmlSchemaVPushText()");
26757 goto internal_error;
26758 }
26759 } else if ((nodeType == XML_ENTITY_NODE) ||
26760 (nodeType == XML_ENTITY_REF_NODE)) {
26761 /*
26762 * VAL TODO: What to do with entities?
26763 */
26764 TODO
26765 }
26766 /*
26767 * Read next node.
26768 */
26769 ret = xmlTextReaderRead(vctxt->reader);
26770 } while (ret == 1);
26771
26772exit:
26773 return (ret);
26774internal_error:
26775 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000026776}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026777#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000026778
26779/************************************************************************
26780 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026781 * SAX validation handlers *
Daniel Veillard4255d502002-04-16 15:50:10 +000026782 * *
26783 ************************************************************************/
26784
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026785/*
26786* Process text content.
26787*/
26788static void
26789xmlSchemaSAXHandleText(void *ctx,
26790 const xmlChar * ch,
26791 int len)
26792{
26793 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26794
26795 if (vctxt->depth < 0)
26796 return;
26797 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26798 return;
26799 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26800 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26801 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
26802 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
26803 VERROR_INT("xmlSchemaSAXHandleCDataSection",
26804 "calling xmlSchemaVPushText()");
26805 vctxt->err = -1;
26806 xmlStopParser(vctxt->parserCtxt);
26807 }
26808}
26809
26810/*
26811* Process CDATA content.
26812*/
26813static void
26814xmlSchemaSAXHandleCDataSection(void *ctx,
26815 const xmlChar * ch,
26816 int len)
26817{
26818 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26819
26820 if (vctxt->depth < 0)
26821 return;
26822 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26823 return;
26824 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26825 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26826 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
26827 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
26828 VERROR_INT("xmlSchemaSAXHandleCDataSection",
26829 "calling xmlSchemaVPushText()");
26830 vctxt->err = -1;
26831 xmlStopParser(vctxt->parserCtxt);
26832 }
26833}
26834
26835static void
26836xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
26837 const xmlChar * name ATTRIBUTE_UNUSED)
26838{
26839 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26840
26841 if (vctxt->depth < 0)
26842 return;
26843 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26844 return;
26845 /* SAX VAL TODO: What to do here? */
26846 TODO
26847}
26848
26849static void
26850xmlSchemaSAXHandleStartElementNs(void *ctx,
26851 const xmlChar * localname,
26852 const xmlChar * prefix ATTRIBUTE_UNUSED,
26853 const xmlChar * URI,
26854 int nb_namespaces,
26855 const xmlChar ** namespaces,
26856 int nb_attributes,
26857 int nb_defaulted ATTRIBUTE_UNUSED,
26858 const xmlChar ** attributes)
26859{
26860 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26861 int ret;
26862 xmlSchemaNodeInfoPtr ielem;
26863 int i, j;
26864
26865 /*
26866 * SAX VAL TODO: What to do with nb_defaulted?
26867 */
26868 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026869 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026870 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026871 vctxt->depth++;
26872 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026873 return;
26874 /*
26875 * Push the element.
26876 */
26877 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26878 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26879 "calling xmlSchemaValidatorPushElem()");
26880 goto internal_error;
26881 }
26882 ielem = vctxt->inode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026883 /*
26884 * TODO: Is this OK?
26885 */
26886 ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026887 ielem->localName = localname;
26888 ielem->nsName = URI;
26889 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26890 /*
26891 * Register namespaces on the elem info.
26892 */
26893 if (nb_namespaces != 0) {
26894 /*
26895 * Although the parser builds its own namespace list,
26896 * we have no access to it, so we'll use an own one.
26897 */
26898 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
26899 /*
26900 * Store prefix and namespace name.
26901 */
26902 if (ielem->nsBindings == NULL) {
26903 ielem->nsBindings =
26904 (const xmlChar **) xmlMalloc(10 *
26905 sizeof(const xmlChar *));
26906 if (ielem->nsBindings == NULL) {
26907 xmlSchemaVErrMemory(vctxt,
26908 "allocating namespace bindings for SAX validation",
26909 NULL);
26910 goto internal_error;
26911 }
26912 ielem->nbNsBindings = 0;
26913 ielem->sizeNsBindings = 5;
26914 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
26915 ielem->sizeNsBindings *= 2;
26916 ielem->nsBindings =
26917 (const xmlChar **) xmlRealloc(
26918 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026919 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026920 if (ielem->nsBindings == NULL) {
26921 xmlSchemaVErrMemory(vctxt,
26922 "re-allocating namespace bindings for SAX validation",
26923 NULL);
26924 goto internal_error;
26925 }
26926 }
26927
26928 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
26929 if (namespaces[j+1][0] == 0) {
26930 /*
26931 * Handle xmlns="".
26932 */
26933 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
26934 } else
26935 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
26936 namespaces[j+1];
26937 ielem->nbNsBindings++;
26938 }
26939 }
26940 /*
26941 * Register attributes.
26942 * SAX VAL TODO: We are not adding namespace declaration
26943 * attributes yet.
26944 */
26945 if (nb_attributes != 0) {
26946 xmlChar *value;
26947
26948 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
26949 /*
26950 * Duplicate the value.
26951 */
26952 value = xmlStrndup(attributes[j+3],
26953 attributes[j+4] - attributes[j+3]);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026954 /*
26955 * TODO: Set the node line.
26956 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026957 ret = xmlSchemaValidatorPushAttribute(vctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026958 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026959 value, 1);
26960 if (ret == -1) {
26961 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26962 "calling xmlSchemaValidatorPushAttribute()");
26963 goto internal_error;
26964 }
26965 }
26966 }
26967 /*
26968 * Validate the element.
26969 */
26970 ret = xmlSchemaValidateElem(vctxt);
26971 if (ret != 0) {
26972 if (ret == -1) {
26973 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26974 "calling xmlSchemaValidateElem()");
26975 goto internal_error;
26976 }
26977 goto exit;
26978 }
26979
26980exit:
26981 return;
26982internal_error:
26983 vctxt->err = -1;
26984 xmlStopParser(vctxt->parserCtxt);
26985 return;
26986}
26987
26988static void
26989xmlSchemaSAXHandleEndElementNs(void *ctx,
26990 const xmlChar * localname ATTRIBUTE_UNUSED,
26991 const xmlChar * prefix ATTRIBUTE_UNUSED,
26992 const xmlChar * URI ATTRIBUTE_UNUSED)
26993{
26994 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26995 int res;
26996
26997 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026998 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026999 */
27000 if (vctxt->skipDepth != -1) {
27001 if (vctxt->depth > vctxt->skipDepth) {
27002 vctxt->depth--;
27003 return;
27004 } else
27005 vctxt->skipDepth = -1;
27006 }
27007 /*
27008 * SAX VAL TODO: Just a temporary check.
27009 */
27010 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27011 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
27012 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27013 "elem pop mismatch");
27014 }
27015 res = xmlSchemaValidatorPopElem(vctxt);
27016 if (res != 0) {
27017 if (res < 0) {
27018 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27019 "calling xmlSchemaValidatorPopElem()");
27020 goto internal_error;
27021 }
27022 goto exit;
27023 }
27024exit:
27025 return;
27026internal_error:
27027 vctxt->err = -1;
27028 xmlStopParser(vctxt->parserCtxt);
27029 return;
27030}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027031
Daniel Veillard4255d502002-04-16 15:50:10 +000027032/************************************************************************
27033 * *
27034 * Validation interfaces *
27035 * *
27036 ************************************************************************/
27037
27038/**
27039 * xmlSchemaNewValidCtxt:
27040 * @schema: a precompiled XML Schemas
27041 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027042 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000027043 *
27044 * Returns the validation context or NULL in case of error
27045 */
27046xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027047xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27048{
Daniel Veillard4255d502002-04-16 15:50:10 +000027049 xmlSchemaValidCtxtPtr ret;
27050
27051 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27052 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027053 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000027054 return (NULL);
27055 }
27056 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027057 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027058 ret->dict = xmlDictCreate();
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000027059 ret->nodeQNames = xmlSchemaItemListCreate();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027060 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000027061 return (ret);
27062}
27063
27064/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027065 * xmlSchemaClearValidCtxt:
27066 * @ctxt: the schema validation context
27067 *
27068 * Free the resources associated to the schema validation context;
27069 * leaves some fields alive intended for reuse of the context.
27070 */
27071static void
27072xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27073{
27074 if (vctxt == NULL)
27075 return;
27076
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027077 /*
27078 * TODO: Should we clear the flags?
27079 * Might be problematic if one reuses the context
27080 * and assumes that the options remain the same.
27081 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000027082 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027083 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027084 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000027085#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027086 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000027087#endif
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027088 vctxt->hasKeyrefs = 0;
27089
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027090 if (vctxt->value != NULL) {
27091 xmlSchemaFreeValue(vctxt->value);
27092 vctxt->value = NULL;
27093 }
27094 /*
27095 * Augmented IDC information.
27096 */
27097 if (vctxt->aidcs != NULL) {
27098 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27099 do {
27100 next = cur->next;
27101 xmlFree(cur);
27102 cur = next;
27103 } while (cur != NULL);
27104 vctxt->aidcs = NULL;
27105 }
27106 if (vctxt->idcNodes != NULL) {
27107 int i;
27108 xmlSchemaPSVIIDCNodePtr item;
27109
27110 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027111 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027112 xmlFree(item->keys);
27113 xmlFree(item);
27114 }
27115 xmlFree(vctxt->idcNodes);
27116 vctxt->idcNodes = NULL;
27117 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027118 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027119 * Note that we won't delete the XPath state pool here.
27120 */
27121 if (vctxt->xpathStates != NULL) {
27122 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27123 vctxt->xpathStates = NULL;
27124 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027125 /*
27126 * Attribute info.
27127 */
27128 if (vctxt->nbAttrInfos != 0) {
27129 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027130 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027131 /*
27132 * Element info.
27133 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027134 if (vctxt->elemInfos != NULL) {
27135 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027136 xmlSchemaNodeInfoPtr ei;
27137
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027138 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027139 ei = vctxt->elemInfos[i];
27140 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027141 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027142 xmlSchemaClearElemInfo(ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027143 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027144 }
27145 xmlSchemaItemListClear(vctxt->nodeQNames);
27146 /* Recreate the dict. */
27147 xmlDictFree(vctxt->dict);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027148 /*
27149 * TODO: Is is save to recreate it? Do we have a scenario
27150 * where the user provides the dict?
27151 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027152 vctxt->dict = xmlDictCreate();
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027153}
27154
27155/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027156 * xmlSchemaFreeValidCtxt:
27157 * @ctxt: the schema validation context
27158 *
27159 * Free the resources associated to the schema validation context
27160 */
27161void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027162xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27163{
Daniel Veillard4255d502002-04-16 15:50:10 +000027164 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027165 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000027166 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027167 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027168 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027169 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027170 if (ctxt->idcNodes != NULL) {
27171 int i;
27172 xmlSchemaPSVIIDCNodePtr item;
27173
27174 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027175 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027176 xmlFree(item->keys);
27177 xmlFree(item);
27178 }
27179 xmlFree(ctxt->idcNodes);
27180 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027181 if (ctxt->idcKeys != NULL) {
27182 int i;
27183 for (i = 0; i < ctxt->nbIdcKeys; i++)
27184 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27185 xmlFree(ctxt->idcKeys);
27186 }
27187
27188 if (ctxt->xpathStates != NULL)
27189 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27190 if (ctxt->xpathStatePool != NULL)
27191 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27192
27193 /*
27194 * Augmented IDC information.
27195 */
27196 if (ctxt->aidcs != NULL) {
27197 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27198 do {
27199 next = cur->next;
27200 xmlFree(cur);
27201 cur = next;
27202 } while (cur != NULL);
27203 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027204 if (ctxt->attrInfos != NULL) {
27205 int i;
27206 xmlSchemaAttrInfoPtr attr;
27207
27208 /* Just a paranoid call to the cleanup. */
27209 if (ctxt->nbAttrInfos != 0)
27210 xmlSchemaClearAttrInfos(ctxt);
27211 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27212 attr = ctxt->attrInfos[i];
27213 xmlFree(attr);
27214 }
27215 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000027216 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027217 if (ctxt->elemInfos != NULL) {
27218 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027219 xmlSchemaNodeInfoPtr ei;
27220
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027221 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027222 ei = ctxt->elemInfos[i];
27223 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027224 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027225 xmlSchemaClearElemInfo(ei);
27226 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027227 }
27228 xmlFree(ctxt->elemInfos);
27229 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027230 if (ctxt->nodeQNames != NULL)
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000027231 xmlSchemaItemListFree(ctxt->nodeQNames);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027232 if (ctxt->dict != NULL)
27233 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000027234 xmlFree(ctxt);
27235}
27236
27237/**
Daniel Veillardf10ae122005-07-10 19:03:16 +000027238 * xmlSchemaIsValid:
27239 * @ctxt: the schema validation context
27240 *
27241 * Check if any error was detected during validation.
27242 *
27243 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27244 * of internal error.
27245 */
27246int
27247xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27248{
27249 if (ctxt == NULL)
27250 return(-1);
27251 return(ctxt->err == 0);
27252}
27253
27254/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027255 * xmlSchemaSetValidErrors:
27256 * @ctxt: a schema validation context
27257 * @err: the error function
27258 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000027259 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000027260 *
William M. Brack2f2a6632004-08-20 23:09:47 +000027261 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000027262 */
27263void
27264xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027265 xmlSchemaValidityErrorFunc err,
27266 xmlSchemaValidityWarningFunc warn, void *ctx)
27267{
Daniel Veillard4255d502002-04-16 15:50:10 +000027268 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027269 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000027270 ctxt->error = err;
27271 ctxt->warning = warn;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027272 ctxt->errCtxt = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027273 if (ctxt->pctxt != NULL)
27274 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000027275}
27276
27277/**
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027278 * xmlSchemaSetValidStructuredErrors:
27279 * @ctxt: a schema validation context
27280 * @serror: the structured error function
27281 * @ctx: the functions context
27282 *
27283 * Set the structured error callback
27284 */
27285void
27286xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027287 xmlStructuredErrorFunc serror, void *ctx)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027288{
27289 if (ctxt == NULL)
27290 return;
27291 ctxt->serror = serror;
27292 ctxt->error = NULL;
27293 ctxt->warning = NULL;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027294 ctxt->errCtxt = ctx;
27295 if (ctxt->pctxt != NULL)
27296 xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027297}
27298
27299/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000027300 * xmlSchemaGetValidErrors:
27301 * @ctxt: a XML-Schema validation context
27302 * @err: the error function result
27303 * @warn: the warning function result
27304 * @ctx: the functions context result
27305 *
27306 * Get the error and warning callback informations
27307 *
27308 * Returns -1 in case of error and 0 otherwise
27309 */
27310int
27311xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027312 xmlSchemaValidityErrorFunc * err,
27313 xmlSchemaValidityWarningFunc * warn, void **ctx)
Daniel Veillard259f0df2004-08-18 09:13:18 +000027314{
27315 if (ctxt == NULL)
27316 return (-1);
27317 if (err != NULL)
27318 *err = ctxt->error;
27319 if (warn != NULL)
27320 *warn = ctxt->warning;
27321 if (ctx != NULL)
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027322 *ctx = ctxt->errCtxt;
Daniel Veillard259f0df2004-08-18 09:13:18 +000027323 return (0);
27324}
27325
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027326
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027327/**
Daniel Veillard6927b102004-10-27 17:29:04 +000027328 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027329 * @ctxt: a schema validation context
27330 * @options: a combination of xmlSchemaValidOption
27331 *
27332 * Sets the options to be used during the validation.
27333 *
27334 * Returns 0 in case of success, -1 in case of an
27335 * API error.
27336 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027337int
27338xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27339 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027340
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027341{
27342 int i;
27343
27344 if (ctxt == NULL)
27345 return (-1);
27346 /*
27347 * WARNING: Change the start value if adding to the
27348 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027349 * TODO: Is there an other, more easy to maintain,
27350 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027351 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027352 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027353 if (options & 1<<i)
27354 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027355 }
27356 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027357 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027358}
27359
27360/**
Daniel Veillard6927b102004-10-27 17:29:04 +000027361 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027362 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027363 *
William M. Brack21e4ef22005-01-02 09:53:13 +000027364 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027365 *
William M. Brack21e4ef22005-01-02 09:53:13 +000027366 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027367 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027368int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027369xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027370
27371{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027372 if (ctxt == NULL)
27373 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027374 else
27375 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027376}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027377
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027378static int
27379xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27380{
27381 xmlAttrPtr attr;
27382 int ret = 0;
27383 xmlSchemaNodeInfoPtr ielem = NULL;
27384 xmlNodePtr node, valRoot;
27385 const xmlChar *nsName;
27386
27387 /* DOC VAL TODO: Move this to the start function. */
27388 valRoot = xmlDocGetRootElement(vctxt->doc);
27389 if (valRoot == NULL) {
27390 /* VAL TODO: Error code? */
27391 VERROR(1, NULL, "The document has no document element");
27392 return (1);
27393 }
27394 vctxt->depth = -1;
27395 vctxt->validationRoot = valRoot;
27396 node = valRoot;
27397 while (node != NULL) {
27398 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27399 goto next_sibling;
27400 if (node->type == XML_ELEMENT_NODE) {
27401
27402 /*
27403 * Init the node-info.
27404 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000027405 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027406 if (xmlSchemaValidatorPushElem(vctxt) == -1)
27407 goto internal_error;
27408 ielem = vctxt->inode;
27409 ielem->node = node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027410 ielem->nodeLine = node->line;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027411 ielem->localName = node->name;
27412 if (node->ns != NULL)
27413 ielem->nsName = node->ns->href;
27414 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27415 /*
27416 * Register attributes.
27417 * DOC VAL TODO: We do not register namespace declaration
27418 * attributes yet.
27419 */
27420 vctxt->nbAttrInfos = 0;
27421 if (node->properties != NULL) {
27422 attr = node->properties;
27423 do {
27424 if (attr->ns != NULL)
27425 nsName = attr->ns->href;
27426 else
27427 nsName = NULL;
27428 ret = xmlSchemaValidatorPushAttribute(vctxt,
27429 (xmlNodePtr) attr,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027430 /*
27431 * Note that we give it the line number of the
27432 * parent element.
27433 */
27434 ielem->nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027435 attr->name, nsName, 0,
27436 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27437 if (ret == -1) {
27438 VERROR_INT("xmlSchemaDocWalk",
27439 "calling xmlSchemaValidatorPushAttribute()");
27440 goto internal_error;
27441 }
27442 attr = attr->next;
27443 } while (attr);
27444 }
27445 /*
27446 * Validate the element.
27447 */
27448 ret = xmlSchemaValidateElem(vctxt);
27449 if (ret != 0) {
27450 if (ret == -1) {
27451 VERROR_INT("xmlSchemaDocWalk",
27452 "calling xmlSchemaValidateElem()");
27453 goto internal_error;
27454 }
27455 /*
27456 * Don't stop validation; just skip the content
27457 * of this element.
27458 */
27459 goto leave_node;
27460 }
27461 if ((vctxt->skipDepth != -1) &&
27462 (vctxt->depth >= vctxt->skipDepth))
27463 goto leave_node;
27464 } else if ((node->type == XML_TEXT_NODE) ||
27465 (node->type == XML_CDATA_SECTION_NODE)) {
27466 /*
27467 * Process character content.
27468 */
Daniel Veillard14b56432006-03-09 18:41:40 +000027469 if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027470 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27471 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27472 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27473 if (ret < 0) {
27474 VERROR_INT("xmlSchemaVDocWalk",
27475 "calling xmlSchemaVPushText()");
27476 goto internal_error;
27477 }
27478 /*
27479 * DOC VAL TODO: Should we skip further validation of the
27480 * element content here?
27481 */
27482 } else if ((node->type == XML_ENTITY_NODE) ||
27483 (node->type == XML_ENTITY_REF_NODE)) {
27484 /*
27485 * DOC VAL TODO: What to do with entities?
27486 */
27487 TODO
27488 } else {
27489 goto leave_node;
27490 /*
27491 * DOC VAL TODO: XInclude nodes, etc.
27492 */
27493 }
27494 /*
27495 * Walk the doc.
27496 */
27497 if (node->children != NULL) {
27498 node = node->children;
27499 continue;
27500 }
27501leave_node:
27502 if (node->type == XML_ELEMENT_NODE) {
27503 /*
27504 * Leaving the scope of an element.
27505 */
27506 if (node != vctxt->inode->node) {
27507 VERROR_INT("xmlSchemaVDocWalk",
27508 "element position mismatch");
27509 goto internal_error;
27510 }
27511 ret = xmlSchemaValidatorPopElem(vctxt);
27512 if (ret != 0) {
27513 if (ret < 0) {
27514 VERROR_INT("xmlSchemaVDocWalk",
27515 "calling xmlSchemaValidatorPopElem()");
27516 goto internal_error;
27517 }
27518 }
27519 if (node == valRoot)
27520 goto exit;
27521 }
27522next_sibling:
27523 if (node->next != NULL)
27524 node = node->next;
27525 else {
27526 node = node->parent;
27527 goto leave_node;
27528 }
27529 }
27530
27531exit:
27532 return (ret);
27533internal_error:
27534 return (-1);
27535}
27536
27537static int
Daniel Veillardf10ae122005-07-10 19:03:16 +000027538xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027539 /*
27540 * Some initialization.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027541 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027542 vctxt->err = 0;
27543 vctxt->nberrors = 0;
27544 vctxt->depth = -1;
27545 vctxt->skipDepth = -1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027546 vctxt->xsiAssemble = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027547 vctxt->hasKeyrefs = 0;
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000027548#ifdef ENABLE_IDC_NODE_TABLES_TEST
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027549 vctxt->createIDCNodeTables = 1;
27550#else
27551 vctxt->createIDCNodeTables = 0;
27552#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027553 /*
27554 * Create a schema + parser if necessary.
27555 */
27556 if (vctxt->schema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027557 xmlSchemaParserCtxtPtr pctxt;
27558
27559 vctxt->xsiAssemble = 1;
27560 /*
27561 * If not schema was given then we will create a schema
27562 * dynamically using XSI schema locations.
27563 *
27564 * Create the schema parser context.
27565 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027566 if ((vctxt->pctxt == NULL) &&
27567 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
27568 return (-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027569 pctxt = vctxt->pctxt;
27570 pctxt->xsiAssemble = 1;
27571 /*
27572 * Create the schema.
27573 */
27574 vctxt->schema = xmlSchemaNewSchema(pctxt);
27575 if (vctxt->schema == NULL)
27576 return (-1);
27577 /*
27578 * Create the schema construction context.
27579 */
27580 pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
27581 if (pctxt->constructor == NULL)
27582 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000027583 pctxt->constructor->mainSchema = vctxt->schema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027584 /*
27585 * Take ownership of the constructor to be able to free it.
27586 */
27587 pctxt->ownsConstructor = 1;
27588 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027589 /*
27590 * Augment the IDC definitions.
27591 */
27592 if (vctxt->schema->idcDef != NULL) {
27593 xmlHashScan(vctxt->schema->idcDef,
27594 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
27595 }
Daniel Veillardf10ae122005-07-10 19:03:16 +000027596 return(0);
27597}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027598
Daniel Veillardf10ae122005-07-10 19:03:16 +000027599static void
27600xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027601 if (vctxt->xsiAssemble) {
27602 if (vctxt->schema != NULL) {
27603 xmlSchemaFree(vctxt->schema);
27604 vctxt->schema = NULL;
27605 }
27606 }
27607 xmlSchemaClearValidCtxt(vctxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +000027608}
27609
27610static int
27611xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
27612{
27613 int ret = 0;
27614
27615 if (xmlSchemaPreRun(vctxt) < 0)
27616 return(-1);
27617
27618 if (vctxt->doc != NULL) {
27619 /*
27620 * Tree validation.
27621 */
27622 ret = xmlSchemaVDocWalk(vctxt);
27623#ifdef LIBXML_READER_ENABLED
27624 } else if (vctxt->reader != NULL) {
27625 /*
27626 * XML Reader validation.
27627 */
27628#ifdef XML_SCHEMA_READER_ENABLED
27629 ret = xmlSchemaVReaderWalk(vctxt);
27630#endif
27631#endif
27632 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
27633 /*
27634 * SAX validation.
27635 */
27636 ret = xmlParseDocument(vctxt->parserCtxt);
27637 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027638 VERROR_INT("xmlSchemaVStart",
Daniel Veillardf10ae122005-07-10 19:03:16 +000027639 "no instance to validate");
27640 ret = -1;
27641 }
27642
27643 xmlSchemaPostRun(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027644 if (ret == 0)
27645 ret = vctxt->err;
27646 return (ret);
27647}
27648
27649/**
27650 * xmlSchemaValidateOneElement:
27651 * @ctxt: a schema validation context
27652 * @elem: an element node
27653 *
27654 * Validate a branch of a tree, starting with the given @elem.
27655 *
27656 * Returns 0 if the element and its subtree is valid, a positive error
27657 * code number otherwise and -1 in case of an internal or API error.
27658 */
27659int
27660xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
27661{
27662 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
27663 return (-1);
27664
27665 if (ctxt->schema == NULL)
27666 return (-1);
27667
27668 ctxt->doc = elem->doc;
27669 ctxt->node = elem;
27670 ctxt->validationRoot = elem;
27671 return(xmlSchemaVStart(ctxt));
27672}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027673
Daniel Veillard259f0df2004-08-18 09:13:18 +000027674/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027675 * xmlSchemaValidateDoc:
27676 * @ctxt: a schema validation context
27677 * @doc: a parsed document tree
27678 *
27679 * Validate a document tree in memory.
27680 *
27681 * Returns 0 if the document is schemas valid, a positive error code
27682 * number otherwise and -1 in case of internal or API error.
27683 */
27684int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027685xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
27686{
Daniel Veillard4255d502002-04-16 15:50:10 +000027687 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027688 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000027689
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027690 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027691 ctxt->node = xmlDocGetRootElement(doc);
27692 if (ctxt->node == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027693 xmlSchemaCustomErr(ACTXT_CAST ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027694 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
27695 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027696 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027697 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027698 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027699 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027700 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000027701}
27702
Daniel Veillardcdc82732005-07-08 15:04:06 +000027703
27704/************************************************************************
27705 * *
27706 * Function and data for SAX streaming API *
27707 * *
27708 ************************************************************************/
27709typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
27710typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
27711
27712struct _xmlSchemaSplitSAXData {
27713 xmlSAXHandlerPtr user_sax;
27714 void *user_data;
27715 xmlSchemaValidCtxtPtr ctxt;
27716 xmlSAXHandlerPtr schemas_sax;
27717};
27718
Daniel Veillard971771e2005-07-09 17:32:57 +000027719#define XML_SAX_PLUG_MAGIC 0xdc43ba21
27720
27721struct _xmlSchemaSAXPlug {
27722 unsigned int magic;
27723
27724 /* the original callbacks informations */
27725 xmlSAXHandlerPtr *user_sax_ptr;
27726 xmlSAXHandlerPtr user_sax;
27727 void **user_data_ptr;
27728 void *user_data;
27729
27730 /* the block plugged back and validation informations */
27731 xmlSAXHandler schemas_sax;
27732 xmlSchemaValidCtxtPtr ctxt;
27733};
27734
Daniel Veillardcdc82732005-07-08 15:04:06 +000027735/* All those functions just bounces to the user provided SAX handlers */
27736static void
27737internalSubsetSplit(void *ctx, const xmlChar *name,
27738 const xmlChar *ExternalID, const xmlChar *SystemID)
27739{
Daniel Veillard971771e2005-07-09 17:32:57 +000027740 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027741 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27742 (ctxt->user_sax->internalSubset != NULL))
27743 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
27744 SystemID);
27745}
27746
27747static int
27748isStandaloneSplit(void *ctx)
27749{
Daniel Veillard971771e2005-07-09 17:32:57 +000027750 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027751 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27752 (ctxt->user_sax->isStandalone != NULL))
27753 return(ctxt->user_sax->isStandalone(ctxt->user_data));
27754 return(0);
27755}
27756
27757static int
27758hasInternalSubsetSplit(void *ctx)
27759{
Daniel Veillard971771e2005-07-09 17:32:57 +000027760 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027761 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27762 (ctxt->user_sax->hasInternalSubset != NULL))
27763 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
27764 return(0);
27765}
27766
27767static int
27768hasExternalSubsetSplit(void *ctx)
27769{
Daniel Veillard971771e2005-07-09 17:32:57 +000027770 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027771 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27772 (ctxt->user_sax->hasExternalSubset != NULL))
27773 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
27774 return(0);
27775}
27776
27777static void
27778externalSubsetSplit(void *ctx, const xmlChar *name,
27779 const xmlChar *ExternalID, const xmlChar *SystemID)
27780{
Daniel Veillard971771e2005-07-09 17:32:57 +000027781 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027782 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27783 (ctxt->user_sax->internalSubset != NULL))
27784 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
27785 SystemID);
27786}
27787
27788static xmlParserInputPtr
27789resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
27790{
Daniel Veillard971771e2005-07-09 17:32:57 +000027791 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027792 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27793 (ctxt->user_sax->resolveEntity != NULL))
27794 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
27795 systemId));
27796 return(NULL);
27797}
27798
27799static xmlEntityPtr
27800getEntitySplit(void *ctx, const xmlChar *name)
27801{
Daniel Veillard971771e2005-07-09 17:32:57 +000027802 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027803 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27804 (ctxt->user_sax->getEntity != NULL))
27805 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
27806 return(NULL);
27807}
27808
27809static xmlEntityPtr
27810getParameterEntitySplit(void *ctx, const xmlChar *name)
27811{
Daniel Veillard971771e2005-07-09 17:32:57 +000027812 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027813 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27814 (ctxt->user_sax->getParameterEntity != NULL))
27815 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
27816 return(NULL);
27817}
27818
27819
27820static void
27821entityDeclSplit(void *ctx, const xmlChar *name, int type,
27822 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
27823{
Daniel Veillard971771e2005-07-09 17:32:57 +000027824 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027825 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27826 (ctxt->user_sax->entityDecl != NULL))
27827 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
27828 systemId, content);
27829}
27830
27831static void
27832attributeDeclSplit(void *ctx, const xmlChar * elem,
27833 const xmlChar * name, int type, int def,
27834 const xmlChar * defaultValue, xmlEnumerationPtr tree)
27835{
Daniel Veillard971771e2005-07-09 17:32:57 +000027836 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027837 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27838 (ctxt->user_sax->attributeDecl != NULL)) {
27839 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
27840 def, defaultValue, tree);
27841 } else {
27842 xmlFreeEnumeration(tree);
27843 }
27844}
27845
27846static void
27847elementDeclSplit(void *ctx, const xmlChar *name, int type,
27848 xmlElementContentPtr content)
27849{
Daniel Veillard971771e2005-07-09 17:32:57 +000027850 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027851 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27852 (ctxt->user_sax->elementDecl != NULL))
27853 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
27854}
27855
27856static void
27857notationDeclSplit(void *ctx, const xmlChar *name,
27858 const xmlChar *publicId, const xmlChar *systemId)
27859{
Daniel Veillard971771e2005-07-09 17:32:57 +000027860 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027861 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27862 (ctxt->user_sax->notationDecl != NULL))
27863 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
27864 systemId);
27865}
27866
27867static void
27868unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
27869 const xmlChar *publicId, const xmlChar *systemId,
27870 const xmlChar *notationName)
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->unparsedEntityDecl != NULL))
27875 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
27876 systemId, notationName);
27877}
27878
27879static void
27880setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
27881{
Daniel Veillard971771e2005-07-09 17:32:57 +000027882 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027883 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27884 (ctxt->user_sax->setDocumentLocator != NULL))
27885 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
27886}
27887
27888static void
27889startDocumentSplit(void *ctx)
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->startDocument != NULL))
27894 ctxt->user_sax->startDocument(ctxt->user_data);
27895}
27896
27897static void
27898endDocumentSplit(void *ctx)
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->endDocument != NULL))
27903 ctxt->user_sax->endDocument(ctxt->user_data);
27904}
27905
27906static void
27907processingInstructionSplit(void *ctx, const xmlChar *target,
27908 const xmlChar *data)
27909{
Daniel Veillard971771e2005-07-09 17:32:57 +000027910 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027911 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27912 (ctxt->user_sax->processingInstruction != NULL))
27913 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
27914}
27915
27916static void
27917commentSplit(void *ctx, const xmlChar *value)
27918{
Daniel Veillard971771e2005-07-09 17:32:57 +000027919 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027920 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27921 (ctxt->user_sax->comment != NULL))
27922 ctxt->user_sax->comment(ctxt->user_data, value);
27923}
27924
27925/*
27926 * Varargs error callbacks to the user application, harder ...
27927 */
27928
Daniel Veillardffa3c742005-07-21 13:24:09 +000027929static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027930warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027931 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027932 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27933 (ctxt->user_sax->warning != NULL)) {
27934 TODO
27935 }
27936}
Daniel Veillardffa3c742005-07-21 13:24:09 +000027937static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027938errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027939 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027940 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27941 (ctxt->user_sax->error != NULL)) {
27942 TODO
27943 }
27944}
Daniel Veillardffa3c742005-07-21 13:24:09 +000027945static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027946fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027947 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027948 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27949 (ctxt->user_sax->fatalError != NULL)) {
27950 TODO
27951 }
27952}
27953
27954/*
27955 * Those are function where both the user handler and the schemas handler
27956 * need to be called.
27957 */
27958static void
27959charactersSplit(void *ctx, const xmlChar *ch, int len)
27960{
Daniel Veillard971771e2005-07-09 17:32:57 +000027961 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027962 if (ctxt == NULL)
27963 return;
27964 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
27965 ctxt->user_sax->characters(ctxt->user_data, ch, len);
27966 if (ctxt->ctxt != NULL)
27967 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
27968}
27969
27970static void
27971ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
27972{
Daniel Veillard971771e2005-07-09 17:32:57 +000027973 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027974 if (ctxt == NULL)
27975 return;
27976 if ((ctxt->user_sax != NULL) &&
27977 (ctxt->user_sax->ignorableWhitespace != NULL))
27978 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
27979 if (ctxt->ctxt != NULL)
27980 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
27981}
27982
27983static void
27984cdataBlockSplit(void *ctx, const xmlChar *value, int len)
27985{
Daniel Veillard971771e2005-07-09 17:32:57 +000027986 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027987 if (ctxt == NULL)
27988 return;
27989 if ((ctxt->user_sax != NULL) &&
27990 (ctxt->user_sax->ignorableWhitespace != NULL))
27991 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, value, len);
27992 if (ctxt->ctxt != NULL)
27993 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
27994}
27995
27996static void
27997referenceSplit(void *ctx, const xmlChar *name)
27998{
Daniel Veillard971771e2005-07-09 17:32:57 +000027999 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillard14b56432006-03-09 18:41:40 +000028000 if (ctxt == NULL)
28001 return;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028002 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28003 (ctxt->user_sax->reference != NULL))
28004 ctxt->user_sax->reference(ctxt->user_data, name);
28005 if (ctxt->ctxt != NULL)
28006 xmlSchemaSAXHandleReference(ctxt->user_data, name);
28007}
28008
28009static void
28010startElementNsSplit(void *ctx, const xmlChar * localname,
28011 const xmlChar * prefix, const xmlChar * URI,
28012 int nb_namespaces, const xmlChar ** namespaces,
28013 int nb_attributes, int nb_defaulted,
28014 const xmlChar ** attributes) {
Daniel Veillard971771e2005-07-09 17:32:57 +000028015 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028016 if (ctxt == NULL)
28017 return;
28018 if ((ctxt->user_sax != NULL) &&
28019 (ctxt->user_sax->startElementNs != NULL))
28020 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28021 URI, nb_namespaces, namespaces,
28022 nb_attributes, nb_defaulted,
28023 attributes);
28024 if (ctxt->ctxt != NULL)
28025 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28026 URI, nb_namespaces, namespaces,
28027 nb_attributes, nb_defaulted,
28028 attributes);
28029}
28030
28031static void
28032endElementNsSplit(void *ctx, const xmlChar * localname,
28033 const xmlChar * prefix, const xmlChar * URI) {
Daniel Veillard971771e2005-07-09 17:32:57 +000028034 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028035 if (ctxt == NULL)
28036 return;
28037 if ((ctxt->user_sax != NULL) &&
28038 (ctxt->user_sax->endElementNs != NULL))
28039 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28040 if (ctxt->ctxt != NULL)
28041 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28042}
28043
Daniel Veillard4255d502002-04-16 15:50:10 +000028044/**
Daniel Veillard971771e2005-07-09 17:32:57 +000028045 * xmlSchemaSAXPlug:
28046 * @ctxt: a schema validation context
Daniel Veillard1f33c4d2005-07-10 21:38:31 +000028047 * @sax: a pointer to the original xmlSAXHandlerPtr
28048 * @user_data: a pointer to the original SAX user data pointer
Daniel Veillard971771e2005-07-09 17:32:57 +000028049 *
28050 * Plug a SAX based validation layer in a SAX parsing event flow.
28051 * The original @saxptr and @dataptr data are replaced by new pointers
28052 * but the calls to the original will be maintained.
28053 *
28054 * Returns a pointer to a data structure needed to unplug the validation layer
28055 * or NULL in case of errors.
28056 */
28057xmlSchemaSAXPlugPtr
28058xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28059 xmlSAXHandlerPtr *sax, void **user_data)
28060{
28061 xmlSchemaSAXPlugPtr ret;
28062 xmlSAXHandlerPtr old_sax;
28063
28064 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28065 return(NULL);
28066
28067 /*
28068 * We only allow to plug into SAX2 event streams
28069 */
28070 old_sax = *sax;
28071 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28072 return(NULL);
28073 if ((old_sax != NULL) &&
28074 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28075 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28076 return(NULL);
28077
28078 /*
28079 * everything seems right allocate the local data needed for that layer
28080 */
28081 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28082 if (ret == NULL) {
28083 return(NULL);
28084 }
28085 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28086 ret->magic = XML_SAX_PLUG_MAGIC;
28087 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28088 ret->ctxt = ctxt;
28089 ret->user_sax_ptr = sax;
28090 ret->user_sax = old_sax;
28091 if (old_sax == NULL) {
28092 /*
28093 * go direct, no need for the split block and functions.
28094 */
28095 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28096 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28097 /*
28098 * Note that we use the same text-function for both, to prevent
28099 * the parser from testing for ignorable whitespace.
28100 */
28101 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28102 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28103
28104 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28105 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28106
28107 ret->user_data = ctxt;
28108 *user_data = ctxt;
28109 } else {
28110 /*
28111 * for each callback unused by Schemas initialize it to the Split
28112 * routine only if non NULL in the user block, this can speed up
28113 * things at the SAX level.
28114 */
28115 if (old_sax->internalSubset != NULL)
28116 ret->schemas_sax.internalSubset = internalSubsetSplit;
28117 if (old_sax->isStandalone != NULL)
28118 ret->schemas_sax.isStandalone = isStandaloneSplit;
28119 if (old_sax->hasInternalSubset != NULL)
28120 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28121 if (old_sax->hasExternalSubset != NULL)
28122 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28123 if (old_sax->resolveEntity != NULL)
28124 ret->schemas_sax.resolveEntity = resolveEntitySplit;
28125 if (old_sax->getEntity != NULL)
28126 ret->schemas_sax.getEntity = getEntitySplit;
28127 if (old_sax->entityDecl != NULL)
28128 ret->schemas_sax.entityDecl = entityDeclSplit;
28129 if (old_sax->notationDecl != NULL)
28130 ret->schemas_sax.notationDecl = notationDeclSplit;
28131 if (old_sax->attributeDecl != NULL)
28132 ret->schemas_sax.attributeDecl = attributeDeclSplit;
28133 if (old_sax->elementDecl != NULL)
28134 ret->schemas_sax.elementDecl = elementDeclSplit;
28135 if (old_sax->unparsedEntityDecl != NULL)
28136 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28137 if (old_sax->setDocumentLocator != NULL)
28138 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28139 if (old_sax->startDocument != NULL)
28140 ret->schemas_sax.startDocument = startDocumentSplit;
28141 if (old_sax->endDocument != NULL)
28142 ret->schemas_sax.endDocument = endDocumentSplit;
28143 if (old_sax->processingInstruction != NULL)
28144 ret->schemas_sax.processingInstruction = processingInstructionSplit;
28145 if (old_sax->comment != NULL)
28146 ret->schemas_sax.comment = commentSplit;
28147 if (old_sax->warning != NULL)
28148 ret->schemas_sax.warning = warningSplit;
28149 if (old_sax->error != NULL)
28150 ret->schemas_sax.error = errorSplit;
28151 if (old_sax->fatalError != NULL)
28152 ret->schemas_sax.fatalError = fatalErrorSplit;
28153 if (old_sax->getParameterEntity != NULL)
28154 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28155 if (old_sax->externalSubset != NULL)
28156 ret->schemas_sax.externalSubset = externalSubsetSplit;
28157
28158 /*
28159 * the 6 schemas callback have to go to the splitter functions
28160 * Note that we use the same text-function for ignorableWhitespace
28161 * if possible, to prevent the parser from testing for ignorable
28162 * whitespace.
28163 */
28164 ret->schemas_sax.characters = charactersSplit;
28165 if ((old_sax->ignorableWhitespace != NULL) &&
28166 (old_sax->ignorableWhitespace != old_sax->characters))
28167 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28168 else
28169 ret->schemas_sax.ignorableWhitespace = charactersSplit;
28170 ret->schemas_sax.cdataBlock = cdataBlockSplit;
28171 ret->schemas_sax.reference = referenceSplit;
28172 ret->schemas_sax.startElementNs = startElementNsSplit;
28173 ret->schemas_sax.endElementNs = endElementNsSplit;
28174
28175 ret->user_data_ptr = user_data;
28176 ret->user_data = *user_data;
28177 *user_data = ret;
28178 }
28179
28180 /*
28181 * plug the pointers back.
28182 */
28183 *sax = &(ret->schemas_sax);
Daniel Veillardf10ae122005-07-10 19:03:16 +000028184 ctxt->sax = *sax;
28185 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28186 xmlSchemaPreRun(ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000028187 return(ret);
28188}
28189
28190/**
28191 * xmlSchemaSAXUnplug:
28192 * @plug: a data structure returned by xmlSchemaSAXPlug
28193 *
28194 * Unplug a SAX based validation layer in a SAX parsing event flow.
28195 * The original pointers used in the call are restored.
28196 *
28197 * Returns 0 in case of success and -1 in case of failure.
28198 */
28199int
28200xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28201{
28202 xmlSAXHandlerPtr *sax;
28203 void **user_data;
28204
28205 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28206 return(-1);
28207 plug->magic = 0;
28208
Daniel Veillardf10ae122005-07-10 19:03:16 +000028209 xmlSchemaPostRun(plug->ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000028210 /* restore the data */
28211 sax = plug->user_sax_ptr;
28212 *sax = plug->user_sax;
28213 if (plug->user_sax != NULL) {
28214 user_data = plug->user_data_ptr;
28215 *user_data = plug->user_data;
28216 }
28217
28218 /* free and return */
28219 xmlFree(plug);
28220 return(0);
28221}
28222
28223/**
Daniel Veillard4255d502002-04-16 15:50:10 +000028224 * xmlSchemaValidateStream:
28225 * @ctxt: a schema validation context
28226 * @input: the input to use for reading the data
28227 * @enc: an optional encoding information
28228 * @sax: a SAX handler for the resulting events
28229 * @user_data: the context to provide to the SAX handler.
28230 *
Daniel Veillardcdc82732005-07-08 15:04:06 +000028231 * Validate an input based on a flow of SAX event from the parser
28232 * and forward the events to the @sax handler with the provided @user_data
28233 * the user provided @sax handler must be a SAX2 one.
Daniel Veillard4255d502002-04-16 15:50:10 +000028234 *
28235 * Returns 0 if the document is schemas valid, a positive error code
28236 * number otherwise and -1 in case of internal or API error.
28237 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028238int
Daniel Veillard4255d502002-04-16 15:50:10 +000028239xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028240 xmlParserInputBufferPtr input, xmlCharEncoding enc,
28241 xmlSAXHandlerPtr sax, void *user_data)
28242{
Daniel Veillard971771e2005-07-09 17:32:57 +000028243 xmlSchemaSAXPlugPtr plug = NULL;
28244 xmlSAXHandlerPtr old_sax = NULL;
28245 xmlParserCtxtPtr pctxt = NULL;
28246 xmlParserInputPtr inputStream = NULL;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028247 int ret;
28248
Daniel Veillard4255d502002-04-16 15:50:10 +000028249 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028250 return (-1);
Daniel Veillardcdc82732005-07-08 15:04:06 +000028251
Daniel Veillardcdc82732005-07-08 15:04:06 +000028252 /*
28253 * prepare the parser
28254 */
28255 pctxt = xmlNewParserCtxt();
28256 if (pctxt == NULL)
28257 return (-1);
28258 old_sax = pctxt->sax;
Daniel Veillard971771e2005-07-09 17:32:57 +000028259 pctxt->sax = sax;
28260 pctxt->userData = user_data;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028261#if 0
28262 if (options)
28263 xmlCtxtUseOptions(pctxt, options);
28264#endif
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000028265 pctxt->linenumbers = 1;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028266
Daniel Veillardf0af8ec2005-07-08 17:27:33 +000028267 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028268 if (inputStream == NULL) {
28269 ret = -1;
28270 goto done;
28271 }
28272 inputPush(pctxt, inputStream);
28273 ctxt->parserCtxt = pctxt;
28274 ctxt->input = input;
28275
28276 /*
Daniel Veillard971771e2005-07-09 17:32:57 +000028277 * Plug the validation and launch the parsing
Daniel Veillardcdc82732005-07-08 15:04:06 +000028278 */
Daniel Veillard971771e2005-07-09 17:32:57 +000028279 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28280 if (plug == NULL) {
28281 ret = -1;
28282 goto done;
28283 }
28284 ctxt->input = input;
28285 ctxt->enc = enc;
28286 ctxt->sax = pctxt->sax;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028287 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28288 ret = xmlSchemaVStart(ctxt);
28289
28290 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28291 ret = ctxt->parserCtxt->errNo;
28292 if (ret == 0)
28293 ret = 1;
28294 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028295
28296done:
Daniel Veillard971771e2005-07-09 17:32:57 +000028297 ctxt->parserCtxt = NULL;
28298 ctxt->sax = NULL;
28299 ctxt->input = NULL;
28300 if (plug != NULL) {
28301 xmlSchemaSAXUnplug(plug);
28302 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028303 /* cleanup */
Daniel Veillard971771e2005-07-09 17:32:57 +000028304 if (pctxt != NULL) {
28305 pctxt->sax = old_sax;
28306 xmlFreeParserCtxt(pctxt);
28307 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028308 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000028309}
28310
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028311/**
28312 * xmlSchemaValidateFile:
28313 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000028314 * @filename: the URI of the instance
28315 * @options: a future set of options, currently unused
28316 *
28317 * Do a schemas validation of the given resource, it will use the
28318 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028319 *
28320 * Returns 0 if the document is valid, a positive error code
28321 * number otherwise and -1 in case of an internal or API error.
28322 */
28323int
28324xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000028325 const char * filename,
28326 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028327{
28328 int ret;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028329 xmlParserInputBufferPtr input;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028330
28331 if ((ctxt == NULL) || (filename == NULL))
28332 return (-1);
28333
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028334 input = xmlParserInputBufferCreateFilename(filename,
28335 XML_CHAR_ENCODING_NONE);
28336 if (input == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028337 return (-1);
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028338 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28339 NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028340 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000028341}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028342
Daniel Veillard5d4644e2005-04-01 13:11:58 +000028343#define bottom_xmlschemas
28344#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000028345#endif /* LIBXML_SCHEMAS_ENABLED */