blob: 20591963e813d2b71122011b25da3a49a8a65da4 [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{
3013 xmlChar *des = NULL, *strT = NULL;
3014
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 FREE_AND_NULL(strT);
3022}
3023
3024/**
3025 * xmlSchemaPMutualExclAttrErr:
3026 * @ctxt: the schema validation context
3027 * @error: the error code
3028 * @elemDes: the designation of the parent element node
3029 * @attr: the bad attribute node
3030 * @type: the corresponding type of the attribute node
3031 *
3032 * Reports an illegal attribute.
3033 */
3034static void
3035xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3036 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003037 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003038 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003039 const char *name1,
3040 const char *name2)
3041{
3042 xmlChar *des = NULL;
3043
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003044 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003045 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003046 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003047 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003048 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003049}
3050
3051/**
3052 * xmlSchemaPSimpleTypeErr:
3053 * @ctxt: the schema validation context
3054 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00003055 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00003056 * @ownerDes: the designation of the owner
3057 * @ownerItem: the schema object if existent
3058 * @node: the validated node
3059 * @value: the validated value
3060 *
3061 * Reports a simple type validation error.
3062 * TODO: Should this report the value of an element as well?
3063 */
3064static void
3065xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3066 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003067 xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003068 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00003069 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003070 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003071 const xmlChar *value,
3072 const char *message,
3073 const xmlChar *str1,
3074 const xmlChar *str2)
3075{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003076 xmlChar *msg = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003077
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003078 xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003079 if (message == NULL) {
3080 /*
3081 * Use default messages.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003082 */
3083 if (type != NULL) {
3084 if (node->type == XML_ATTRIBUTE_NODE)
3085 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3086 else
3087 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3088 "valid value of ");
3089 if (! xmlSchemaIsGlobalItem(type))
3090 msg = xmlStrcat(msg, BAD_CAST "the local ");
3091 else
3092 msg = xmlStrcat(msg, BAD_CAST "the ");
3093
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003094 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003095 msg = xmlStrcat(msg, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003096 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003097 msg = xmlStrcat(msg, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003098 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003099 msg = xmlStrcat(msg, BAD_CAST "union type");
3100
3101 if (xmlSchemaIsGlobalItem(type)) {
3102 xmlChar *str = NULL;
3103 msg = xmlStrcat(msg, BAD_CAST " '");
3104 if (type->builtInType != 0) {
3105 msg = xmlStrcat(msg, BAD_CAST "xs:");
3106 msg = xmlStrcat(msg, type->name);
3107 } else
3108 msg = xmlStrcat(msg,
3109 xmlSchemaFormatQName(&str,
3110 type->targetNamespace, type->name));
3111 msg = xmlStrcat(msg, BAD_CAST "'.");
3112 FREE_AND_NULL(str);
3113 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003114 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003115 if (node->type == XML_ATTRIBUTE_NODE)
3116 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3117 else
3118 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3119 "valid.");
3120 }
3121 if (expected) {
3122 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3123 msg = xmlStrcat(msg, BAD_CAST expected);
3124 msg = xmlStrcat(msg, BAD_CAST "'.\n");
3125 } else
3126 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00003127 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003128 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3129 else
3130 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3131 } else {
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00003132 msg = xmlStrcat(msg, BAD_CAST message);
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00003133 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003134 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00003135 (const char*) msg, str1, str2, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003136 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003137 /* Cleanup. */
3138 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003139}
3140
William M. Brack2f2a6632004-08-20 23:09:47 +00003141/**
3142 * xmlSchemaPContentErr:
3143 * @ctxt: the schema parser context
3144 * @error: the error code
3145 * @onwerDes: the designation of the holder of the content
3146 * @ownerItem: the owner item of the holder of the content
3147 * @ownerElem: the node of the holder of the content
3148 * @child: the invalid child node
3149 * @message: the optional error message
3150 * @content: the optional string describing the correct content
3151 *
3152 * Reports an error concerning the content of a schema element.
3153 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00003154static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003155xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003156 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003157 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003158 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003159 xmlNodePtr child,
3160 const char *message,
3161 const char *content)
3162{
3163 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003164
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003165 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003166 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003167 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3168 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003169 BAD_CAST des, BAD_CAST message);
3170 else {
3171 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003172 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3173 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003174 BAD_CAST des, BAD_CAST content);
3175 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003176 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3177 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003178 BAD_CAST des, NULL);
3179 }
3180 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003181 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003182}
3183
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003184/************************************************************************
3185 * *
3186 * Streamable error functions *
3187 * *
3188 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00003189
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003190
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003191
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003192
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003193/************************************************************************
3194 * *
3195 * Validation helper functions *
3196 * *
3197 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003198
Daniel Veillardc0826a72004-08-10 14:17:33 +00003199
Daniel Veillard4255d502002-04-16 15:50:10 +00003200/************************************************************************
3201 * *
3202 * Allocation functions *
3203 * *
3204 ************************************************************************/
3205
3206/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003207 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00003208 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00003209 *
3210 * Allocate a new Schema structure.
3211 *
3212 * Returns the newly allocated structure or NULL in case or error
3213 */
3214static xmlSchemaPtr
3215xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3216{
3217 xmlSchemaPtr ret;
3218
3219 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3220 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003221 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003222 return (NULL);
3223 }
3224 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003225 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003226 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003227
3228 return (ret);
3229}
3230
3231/**
3232 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00003233 *
3234 * Allocate a new Facet structure.
3235 *
3236 * Returns the newly allocated structure or NULL in case or error
3237 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003238xmlSchemaFacetPtr
3239xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00003240{
3241 xmlSchemaFacetPtr ret;
3242
3243 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3244 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003245 return (NULL);
3246 }
3247 memset(ret, 0, sizeof(xmlSchemaFacet));
3248
3249 return (ret);
3250}
3251
3252/**
3253 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00003254 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00003255 * @node: a node
3256 *
3257 * Allocate a new annotation structure.
3258 *
3259 * Returns the newly allocated structure or NULL in case or error
3260 */
3261static xmlSchemaAnnotPtr
3262xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3263{
3264 xmlSchemaAnnotPtr ret;
3265
3266 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3267 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003268 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003269 return (NULL);
3270 }
3271 memset(ret, 0, sizeof(xmlSchemaAnnot));
3272 ret->content = node;
3273 return (ret);
3274}
3275
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003276static xmlSchemaItemListPtr
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003277xmlSchemaItemListCreate(void)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003278{
3279 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003280
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003281 ret = xmlMalloc(sizeof(xmlSchemaItemList));
3282 if (ret == NULL) {
3283 xmlSchemaPErrMemory(NULL,
3284 "allocating an item list structure", NULL);
3285 return (NULL);
3286 }
3287 memset(ret, 0, sizeof(xmlSchemaItemList));
3288 return (ret);
3289}
3290
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00003291static void
3292xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3293{
3294 if (list->items != NULL) {
3295 xmlFree(list->items);
3296 list->items = NULL;
3297 }
3298 list->nbItems = 0;
3299 list->sizeItems = 0;
3300}
3301
3302static int
3303xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3304{
3305 if (list->items == NULL) {
3306 list->items = (void **) xmlMalloc(
3307 20 * sizeof(void *));
3308 if (list->items == NULL) {
3309 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3310 return(-1);
3311 }
3312 list->sizeItems = 20;
3313 } else if (list->sizeItems <= list->nbItems) {
3314 list->sizeItems *= 2;
3315 list->items = (void **) xmlRealloc(list->items,
3316 list->sizeItems * sizeof(void *));
3317 if (list->items == NULL) {
3318 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3319 list->sizeItems = 0;
3320 return(-1);
3321 }
3322 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00003323 list->items[list->nbItems++] = item;
3324 return(0);
3325}
3326
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003327static int
3328xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3329 int initialSize,
3330 void *item)
3331{
3332 if (list->items == NULL) {
3333 if (initialSize <= 0)
3334 initialSize = 1;
3335 list->items = (void **) xmlMalloc(
3336 initialSize * sizeof(void *));
3337 if (list->items == NULL) {
3338 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3339 return(-1);
3340 }
3341 list->sizeItems = initialSize;
3342 } else if (list->sizeItems <= list->nbItems) {
3343 list->sizeItems *= 2;
3344 list->items = (void **) xmlRealloc(list->items,
3345 list->sizeItems * sizeof(void *));
3346 if (list->items == NULL) {
3347 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3348 list->sizeItems = 0;
3349 return(-1);
3350 }
3351 }
3352 list->items[list->nbItems++] = item;
3353 return(0);
3354}
3355
3356static int
3357xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3358{
3359 if (list->items == NULL) {
3360 list->items = (void **) xmlMalloc(
3361 20 * sizeof(void *));
3362 if (list->items == NULL) {
3363 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3364 return(-1);
3365 }
3366 list->sizeItems = 20;
3367 } else if (list->sizeItems <= list->nbItems) {
3368 list->sizeItems *= 2;
3369 list->items = (void **) xmlRealloc(list->items,
3370 list->sizeItems * sizeof(void *));
3371 if (list->items == NULL) {
3372 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3373 list->sizeItems = 0;
3374 return(-1);
3375 }
3376 }
3377 /*
3378 * Just append if the index is greater/equal than the item count.
3379 */
3380 if (idx >= list->nbItems) {
3381 list->items[list->nbItems++] = item;
3382 } else {
3383 int i;
3384 for (i = list->nbItems; i > idx; i--)
3385 list->items[i] = list->items[i-1];
3386 list->items[idx] = item;
3387 list->nbItems++;
3388 }
3389 return(0);
3390}
3391
3392#if 0 /* enable if ever needed */
3393static int
3394xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3395 int initialSize,
3396 void *item,
3397 int idx)
3398{
3399 if (list->items == NULL) {
3400 if (initialSize <= 0)
3401 initialSize = 1;
3402 list->items = (void **) xmlMalloc(
3403 initialSize * sizeof(void *));
3404 if (list->items == NULL) {
3405 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3406 return(-1);
3407 }
3408 list->sizeItems = initialSize;
3409 } else if (list->sizeItems <= list->nbItems) {
3410 list->sizeItems *= 2;
3411 list->items = (void **) xmlRealloc(list->items,
3412 list->sizeItems * sizeof(void *));
3413 if (list->items == NULL) {
3414 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3415 list->sizeItems = 0;
3416 return(-1);
3417 }
3418 }
3419 /*
3420 * Just append if the index is greater/equal than the item count.
3421 */
3422 if (idx >= list->nbItems) {
3423 list->items[list->nbItems++] = item;
3424 } else {
3425 int i;
3426 for (i = list->nbItems; i > idx; i--)
3427 list->items[i] = list->items[i-1];
3428 list->items[idx] = item;
3429 list->nbItems++;
3430 }
3431 return(0);
3432}
3433#endif
3434
3435static int
3436xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3437{
3438 int i;
3439 if ((list->items == NULL) || (idx >= list->nbItems)) {
3440 xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3441 "index error.\n");
3442 return(-1);
3443 }
3444
3445 if (list->nbItems == 1) {
3446 /* TODO: Really free the list? */
3447 xmlFree(list->items);
3448 list->items = NULL;
3449 list->nbItems = 0;
3450 list->sizeItems = 0;
3451 } else if (list->nbItems -1 == idx) {
3452 list->nbItems--;
3453 } else {
3454 for (i = idx; i < list->nbItems -1; i++)
3455 list->items[i] = list->items[i+1];
3456 list->nbItems--;
3457 }
3458 return(0);
3459}
3460
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003461/**
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003462 * xmlSchemaItemListFree:
3463 * @annot: a schema type structure
3464 *
3465 * Deallocate a annotation structure
3466 */
3467static void
3468xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3469{
3470 if (list == NULL)
3471 return;
3472 if (list->items != NULL)
3473 xmlFree(list->items);
3474 xmlFree(list);
3475}
3476
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003477static void
3478xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003479{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003480 if (bucket == NULL)
3481 return;
3482 if (bucket->globals != NULL) {
3483 xmlSchemaComponentListFree(bucket->globals);
3484 xmlSchemaItemListFree(bucket->globals);
3485 }
3486 if (bucket->locals != NULL) {
3487 xmlSchemaComponentListFree(bucket->locals);
3488 xmlSchemaItemListFree(bucket->locals);
3489 }
3490 if (bucket->relations != NULL) {
3491 xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3492 do {
3493 prev = cur;
3494 cur = cur->next;
3495 xmlFree(prev);
3496 } while (cur != NULL);
3497 }
3498 if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3499 xmlFreeDoc(bucket->doc);
3500 }
3501 if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003502 if (WXS_IMPBUCKET(bucket)->schema != NULL)
3503 xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003504 }
3505 xmlFree(bucket);
3506}
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003507
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003508static xmlSchemaBucketPtr
3509xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003510 int type, const xmlChar *targetNamespace)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003511{
3512 xmlSchemaBucketPtr ret;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003513 int size;
3514 xmlSchemaPtr mainSchema;
3515
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003516 if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003517 PERROR_INT("xmlSchemaBucketCreate",
3518 "no main schema on constructor");
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003519 return(NULL);
3520 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003521 mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003522 /* Create the schema bucket. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003523 if (WXS_IS_BUCKET_INCREDEF(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003524 size = sizeof(xmlSchemaInclude);
3525 else
3526 size = sizeof(xmlSchemaImport);
3527 ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3528 if (ret == NULL) {
3529 xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3530 return(NULL);
3531 }
3532 memset(ret, 0, size);
3533 ret->targetNamespace = targetNamespace;
3534 ret->type = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003535 ret->globals = xmlSchemaItemListCreate();
3536 if (ret->globals == NULL) {
3537 xmlFree(ret);
3538 return(NULL);
3539 }
3540 ret->locals = xmlSchemaItemListCreate();
3541 if (ret->locals == NULL) {
3542 xmlFree(ret);
3543 return(NULL);
3544 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003545 /*
3546 * The following will assure that only the first bucket is marked as
3547 * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3548 * For each following import buckets an xmlSchema will be created.
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003549 * An xmlSchema will be created for every distinct targetNamespace.
3550 * We assign the targetNamespace to the schemata here.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003551 */
3552 if (! WXS_HAS_BUCKETS(pctxt)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003553 if (WXS_IS_BUCKET_INCREDEF(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003554 PERROR_INT("xmlSchemaBucketCreate",
3555 "first bucket but it's an include or redefine");
3556 xmlSchemaBucketFree(ret);
3557 return(NULL);
3558 }
3559 /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3560 ret->type = XML_SCHEMA_SCHEMA_MAIN;
3561 /* Point to the *main* schema. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003562 WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3563 WXS_IMPBUCKET(ret)->schema = mainSchema;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003564 /*
3565 * Ensure that the main schema gets a targetNamespace.
3566 */
3567 mainSchema->targetNamespace = targetNamespace;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003568 } else {
3569 if (type == XML_SCHEMA_SCHEMA_MAIN) {
3570 PERROR_INT("xmlSchemaBucketCreate",
3571 "main bucket but it's not the first one");
3572 xmlSchemaBucketFree(ret);
3573 return(NULL);
3574 } else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3575 /*
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003576 * Create a schema for imports and assign the
3577 * targetNamespace.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003578 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003579 WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3580 if (WXS_IMPBUCKET(ret)->schema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003581 xmlSchemaBucketFree(ret);
3582 return(NULL);
3583 }
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003584 WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003585 }
3586 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003587 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003588 int res;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003589 /*
3590 * Imports go into the "schemasImports" slot of the main *schema*.
3591 * Note that we create an import entry for the main schema as well; i.e.,
3592 * even if there's only one schema, we'll get an import.
3593 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003594 if (mainSchema->schemasImports == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003595 mainSchema->schemasImports = xmlHashCreateDict(5,
3596 WXS_CONSTRUCTOR(pctxt)->dict);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003597 if (mainSchema->schemasImports == NULL) {
3598 xmlSchemaBucketFree(ret);
3599 return(NULL);
3600 }
3601 }
3602 if (targetNamespace == NULL)
3603 res = xmlHashAddEntry(mainSchema->schemasImports,
3604 XML_SCHEMAS_NO_NAMESPACE, ret);
3605 else
3606 res = xmlHashAddEntry(mainSchema->schemasImports,
3607 targetNamespace, ret);
3608 if (res != 0) {
3609 PERROR_INT("xmlSchemaBucketCreate",
3610 "failed to add the schema bucket to the hash");
3611 xmlSchemaBucketFree(ret);
3612 return(NULL);
3613 }
3614 } else {
3615 /* Set the @ownerImport of an include bucket. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003616 if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3617 WXS_INCBUCKET(ret)->ownerImport =
3618 WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003619 else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003620 WXS_INCBUCKET(ret)->ownerImport =
3621 WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003622
3623 /* Includes got into the "includes" slot of the *main* schema. */
3624 if (mainSchema->includes == NULL) {
3625 mainSchema->includes = xmlSchemaItemListCreate();
3626 if (mainSchema->includes == NULL) {
3627 xmlSchemaBucketFree(ret);
3628 return(NULL);
3629 }
3630 }
3631 xmlSchemaItemListAdd(mainSchema->includes, ret);
3632 }
3633 /*
3634 * Add to list of all buckets; this is used for lookup
3635 * during schema construction time only.
3636 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003637 if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003638 return(NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003639 return(ret);
3640}
3641
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003642static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003643xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003644{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003645 if (*list == NULL) {
3646 *list = xmlSchemaItemListCreate();
3647 if (*list == NULL)
3648 return(-1);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003649 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003650 xmlSchemaItemListAddSize(*list, initialSize, item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003651 return(0);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003652}
3653
3654/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00003655 * xmlSchemaFreeAnnot:
3656 * @annot: a schema type structure
3657 *
3658 * Deallocate a annotation structure
3659 */
3660static void
3661xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3662{
3663 if (annot == NULL)
3664 return;
Kasimier T. Buchcik004b5462005-08-08 12:43:09 +00003665 if (annot->next == NULL) {
3666 xmlFree(annot);
3667 } else {
3668 xmlSchemaAnnotPtr prev;
3669
3670 do {
3671 prev = annot;
3672 annot = annot->next;
3673 xmlFree(prev);
3674 } while (annot != NULL);
3675 }
Daniel Veillardfdc91562002-07-01 21:52:03 +00003676}
3677
3678/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003679 * xmlSchemaFreeNotation:
3680 * @schema: a schema notation structure
3681 *
3682 * Deallocate a Schema Notation structure.
3683 */
3684static void
3685xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3686{
3687 if (nota == NULL)
3688 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003689 xmlFree(nota);
3690}
3691
3692/**
3693 * xmlSchemaFreeAttribute:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003694 * @attr: an attribute declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00003695 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003696 * Deallocates an attribute declaration structure.
Daniel Veillard4255d502002-04-16 15:50:10 +00003697 */
3698static void
3699xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3700{
3701 if (attr == NULL)
3702 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003703 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003704 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003705 if (attr->defVal != NULL)
3706 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003707 xmlFree(attr);
3708}
3709
3710/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003711 * xmlSchemaFreeAttributeUse:
3712 * @use: an attribute use
3713 *
3714 * Deallocates an attribute use structure.
3715 */
3716static void
3717xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3718{
3719 if (use == NULL)
3720 return;
3721 if (use->annot != NULL)
3722 xmlSchemaFreeAnnot(use->annot);
3723 if (use->defVal != NULL)
3724 xmlSchemaFreeValue(use->defVal);
3725 xmlFree(use);
3726}
3727
3728/**
3729 * xmlSchemaFreeAttributeUseProhib:
3730 * @prohib: an attribute use prohibition
3731 *
3732 * Deallocates an attribute use structure.
3733 */
3734static void
3735xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3736{
3737 if (prohib == NULL)
3738 return;
3739 xmlFree(prohib);
3740}
3741
3742/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003743 * xmlSchemaFreeWildcardNsSet:
3744 * set: a schema wildcard namespace
3745 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003746 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00003747 */
3748static void
3749xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3750{
3751 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003752
Daniel Veillard3646d642004-06-02 19:19:14 +00003753 while (set != NULL) {
3754 next = set->next;
3755 xmlFree(set);
3756 set = next;
3757 }
3758}
3759
3760/**
3761 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003762 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00003763 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003764 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00003765 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003766void
Daniel Veillard3646d642004-06-02 19:19:14 +00003767xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3768{
3769 if (wildcard == NULL)
3770 return;
3771 if (wildcard->annot != NULL)
3772 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003773 if (wildcard->nsSet != NULL)
3774 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3775 if (wildcard->negNsSet != NULL)
3776 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00003777 xmlFree(wildcard);
3778}
3779
3780/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003781 * xmlSchemaFreeAttributeGroup:
3782 * @schema: a schema attribute group structure
3783 *
3784 * Deallocate a Schema Attribute Group structure.
3785 */
3786static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003787xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
Daniel Veillard4255d502002-04-16 15:50:10 +00003788{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003789 if (attrGr == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00003790 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003791 if (attrGr->annot != NULL)
3792 xmlSchemaFreeAnnot(attrGr->annot);
3793 if (attrGr->attrUses != NULL)
3794 xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3795 xmlFree(attrGr);
Daniel Veillard3646d642004-06-02 19:19:14 +00003796}
3797
3798/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003799 * xmlSchemaFreeQNameRef:
3800 * @item: a QName reference structure
3801 *
3802 * Deallocatea a QName reference structure.
3803 */
3804static void
3805xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3806{
3807 xmlFree(item);
3808}
3809
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003810/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003811 * xmlSchemaFreeTypeLinkList:
3812 * @alink: a type link
3813 *
3814 * Deallocate a list of types.
3815 */
3816static void
3817xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3818{
3819 xmlSchemaTypeLinkPtr next;
3820
3821 while (link != NULL) {
3822 next = link->next;
3823 xmlFree(link);
3824 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003825 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003826}
3827
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003828static void
3829xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3830{
3831 xmlSchemaIDCStateObjPtr next;
3832 while (sto != NULL) {
3833 next = sto->next;
3834 if (sto->history != NULL)
3835 xmlFree(sto->history);
3836 if (sto->xpathCtxt != NULL)
3837 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3838 xmlFree(sto);
3839 sto = next;
3840 }
3841}
3842
3843/**
3844 * xmlSchemaFreeIDC:
3845 * @idc: a identity-constraint definition
3846 *
3847 * Deallocates an identity-constraint definition.
3848 */
3849static void
3850xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3851{
3852 xmlSchemaIDCSelectPtr cur, prev;
3853
3854 if (idcDef == NULL)
3855 return;
3856 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003857 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003858 /* Selector */
3859 if (idcDef->selector != NULL) {
3860 if (idcDef->selector->xpathComp != NULL)
3861 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3862 xmlFree(idcDef->selector);
3863 }
3864 /* Fields */
3865 if (idcDef->fields != NULL) {
3866 cur = idcDef->fields;
3867 do {
3868 prev = cur;
3869 cur = cur->next;
3870 if (prev->xpathComp != NULL)
3871 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003872 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003873 } while (cur != NULL);
3874 }
3875 xmlFree(idcDef);
3876}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003877
Daniel Veillard01fa6152004-06-29 17:04:39 +00003878/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003879 * xmlSchemaFreeElement:
3880 * @schema: a schema element structure
3881 *
3882 * Deallocate a Schema Element structure.
3883 */
3884static void
3885xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3886{
3887 if (elem == NULL)
3888 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003889 if (elem->annot != NULL)
3890 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003891 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003892 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003893 if (elem->defVal != NULL)
3894 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003895 xmlFree(elem);
3896}
3897
3898/**
3899 * xmlSchemaFreeFacet:
3900 * @facet: a schema facet structure
3901 *
3902 * Deallocate a Schema Facet structure.
3903 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003904void
Daniel Veillard4255d502002-04-16 15:50:10 +00003905xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3906{
3907 if (facet == NULL)
3908 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003909 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003910 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003911 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003912 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003913 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003914 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003915 xmlFree(facet);
3916}
3917
3918/**
3919 * xmlSchemaFreeType:
3920 * @type: a schema type structure
3921 *
3922 * Deallocate a Schema Type structure.
3923 */
3924void
3925xmlSchemaFreeType(xmlSchemaTypePtr type)
3926{
3927 if (type == NULL)
3928 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003929 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003930 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003931 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003932 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003933
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003934 facet = type->facets;
3935 while (facet != NULL) {
3936 next = facet->next;
3937 xmlSchemaFreeFacet(facet);
3938 facet = next;
3939 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003940 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003941 if (type->attrUses != NULL)
3942 xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003943 if (type->memberTypes != NULL)
3944 xmlSchemaFreeTypeLinkList(type->memberTypes);
3945 if (type->facetSet != NULL) {
3946 xmlSchemaFacetLinkPtr next, link;
3947
3948 link = type->facetSet;
3949 do {
3950 next = link->next;
3951 xmlFree(link);
3952 link = next;
3953 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003954 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003955 if (type->contModel != NULL)
3956 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003957 xmlFree(type);
3958}
3959
3960/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003961 * xmlSchemaFreeModelGroupDef:
3962 * @item: a schema model group definition
3963 *
3964 * Deallocates a schema model group definition.
3965 */
3966static void
3967xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3968{
3969 if (item->annot != NULL)
3970 xmlSchemaFreeAnnot(item->annot);
3971 xmlFree(item);
3972}
3973
3974/**
3975 * xmlSchemaFreeModelGroup:
3976 * @item: a schema model group
3977 *
3978 * Deallocates a schema model group structure.
3979 */
3980static void
3981xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3982{
3983 if (item->annot != NULL)
3984 xmlSchemaFreeAnnot(item->annot);
3985 xmlFree(item);
3986}
3987
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003988static void
3989xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
3990{
3991 if ((list == NULL) || (list->nbItems == 0))
3992 return;
3993 {
3994 xmlSchemaTreeItemPtr item;
3995 xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
3996 int i;
3997
3998 for (i = 0; i < list->nbItems; i++) {
3999 item = items[i];
4000 if (item == NULL)
4001 continue;
4002 switch (item->type) {
4003 case XML_SCHEMA_TYPE_SIMPLE:
4004 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004005 xmlSchemaFreeType((xmlSchemaTypePtr) item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004006 break;
4007 case XML_SCHEMA_TYPE_ATTRIBUTE:
4008 xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004009 break;
4010 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4011 xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4012 break;
4013 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4014 xmlSchemaFreeAttributeUseProhib(
4015 (xmlSchemaAttributeUseProhibPtr) item);
4016 break;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004017 case XML_SCHEMA_TYPE_ELEMENT:
4018 xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4019 break;
4020 case XML_SCHEMA_TYPE_PARTICLE:
4021 if (item->annot != NULL)
4022 xmlSchemaFreeAnnot(item->annot);
4023 xmlFree(item);
4024 break;
4025 case XML_SCHEMA_TYPE_SEQUENCE:
4026 case XML_SCHEMA_TYPE_CHOICE:
4027 case XML_SCHEMA_TYPE_ALL:
4028 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4029 break;
4030 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4031 xmlSchemaFreeAttributeGroup(
4032 (xmlSchemaAttributeGroupPtr) item);
4033 break;
4034 case XML_SCHEMA_TYPE_GROUP:
4035 xmlSchemaFreeModelGroupDef(
4036 (xmlSchemaModelGroupDefPtr) item);
4037 break;
4038 case XML_SCHEMA_TYPE_ANY:
4039 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4040 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4041 break;
4042 case XML_SCHEMA_TYPE_IDC_KEY:
4043 case XML_SCHEMA_TYPE_IDC_UNIQUE:
4044 case XML_SCHEMA_TYPE_IDC_KEYREF:
4045 xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4046 break;
4047 case XML_SCHEMA_TYPE_NOTATION:
4048 xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4049 break;
4050 case XML_SCHEMA_EXTRA_QNAMEREF:
4051 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4052 break;
4053 default: {
4054 /* TODO: This should never be hit. */
4055 xmlSchemaPSimpleInternalErr(NULL,
4056 "Internal error: xmlSchemaComponentListFree, "
4057 "unexpected component type '%s'\n",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004058 (const xmlChar *) WXS_ITEM_TYPE_NAME(item));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004059 }
4060 break;
4061 }
4062 }
4063 list->nbItems = 0;
4064 }
4065}
4066
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004067/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004068 * xmlSchemaFree:
4069 * @schema: a schema structure
4070 *
4071 * Deallocate a Schema structure.
4072 */
4073void
4074xmlSchemaFree(xmlSchemaPtr schema)
4075{
4076 if (schema == NULL)
4077 return;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004078 /* @volatiles is not used anymore :-/ */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004079 if (schema->volatiles != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004080 TODO
4081 /*
4082 * Note that those slots are not responsible for freeing
4083 * schema components anymore; this will now be done by
4084 * the schema buckets.
4085 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004086 if (schema->notaDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004087 xmlHashFree(schema->notaDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004088 if (schema->attrDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004089 xmlHashFree(schema->attrDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004090 if (schema->attrgrpDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004091 xmlHashFree(schema->attrgrpDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004092 if (schema->elemDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004093 xmlHashFree(schema->elemDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004094 if (schema->typeDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004095 xmlHashFree(schema->typeDecl, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004096 if (schema->groupDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004097 xmlHashFree(schema->groupDecl, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004098 if (schema->idcDef != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004099 xmlHashFree(schema->idcDef, NULL);
4100
Daniel Veillard1d913862003-11-21 00:28:39 +00004101 if (schema->schemasImports != NULL)
4102 xmlHashFree(schema->schemasImports,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004103 (xmlHashDeallocator) xmlSchemaBucketFree);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004104 if (schema->includes != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004105 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4106 int i;
4107 for (i = 0; i < list->nbItems; i++) {
4108 xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4109 }
4110 xmlSchemaItemListFree(list);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004111 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004112 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004113 xmlSchemaFreeAnnot(schema->annot);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004114 /* Never free the doc here, since this will be done by the buckets. */
4115
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004116 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004117 xmlFree(schema);
4118}
4119
4120/************************************************************************
4121 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00004122 * Debug functions *
4123 * *
4124 ************************************************************************/
4125
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00004126#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004127
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004128static void
4129xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4130
Daniel Veillard4255d502002-04-16 15:50:10 +00004131/**
4132 * xmlSchemaElementDump:
4133 * @elem: an element
4134 * @output: the file output
4135 *
4136 * Dump the element
4137 */
4138static void
4139xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004140 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004141 const xmlChar * namespace ATTRIBUTE_UNUSED,
4142 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00004143{
4144 if (elem == NULL)
4145 return;
4146
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004147
4148 fprintf(output, "Element");
4149 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4150 fprintf(output, " (global)");
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004151 fprintf(output, ": '%s' ", elem->name);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004152 if (namespace != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004153 fprintf(output, "ns '%s'", namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004154 fprintf(output, "\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004155#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004156 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004157 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004158 if (elem->maxOccurs >= UNBOUNDED)
4159 fprintf(output, "max: unbounded\n");
4160 else if (elem->maxOccurs != 1)
4161 fprintf(output, "max: %d\n", elem->maxOccurs);
4162 else
4163 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00004164 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004165#endif
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004166 /*
4167 * Misc other properties.
4168 */
4169 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4170 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4171 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004172 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004173 fprintf(output, " props: ");
4174 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4175 fprintf(output, "[fixed] ");
4176 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4177 fprintf(output, "[default] ");
4178 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4179 fprintf(output, "[abstract] ");
4180 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4181 fprintf(output, "[nillable] ");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004182 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00004183 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004184 /*
4185 * Default/fixed value.
4186 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004187 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004188 fprintf(output, " value: '%s'\n", elem->value);
4189 /*
4190 * Type.
4191 */
4192 if (elem->namedType != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004193 fprintf(output, " type: '%s' ", elem->namedType);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004194 if (elem->namedTypeNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004195 fprintf(output, "ns '%s'\n", elem->namedTypeNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004196 else
4197 fprintf(output, "\n");
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004198 } else if (elem->subtypes != NULL) {
4199 /*
4200 * Dump local types.
4201 */
4202 xmlSchemaTypeDump(elem->subtypes, output);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004203 }
4204 /*
4205 * Substitution group.
4206 */
4207 if (elem->substGroup != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004208 fprintf(output, " substitutionGroup: '%s' ", elem->substGroup);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004209 if (elem->substGroupNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004210 fprintf(output, "ns '%s'\n", elem->substGroupNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004211 else
4212 fprintf(output, "\n");
4213 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004214}
4215
4216/**
4217 * xmlSchemaAnnotDump:
4218 * @output: the file output
4219 * @annot: a annotation
4220 *
4221 * Dump the annotation
4222 */
4223static void
4224xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4225{
4226 xmlChar *content;
4227
4228 if (annot == NULL)
4229 return;
4230
4231 content = xmlNodeGetContent(annot->content);
4232 if (content != NULL) {
4233 fprintf(output, " Annot: %s\n", content);
4234 xmlFree(content);
4235 } else
4236 fprintf(output, " Annot: empty\n");
4237}
4238
4239/**
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004240 * xmlSchemaContentModelDump:
4241 * @particle: the schema particle
4242 * @output: the file output
4243 * @depth: the depth used for intentation
Daniel Veillard4255d502002-04-16 15:50:10 +00004244 *
4245 * Dump a SchemaType structure
4246 */
4247static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004248xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4249{
4250 xmlChar *str = NULL;
4251 xmlSchemaTreeItemPtr term;
4252 char shift[100];
4253 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004254
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004255 if (particle == NULL)
4256 return;
4257 for (i = 0;((i < depth) && (i < 25));i++)
4258 shift[2 * i] = shift[2 * i + 1] = ' ';
4259 shift[2 * i] = shift[2 * i + 1] = 0;
4260 fprintf(output, shift);
4261 if (particle->children == NULL) {
4262 fprintf(output, "MISSING particle term\n");
4263 return;
4264 }
4265 term = particle->children;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004266 if (term == NULL) {
4267 fprintf(output, "(NULL)");
4268 } else {
4269 switch (term->type) {
4270 case XML_SCHEMA_TYPE_ELEMENT:
4271 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4272 ((xmlSchemaElementPtr)term)->targetNamespace,
4273 ((xmlSchemaElementPtr)term)->name));
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004274 FREE_AND_NULL(str);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004275 break;
4276 case XML_SCHEMA_TYPE_SEQUENCE:
4277 fprintf(output, "SEQUENCE");
4278 break;
4279 case XML_SCHEMA_TYPE_CHOICE:
4280 fprintf(output, "CHOICE");
4281 break;
4282 case XML_SCHEMA_TYPE_ALL:
4283 fprintf(output, "ALL");
4284 break;
4285 case XML_SCHEMA_TYPE_ANY:
4286 fprintf(output, "ANY");
4287 break;
4288 default:
4289 fprintf(output, "UNKNOWN\n");
4290 return;
4291 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004292 }
4293 if (particle->minOccurs != 1)
4294 fprintf(output, " min: %d", particle->minOccurs);
4295 if (particle->maxOccurs >= UNBOUNDED)
4296 fprintf(output, " max: unbounded");
4297 else if (particle->maxOccurs != 1)
4298 fprintf(output, " max: %d", particle->maxOccurs);
4299 fprintf(output, "\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004300 if (term &&
4301 ((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4302 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4303 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4304 (term->children != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004305 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4306 output, depth +1);
4307 }
4308 if (particle->next != NULL)
4309 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4310 output, depth);
4311}
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004312
4313/**
4314 * xmlSchemaAttrUsesDump:
4315 * @uses: attribute uses list
4316 * @output: the file output
4317 *
4318 * Dumps a list of attribute use components.
4319 */
4320static void
4321xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4322{
4323 xmlSchemaAttributeUsePtr use;
4324 xmlSchemaAttributeUseProhibPtr prohib;
4325 xmlSchemaQNameRefPtr ref;
4326 const xmlChar *name, *tns;
4327 xmlChar *str = NULL;
4328 int i;
4329
4330 if ((uses == NULL) || (uses->nbItems == 0))
4331 return;
4332
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004333 fprintf(output, " attributes:\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004334 for (i = 0; i < uses->nbItems; i++) {
4335 use = uses->items[i];
4336 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4337 fprintf(output, " [prohibition] ");
4338 prohib = (xmlSchemaAttributeUseProhibPtr) use;
4339 name = prohib->name;
4340 tns = prohib->targetNamespace;
4341 } else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4342 fprintf(output, " [reference] ");
4343 ref = (xmlSchemaQNameRefPtr) use;
4344 name = ref->name;
4345 tns = ref->targetNamespace;
4346 } else {
4347 fprintf(output, " [use] ");
4348 name = WXS_ATTRUSE_DECL_NAME(use);
4349 tns = WXS_ATTRUSE_DECL_TNS(use);
4350 }
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004351 fprintf(output, "'%s'\n",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004352 (const char *) xmlSchemaFormatQName(&str, tns, name));
4353 FREE_AND_NULL(str);
4354 }
4355}
4356
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004357/**
4358 * xmlSchemaTypeDump:
4359 * @output: the file output
4360 * @type: a type structure
4361 *
4362 * Dump a SchemaType structure
4363 */
4364static void
Daniel Veillard4255d502002-04-16 15:50:10 +00004365xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4366{
4367 if (type == NULL) {
4368 fprintf(output, "Type: NULL\n");
4369 return;
4370 }
4371 fprintf(output, "Type: ");
4372 if (type->name != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004373 fprintf(output, "'%s' ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004374 else
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004375 fprintf(output, "(no name) ");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004376 if (type->targetNamespace != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004377 fprintf(output, "ns '%s' ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004378 switch (type->type) {
4379 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004380 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004381 break;
4382 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004383 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004384 break;
4385 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004386 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004387 break;
4388 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004389 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004390 break;
4391 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004392 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004393 break;
4394 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004395 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004396 break;
4397 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004398 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004399 break;
4400 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004401 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004402 break;
4403 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004404 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004405 break;
4406 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004407 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00004408 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004409 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004410 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004411 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004412 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004413 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004414 break;
4415 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004416 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004417 break;
4418 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004419 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004420 break;
4421 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004422 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004423 break;
4424 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004425 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004426 break;
4427 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004428 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004429 break;
4430 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004431 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004432 break;
4433 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004434 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004435 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00004436 }
4437 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004438 if (type->base != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004439 fprintf(output, " base type: '%s'", type->base);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004440 if (type->baseNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004441 fprintf(output, " ns '%s'\n", type->baseNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004442 else
4443 fprintf(output, "\n");
4444 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004445 if (type->attrUses != NULL)
4446 xmlSchemaAttrUsesDump(type->attrUses, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00004447 if (type->annot != NULL)
4448 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004449#ifdef DUMP_CONTENT_MODEL
4450 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4451 (type->subtypes != NULL)) {
4452 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4453 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004454 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004455#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004456}
4457
4458/**
4459 * xmlSchemaDump:
4460 * @output: the file output
4461 * @schema: a schema structure
4462 *
4463 * Dump a Schema structure.
4464 */
4465void
4466xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4467{
Daniel Veillardce682bc2004-11-05 17:22:25 +00004468 if (output == NULL)
4469 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004470 if (schema == NULL) {
4471 fprintf(output, "Schemas: NULL\n");
4472 return;
4473 }
4474 fprintf(output, "Schemas: ");
4475 if (schema->name != NULL)
4476 fprintf(output, "%s, ", schema->name);
4477 else
4478 fprintf(output, "no name, ");
4479 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00004480 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004481 else
4482 fprintf(output, "no target namespace");
4483 fprintf(output, "\n");
4484 if (schema->annot != NULL)
4485 xmlSchemaAnnotDump(output, schema->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00004486 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
4487 output);
4488 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004489 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00004490}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004491
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004492#ifdef DEBUG_IDC_NODE_TABLE
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004493/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004494 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004495 * @vctxt: the WXS validation context
4496 *
4497 * Displays the current IDC table for debug purposes.
4498 */
4499static void
4500xmlSchemaDebugDumpIDCTable(FILE * output,
4501 const xmlChar *namespaceName,
4502 const xmlChar *localName,
4503 xmlSchemaPSVIIDCBindingPtr bind)
4504{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004505 xmlChar *str = NULL;
4506 const xmlChar *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004507 xmlSchemaPSVIIDCNodePtr tab;
4508 xmlSchemaPSVIIDCKeyPtr key;
4509 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004510
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004511 fprintf(output, "IDC: TABLES on '%s'\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004512 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004513 FREE_AND_NULL(str)
4514
4515 if (bind == NULL)
4516 return;
4517 do {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004518 fprintf(output, "IDC: BINDING '%s' (%d)\n",
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004519 xmlSchemaGetComponentQName(&str,
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004520 bind->definition), bind->nbNodes);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004521 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004522 for (i = 0; i < bind->nbNodes; i++) {
4523 tab = bind->nodeTable[i];
4524 fprintf(output, " ( ");
4525 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004526 key = tab->keys[j];
4527 if ((key != NULL) && (key->val != NULL)) {
4528 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004529 if (res >= 0)
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004530 fprintf(output, "'%s' ", value);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004531 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004532 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004533 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004534 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004535 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004536 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004537 else
4538 fprintf(output, "(key missing), ");
4539 }
4540 fprintf(output, ")\n");
4541 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004542 if (bind->dupls && bind->dupls->nbItems) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004543 fprintf(output, "IDC: dupls (%d):\n", bind->dupls->nbItems);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004544 for (i = 0; i < bind->dupls->nbItems; i++) {
4545 tab = bind->dupls->items[i];
4546 fprintf(output, " ( ");
4547 for (j = 0; j < bind->definition->nbFields; j++) {
4548 key = tab->keys[j];
4549 if ((key != NULL) && (key->val != NULL)) {
4550 res = xmlSchemaGetCanonValue(key->val, &value);
4551 if (res >= 0)
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004552 fprintf(output, "'%s' ", value);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004553 else
4554 fprintf(output, "CANON-VALUE-FAILED ");
4555 if (res == 0)
4556 FREE_AND_NULL(value)
4557 } else if (key != NULL)
4558 fprintf(output, "(no val), ");
4559 else
4560 fprintf(output, "(key missing), ");
4561 }
4562 fprintf(output, ")\n");
4563 }
4564 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004565 bind = bind->next;
4566 } while (bind != NULL);
4567}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00004568#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00004569#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00004570
4571/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004572 * *
4573 * Utilities *
4574 * *
4575 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004576
Daniel Veillardc0826a72004-08-10 14:17:33 +00004577/**
4578 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004579 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00004580 * @name: the name of the attribute
4581 *
4582 * Seeks an attribute with a name of @name in
4583 * no namespace.
4584 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004585 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00004586 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004587static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004588xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00004589{
4590 xmlAttrPtr prop;
4591
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004592 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004593 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004594 prop = node->properties;
4595 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004596 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004597 return(prop);
4598 prop = prop->next;
4599 }
4600 return (NULL);
4601}
4602
4603/**
4604 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004605 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00004606 * @uri: the uri
4607 * @name: the name of the attribute
4608 *
4609 * Seeks an attribute with a local name of @name and
4610 * a namespace URI of @uri.
4611 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004612 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00004613 */
4614static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004615xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00004616{
4617 xmlAttrPtr prop;
4618
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004619 if ((node == NULL) || (name == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004620 return(NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004621 prop = node->properties;
4622 while (prop != NULL) {
4623 if ((prop->ns != NULL) &&
4624 xmlStrEqual(prop->name, BAD_CAST name) &&
4625 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00004626 return(prop);
4627 prop = prop->next;
4628 }
4629 return (NULL);
4630}
4631
4632static const xmlChar *
4633xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4634{
4635 xmlChar *val;
4636 const xmlChar *ret;
4637
4638 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004639 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00004640 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00004641 ret = xmlDictLookup(ctxt->dict, val, -1);
4642 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004643 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004644}
4645
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004646static const xmlChar *
4647xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4648{
4649 return((const xmlChar*) xmlNodeGetContent(node));
4650}
4651
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004652/**
4653 * xmlSchemaGetProp:
4654 * @ctxt: the parser context
4655 * @node: the node
4656 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004657 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004658 * Read a attribute value and internalize the string
4659 *
4660 * Returns the string or NULL if not present.
4661 */
4662static const xmlChar *
4663xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4664 const char *name)
4665{
4666 xmlChar *val;
4667 const xmlChar *ret;
4668
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004669 val = xmlGetNoNsProp(node, BAD_CAST name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004670 if (val == NULL)
4671 return(NULL);
4672 ret = xmlDictLookup(ctxt->dict, val, -1);
4673 xmlFree(val);
4674 return(ret);
4675}
4676
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004677/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00004678 * *
4679 * Parsing functions *
4680 * *
4681 ************************************************************************/
4682
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004683#define WXS_FIND_GLOBAL_ITEM(slot) \
4684 if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4685 ret = xmlHashLookup(schema->slot, name); \
4686 if (ret != NULL) goto exit; \
4687 } \
4688 if (xmlHashSize(schema->schemasImports) > 1) { \
4689 xmlSchemaImportPtr import; \
4690 if (nsName == NULL) \
4691 import = xmlHashLookup(schema->schemasImports, \
4692 XML_SCHEMAS_NO_NAMESPACE); \
4693 else \
4694 import = xmlHashLookup(schema->schemasImports, nsName); \
4695 if (import == NULL) \
4696 goto exit; \
4697 ret = xmlHashLookup(import->schema->slot, name); \
4698 }
4699
Daniel Veillard4255d502002-04-16 15:50:10 +00004700/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004701 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004702 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004703 * @name: the element name
4704 * @ns: the element namespace
4705 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004706 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004707 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004708 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004709 */
4710static xmlSchemaElementPtr
4711xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004712 const xmlChar * nsName)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004713{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004714 xmlSchemaElementPtr ret = NULL;
4715
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004716 if ((name == NULL) || (schema == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004717 return(NULL);
4718 if (schema != NULL) {
4719 WXS_FIND_GLOBAL_ITEM(elemDecl)
4720 }
4721exit:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004722#ifdef DEBUG
4723 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004724 if (nsName == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004725 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004726 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004727 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004728 nsName);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004729 }
4730#endif
4731 return (ret);
4732}
4733
4734/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004735 * xmlSchemaGetType:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004736 * @schema: the main schema
4737 * @name: the type's name
4738 * nsName: the type's namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004739 *
4740 * Lookup a type in the schemas or the predefined types
4741 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004742 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00004743 */
4744static xmlSchemaTypePtr
4745xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004746 const xmlChar * nsName)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004747{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004748 xmlSchemaTypePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004749
4750 if (name == NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004751 return (NULL);
4752 /* First try the built-in types. */
4753 if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4754 ret = xmlSchemaGetPredefinedType(name, nsName);
4755 if (ret != NULL)
4756 goto exit;
4757 /*
4758 * Note that we try the parsed schemas as well here
4759 * since one might have parsed the S4S, which contain more
4760 * than the built-in types.
4761 * TODO: Can we optimize this?
4762 */
4763 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004764 if (schema != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004765 WXS_FIND_GLOBAL_ITEM(typeDecl)
4766 }
4767exit:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004768
Daniel Veillard4255d502002-04-16 15:50:10 +00004769#ifdef DEBUG
4770 if (ret == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004771 if (nsName == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004772 fprintf(stderr, "Unable to lookup type %s", name);
4773 else
4774 fprintf(stderr, "Unable to lookup type %s:%s", name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004775 nsName);
Daniel Veillard4255d502002-04-16 15:50:10 +00004776 }
4777#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004778 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004779}
4780
Daniel Veillard3646d642004-06-02 19:19:14 +00004781/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004782 * xmlSchemaGetAttributeDecl:
4783 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004784 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004785 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004786 *
4787 * Lookup a an attribute in the schema or imported schemas
4788 *
4789 * Returns the attribute declaration or NULL if not found.
4790 */
4791static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004792xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004793 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004794{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004795 xmlSchemaAttributePtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004796
4797 if ((name == NULL) || (schema == NULL))
4798 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004799 if (schema != NULL) {
4800 WXS_FIND_GLOBAL_ITEM(attrDecl)
Daniel Veillard3646d642004-06-02 19:19:14 +00004801 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004802exit:
Daniel Veillard3646d642004-06-02 19:19:14 +00004803#ifdef DEBUG
4804 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004805 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004806 fprintf(stderr, "Unable to lookup attribute %s", name);
4807 else
4808 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004809 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004810 }
4811#endif
4812 return (ret);
4813}
4814
4815/**
4816 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004817 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004818 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004819 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004820 *
4821 * Lookup a an attribute group in the schema or imported schemas
4822 *
4823 * Returns the attribute group definition or NULL if not found.
4824 */
4825static xmlSchemaAttributeGroupPtr
4826xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004827 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004828{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004829 xmlSchemaAttributeGroupPtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004830
4831 if ((name == NULL) || (schema == NULL))
4832 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004833 if (schema != NULL) {
4834 WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4835 }
4836exit:
4837 /* TODO:
4838 if ((ret != NULL) && (ret->redef != NULL)) {
4839 * Return the last redefinition. *
4840 ret = ret->redef;
Daniel Veillard3646d642004-06-02 19:19:14 +00004841 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004842 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004843#ifdef DEBUG
4844 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004845 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004846 fprintf(stderr, "Unable to lookup attribute group %s", name);
4847 else
4848 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004849 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004850 }
4851#endif
4852 return (ret);
4853}
4854
4855/**
4856 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004857 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004858 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004859 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004860 *
4861 * Lookup a group in the schema or imported schemas
4862 *
4863 * Returns the group definition or NULL if not found.
4864 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004865static xmlSchemaModelGroupDefPtr
Daniel Veillard3646d642004-06-02 19:19:14 +00004866xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004867 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004868{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004869 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004870
4871 if ((name == NULL) || (schema == NULL))
4872 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004873 if (schema != NULL) {
4874 WXS_FIND_GLOBAL_ITEM(groupDecl)
Daniel Veillard3646d642004-06-02 19:19:14 +00004875 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004876exit:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004877
Daniel Veillard3646d642004-06-02 19:19:14 +00004878#ifdef DEBUG
4879 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004880 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004881 fprintf(stderr, "Unable to lookup group %s", name);
4882 else
4883 fprintf(stderr, "Unable to lookup group %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004884 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004885 }
4886#endif
4887 return (ret);
4888}
4889
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004890static xmlSchemaNotationPtr
4891xmlSchemaGetNotation(xmlSchemaPtr schema,
4892 const xmlChar *name,
4893 const xmlChar *nsName)
4894{
4895 xmlSchemaNotationPtr ret = NULL;
4896
4897 if ((name == NULL) || (schema == NULL))
4898 return (NULL);
4899 if (schema != NULL) {
4900 WXS_FIND_GLOBAL_ITEM(notaDecl)
4901 }
4902exit:
4903 return (ret);
4904}
4905
4906static xmlSchemaIDCPtr
4907xmlSchemaGetIDC(xmlSchemaPtr schema,
4908 const xmlChar *name,
4909 const xmlChar *nsName)
4910{
4911 xmlSchemaIDCPtr ret = NULL;
4912
4913 if ((name == NULL) || (schema == NULL))
4914 return (NULL);
4915 if (schema != NULL) {
4916 WXS_FIND_GLOBAL_ITEM(idcDef)
4917 }
4918exit:
4919 return (ret);
4920}
4921
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004922/**
4923 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004924 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004925 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004926 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004927 *
4928 * Lookup a group in the schema or imported schemas
4929 *
4930 * Returns the group definition or NULL if not found.
4931 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004932static xmlSchemaBasicItemPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004933xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4934 xmlSchemaTypeType itemType,
4935 const xmlChar *name,
4936 const xmlChar *targetNs)
4937{
4938 switch (itemType) {
4939 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004940 return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004941 name, targetNs));
4942 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004943 return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004944 name, targetNs));
4945 default:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004946 TODO
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004947 return (NULL);
4948 }
4949}
4950
Daniel Veillard4255d502002-04-16 15:50:10 +00004951/************************************************************************
4952 * *
4953 * Parsing functions *
4954 * *
4955 ************************************************************************/
4956
4957#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004958 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00004959
4960/**
4961 * xmlSchemaIsBlank:
4962 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004963 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00004964 *
4965 * Check if a string is ignorable
4966 *
4967 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4968 */
4969static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004970xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004971{
Daniel Veillard4255d502002-04-16 15:50:10 +00004972 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004973 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004974 if (len < 0) {
4975 while (*str != 0) {
4976 if (!(IS_BLANK_CH(*str)))
4977 return (0);
4978 str++;
4979 }
4980 } else while ((*str != 0) && (len != 0)) {
4981 if (!(IS_BLANK_CH(*str)))
4982 return (0);
4983 str++;
4984 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00004985 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004986
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004987 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004988}
4989
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004990#define WXS_COMP_NAME(c, t) ((t) (c))->name
4991#define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
4992/*
4993* xmlSchemaFindRedefCompInGraph:
4994* ATTENTION TODO: This uses pointer comp. for strings.
4995*/
4996static xmlSchemaBasicItemPtr
4997xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
4998 xmlSchemaTypeType type,
4999 const xmlChar *name,
5000 const xmlChar *nsName)
5001{
5002 xmlSchemaBasicItemPtr ret;
5003 int i;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005004
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005005 if ((bucket == NULL) || (name == NULL))
5006 return(NULL);
5007 if ((bucket->globals == NULL) ||
5008 (bucket->globals->nbItems == 0))
5009 goto subschemas;
5010 /*
5011 * Search in global components.
5012 */
5013 for (i = 0; i < bucket->globals->nbItems; i++) {
5014 ret = bucket->globals->items[i];
5015 if (ret->type == type) {
5016 switch (type) {
5017 case XML_SCHEMA_TYPE_COMPLEX:
5018 case XML_SCHEMA_TYPE_SIMPLE:
5019 if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5020 (WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5021 nsName))
5022 {
5023 return(ret);
5024 }
5025 break;
5026 case XML_SCHEMA_TYPE_GROUP:
5027 if ((WXS_COMP_NAME(ret,
5028 xmlSchemaModelGroupDefPtr) == name) &&
5029 (WXS_COMP_TNS(ret,
5030 xmlSchemaModelGroupDefPtr) == nsName))
5031 {
5032 return(ret);
5033 }
5034 break;
5035 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5036 if ((WXS_COMP_NAME(ret,
5037 xmlSchemaAttributeGroupPtr) == name) &&
5038 (WXS_COMP_TNS(ret,
5039 xmlSchemaAttributeGroupPtr) == nsName))
5040 {
5041 return(ret);
5042 }
Kasimier T. Buchcik5d2998b2005-11-22 17:36:01 +00005043 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005044 default:
5045 /* Should not be hit. */
5046 return(NULL);
5047 }
5048 }
5049 }
5050subschemas:
5051 /*
5052 * Process imported/included schemas.
5053 */
5054 if (bucket->relations != NULL) {
5055 xmlSchemaSchemaRelationPtr rel = bucket->relations;
5056
5057 /*
5058 * TODO: Marking the bucket will not avoid multiple searches
5059 * in the same schema, but avoids at least circularity.
5060 */
5061 bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5062 do {
5063 if ((rel->bucket != NULL) &&
5064 ((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5065 ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5066 type, name, nsName);
5067 if (ret != NULL)
5068 return(ret);
5069 }
5070 rel = rel->next;
5071 } while (rel != NULL);
5072 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5073 }
5074 return(NULL);
5075}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005076
5077/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005078 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005079 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005080 * @schema: the schema being built
5081 * @name: the item name
5082 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005083 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00005084 * *WARNING* this interface is highly subject to change
5085 *
5086 * Returns the new struture or NULL in case of error
5087 */
5088static xmlSchemaNotationPtr
5089xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005090 const xmlChar *name, const xmlChar *nsName,
5091 xmlNodePtr node ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00005092{
5093 xmlSchemaNotationPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005094
5095 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5096 return (NULL);
5097
Daniel Veillard4255d502002-04-16 15:50:10 +00005098 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5099 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005100 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005101 return (NULL);
5102 }
5103 memset(ret, 0, sizeof(xmlSchemaNotation));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005104 ret->type = XML_SCHEMA_TYPE_NOTATION;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005105 ret->name = name;
5106 ret->targetNamespace = nsName;
5107 /* TODO: do we need the node to be set?
5108 * ret->node = node;*/
5109 WXS_ADD_GLOBAL(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005110 return (ret);
5111}
5112
Daniel Veillard4255d502002-04-16 15:50:10 +00005113/**
5114 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005115 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005116 * @schema: the schema being built
5117 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005118 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005119 *
5120 * Add an XML schema Attrribute declaration
5121 * *WARNING* this interface is highly subject to change
5122 *
5123 * Returns the new struture or NULL in case of error
5124 */
5125static xmlSchemaAttributePtr
5126xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005127 const xmlChar * name, const xmlChar * nsName,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005128 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005129{
5130 xmlSchemaAttributePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005131
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005132 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005133 return (NULL);
5134
5135 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5136 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005137 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005138 return (NULL);
5139 }
5140 memset(ret, 0, sizeof(xmlSchemaAttribute));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005141 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5142 ret->node = node;
5143 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005144 ret->targetNamespace = nsName;
5145
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005146 if (topLevel)
5147 WXS_ADD_GLOBAL(ctxt, ret);
5148 else
5149 WXS_ADD_LOCAL(ctxt, ret);
5150 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005151 return (ret);
5152}
5153
5154/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005155 * xmlSchemaAddAttributeUse:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005156 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005157 * @schema: the schema being built
5158 * @name: the item name
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005159 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005160 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005161 * Add an XML schema Attrribute declaration
5162 * *WARNING* this interface is highly subject to change
5163 *
5164 * Returns the new struture or NULL in case of error
5165 */
5166static xmlSchemaAttributeUsePtr
5167xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5168 xmlNodePtr node)
5169{
5170 xmlSchemaAttributeUsePtr ret = NULL;
5171
5172 if (pctxt == NULL)
5173 return (NULL);
5174
5175 ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5176 if (ret == NULL) {
5177 xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5178 return (NULL);
5179 }
5180 memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5181 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5182 ret->node = node;
5183
5184 WXS_ADD_LOCAL(pctxt, ret);
5185 return (ret);
5186}
5187
5188/*
5189* xmlSchemaAddRedef:
5190*
5191* Adds a redefinition information. This is used at a later stage to:
5192* resolve references to the redefined components and to check constraints.
5193*/
5194static xmlSchemaRedefPtr
5195xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5196 xmlSchemaBucketPtr targetBucket,
5197 void *item,
5198 const xmlChar *refName,
5199 const xmlChar *refTargetNs)
5200{
5201 xmlSchemaRedefPtr ret;
5202
5203 ret = (xmlSchemaRedefPtr)
5204 xmlMalloc(sizeof(xmlSchemaRedef));
5205 if (ret == NULL) {
5206 xmlSchemaPErrMemory(pctxt,
5207 "allocating redefinition info", NULL);
5208 return (NULL);
5209 }
5210 memset(ret, 0, sizeof(xmlSchemaRedef));
5211 ret->item = item;
5212 ret->targetBucket = targetBucket;
5213 ret->refName = refName;
5214 ret->refTargetNs = refTargetNs;
5215 if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5216 WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5217 else
5218 WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5219 WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5220
5221 return (ret);
5222}
5223
5224/**
5225 * xmlSchemaAddAttributeGroupDefinition:
5226 * @ctxt: a schema parser context
5227 * @schema: the schema being built
5228 * @name: the item name
5229 * @nsName: the target namespace
5230 * @node: the corresponding node
5231 *
5232 * Add an XML schema Attrribute Group definition.
Daniel Veillard4255d502002-04-16 15:50:10 +00005233 *
5234 * Returns the new struture or NULL in case of error
5235 */
5236static xmlSchemaAttributeGroupPtr
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005237xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5238 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5239 const xmlChar *name,
5240 const xmlChar *nsName,
5241 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005242{
5243 xmlSchemaAttributeGroupPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005244
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005245 if ((pctxt == NULL) || (name == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005246 return (NULL);
5247
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005248 ret = (xmlSchemaAttributeGroupPtr)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005249 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00005250 if (ret == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005251 xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005252 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005253 }
5254 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005255 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005256 ret->name = name;
5257 ret->targetNamespace = nsName;
5258 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005259
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005260 /* TODO: Remove the flag. */
5261 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5262 if (pctxt->isRedefine) {
5263 pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5264 ret, name, nsName);
5265 if (pctxt->redef == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005266 xmlFree(ret);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005267 return(NULL);
5268 }
5269 pctxt->redefCounter = 0;
5270 }
5271 WXS_ADD_GLOBAL(pctxt, ret);
5272 WXS_ADD_PENDING(pctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005273 return (ret);
5274}
5275
5276/**
5277 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005278 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005279 * @schema: the schema being built
5280 * @name: the type name
5281 * @namespace: the type namespace
5282 *
5283 * Add an XML schema Element declaration
5284 * *WARNING* this interface is highly subject to change
5285 *
5286 * Returns the new struture or NULL in case of error
5287 */
5288static xmlSchemaElementPtr
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005289xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005290 const xmlChar * name, const xmlChar * nsName,
William M. Brack2f2a6632004-08-20 23:09:47 +00005291 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005292{
5293 xmlSchemaElementPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005294
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005295 if ((ctxt == NULL) || (name == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005296 return (NULL);
5297
Daniel Veillard4255d502002-04-16 15:50:10 +00005298 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5299 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005300 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005301 return (NULL);
5302 }
5303 memset(ret, 0, sizeof(xmlSchemaElement));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005304 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5305 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005306 ret->targetNamespace = nsName;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005307 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005308
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005309 if (topLevel)
5310 WXS_ADD_GLOBAL(ctxt, ret);
5311 else
5312 WXS_ADD_LOCAL(ctxt, ret);
5313 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005314 return (ret);
5315}
5316
5317/**
5318 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00005319 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005320 * @schema: the schema being built
5321 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005322 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005323 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005324 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00005325 * *WARNING* this interface is highly subject to change
5326 *
5327 * Returns the new struture or NULL in case of error
5328 */
5329static xmlSchemaTypePtr
5330xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005331 xmlSchemaTypeType type,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00005332 const xmlChar * name, const xmlChar * nsName,
5333 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005334{
5335 xmlSchemaTypePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005336
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005337 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005338 return (NULL);
5339
5340 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5341 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005342 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005343 return (NULL);
5344 }
5345 memset(ret, 0, sizeof(xmlSchemaType));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005346 ret->type = type;
5347 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005348 ret->targetNamespace = nsName;
5349 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005350 if (topLevel) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005351 if (ctxt->isRedefine) {
5352 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5353 ret, name, nsName);
5354 if (ctxt->redef == NULL) {
5355 xmlFree(ret);
5356 return(NULL);
5357 }
5358 ctxt->redefCounter = 0;
5359 }
5360 WXS_ADD_GLOBAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005361 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005362 WXS_ADD_LOCAL(ctxt, ret);
5363 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005364 return (ret);
5365}
5366
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005367static xmlSchemaQNameRefPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005368xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005369 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005370 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005371 const xmlChar *refNs)
5372{
5373 xmlSchemaQNameRefPtr ret;
5374
5375 ret = (xmlSchemaQNameRefPtr)
5376 xmlMalloc(sizeof(xmlSchemaQNameRef));
5377 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005378 xmlSchemaPErrMemory(pctxt,
5379 "allocating QName reference item", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005380 return (NULL);
5381 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005382 ret->node = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005383 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5384 ret->name = refName;
5385 ret->targetNamespace = refNs;
5386 ret->item = NULL;
5387 ret->itemType = refType;
5388 /*
5389 * Store the reference item in the schema.
5390 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005391 WXS_ADD_LOCAL(pctxt, ret);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005392 return (ret);
5393}
5394
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005395static xmlSchemaAttributeUseProhibPtr
5396xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5397{
5398 xmlSchemaAttributeUseProhibPtr ret;
5399
5400 ret = (xmlSchemaAttributeUseProhibPtr)
5401 xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5402 if (ret == NULL) {
5403 xmlSchemaPErrMemory(pctxt,
5404 "allocating attribute use prohibition", NULL);
5405 return (NULL);
5406 }
5407 memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5408 ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5409 WXS_ADD_LOCAL(pctxt, ret);
5410 return (ret);
5411}
5412
5413
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005414/**
5415 * xmlSchemaAddModelGroup:
5416 * @ctxt: a schema parser context
5417 * @schema: the schema being built
5418 * @type: the "compositor" type of the model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005419 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005420 *
5421 * Adds a schema model group
5422 * *WARNING* this interface is highly subject to change
5423 *
5424 * Returns the new struture or NULL in case of error
5425 */
5426static xmlSchemaModelGroupPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005427xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5428 xmlSchemaPtr schema,
5429 xmlSchemaTypeType type,
5430 xmlNodePtr node)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005431{
5432 xmlSchemaModelGroupPtr ret = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005433
5434 if ((ctxt == NULL) || (schema == NULL))
5435 return (NULL);
5436
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005437 ret = (xmlSchemaModelGroupPtr)
5438 xmlMalloc(sizeof(xmlSchemaModelGroup));
5439 if (ret == NULL) {
5440 xmlSchemaPErrMemory(ctxt, "allocating model group component",
5441 NULL);
5442 return (NULL);
5443 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005444 memset(ret, 0, sizeof(xmlSchemaModelGroup));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005445 ret->type = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005446 ret->node = node;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005447 WXS_ADD_LOCAL(ctxt, ret);
5448 if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5449 (type == XML_SCHEMA_TYPE_CHOICE))
5450 WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005451 return (ret);
5452}
5453
5454
5455/**
5456 * xmlSchemaAddParticle:
5457 * @ctxt: a schema parser context
5458 * @schema: the schema being built
5459 * @node: the corresponding node in the schema doc
5460 * @min: the minOccurs
5461 * @max: the maxOccurs
5462 *
5463 * Adds an XML schema particle component.
5464 * *WARNING* this interface is highly subject to change
5465 *
5466 * Returns the new struture or NULL in case of error
5467 */
5468static xmlSchemaParticlePtr
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +00005469xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005470 xmlNodePtr node, int min, int max)
5471{
5472 xmlSchemaParticlePtr ret = NULL;
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +00005473 if (ctxt == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005474 return (NULL);
5475
5476#ifdef DEBUG
5477 fprintf(stderr, "Adding particle component\n");
5478#endif
5479 ret = (xmlSchemaParticlePtr)
5480 xmlMalloc(sizeof(xmlSchemaParticle));
5481 if (ret == NULL) {
5482 xmlSchemaPErrMemory(ctxt, "allocating particle component",
5483 NULL);
5484 return (NULL);
5485 }
5486 ret->type = XML_SCHEMA_TYPE_PARTICLE;
5487 ret->annot = NULL;
5488 ret->node = node;
5489 ret->minOccurs = min;
5490 ret->maxOccurs = max;
5491 ret->next = NULL;
5492 ret->children = NULL;
5493
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005494 WXS_ADD_LOCAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005495 /*
5496 * Note that addition to pending components will be done locally
5497 * to the specific parsing function, since the most particles
5498 * need not to be fixed up (i.e. the reference to be resolved).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005499 * REMOVED: WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005500 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005501 return (ret);
5502}
5503
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005504/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005505 * xmlSchemaAddModelGroupDefinition:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005506 * @ctxt: a schema validation context
5507 * @schema: the schema being built
5508 * @name: the group name
5509 *
5510 * Add an XML schema Group definition
5511 *
5512 * Returns the new struture or NULL in case of error
5513 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005514static xmlSchemaModelGroupDefPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005515xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5516 xmlSchemaPtr schema,
5517 const xmlChar *name,
5518 const xmlChar *nsName,
5519 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005520{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005521 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005522
5523 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5524 return (NULL);
5525
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005526 ret = (xmlSchemaModelGroupDefPtr)
5527 xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005528 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005529 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005530 return (NULL);
5531 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005532 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005533 ret->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005534 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005535 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005536 ret->targetNamespace = nsName;
5537
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005538 if (ctxt->isRedefine) {
5539 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5540 ret, name, nsName);
5541 if (ctxt->redef == NULL) {
5542 xmlFree(ret);
5543 return(NULL);
5544 }
5545 ctxt->redefCounter = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005546 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005547 WXS_ADD_GLOBAL(ctxt, ret);
5548 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005549 return (ret);
5550}
5551
Daniel Veillard3646d642004-06-02 19:19:14 +00005552/**
5553 * xmlSchemaNewWildcardNs:
5554 * @ctxt: a schema validation context
5555 *
5556 * Creates a new wildcard namespace constraint.
5557 *
5558 * Returns the new struture or NULL in case of error
5559 */
5560static xmlSchemaWildcardNsPtr
5561xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5562{
5563 xmlSchemaWildcardNsPtr ret;
5564
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005565 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005566 xmlMalloc(sizeof(xmlSchemaWildcardNs));
5567 if (ret == NULL) {
5568 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005569 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00005570 }
5571 ret->value = NULL;
5572 ret->next = NULL;
5573 return (ret);
5574}
5575
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005576static xmlSchemaIDCPtr
5577xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5578 const xmlChar *name, const xmlChar *nsName,
5579 int category, xmlNodePtr node)
5580{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005581 xmlSchemaIDCPtr ret = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005582
5583 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5584 return (NULL);
5585
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005586 ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5587 if (ret == NULL) {
5588 xmlSchemaPErrMemory(ctxt,
5589 "allocating an identity-constraint definition", NULL);
5590 return (NULL);
5591 }
5592 memset(ret, 0, sizeof(xmlSchemaIDC));
5593 /* The target namespace of the parent element declaration. */
5594 ret->targetNamespace = nsName;
5595 ret->name = name;
5596 ret->type = category;
5597 ret->node = node;
5598
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005599 WXS_ADD_GLOBAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005600 /*
5601 * Only keyrefs need to be fixup up.
5602 */
5603 if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005604 WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005605 return (ret);
5606}
5607
Daniel Veillard3646d642004-06-02 19:19:14 +00005608/**
5609 * xmlSchemaAddWildcard:
5610 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005611 * @schema: a schema
5612 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005613 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005614 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00005615 *
5616 * Returns the new struture or NULL in case of error
5617 */
5618static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005619xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5620 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00005621{
5622 xmlSchemaWildcardPtr ret = NULL;
5623
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005624 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00005625 return (NULL);
5626
5627 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5628 if (ret == NULL) {
5629 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5630 return (NULL);
5631 }
5632 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005633 ret->type = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005634 ret->node = node;
5635 WXS_ADD_LOCAL(ctxt, ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00005636 return (ret);
5637}
5638
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005639static void
5640xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5641{
5642 if (group == NULL)
5643 return;
5644 if (group->members != NULL)
5645 xmlSchemaItemListFree(group->members);
5646 xmlFree(group);
5647}
5648
5649static xmlSchemaSubstGroupPtr
5650xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5651 xmlSchemaElementPtr head)
5652{
5653 xmlSchemaSubstGroupPtr ret;
5654
5655 /* Init subst group hash. */
5656 if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5657 WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5658 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5659 return(NULL);
5660 }
5661 /* Create a new substitution group. */
5662 ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5663 if (ret == NULL) {
5664 xmlSchemaPErrMemory(NULL,
5665 "allocating a substitution group container", NULL);
5666 return(NULL);
5667 }
5668 memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5669 ret->head = head;
5670 /* Create list of members. */
5671 ret->members = xmlSchemaItemListCreate();
5672 if (ret->members == NULL) {
5673 xmlSchemaSubstGroupFree(ret);
5674 return(NULL);
5675 }
5676 /* Add subst group to hash. */
5677 if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5678 head->name, head->targetNamespace, ret) != 0) {
5679 PERROR_INT("xmlSchemaSubstGroupAdd",
5680 "failed to add a new substitution container");
5681 xmlSchemaSubstGroupFree(ret);
5682 return(NULL);
5683 }
5684 return(ret);
5685}
5686
5687static xmlSchemaSubstGroupPtr
5688xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5689 xmlSchemaElementPtr head)
5690{
5691 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5692 return(NULL);
5693 return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5694 head->name, head->targetNamespace));
5695
5696}
5697
5698/**
5699 * xmlSchemaAddElementSubstitutionMember:
5700 * @pctxt: a schema parser context
5701 * @head: the head of the substitution group
5702 * @member: the new member of the substitution group
5703 *
5704 * Allocate a new annotation structure.
5705 *
5706 * Returns the newly allocated structure or NULL in case or error
5707 */
5708static int
5709xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5710 xmlSchemaElementPtr head,
5711 xmlSchemaElementPtr member)
5712{
5713 xmlSchemaSubstGroupPtr substGroup = NULL;
5714
5715 if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5716 return (-1);
5717
5718 substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5719 if (substGroup == NULL)
5720 substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5721 if (substGroup == NULL)
5722 return(-1);
5723 if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5724 return(-1);
5725 return(0);
5726}
5727
Daniel Veillard4255d502002-04-16 15:50:10 +00005728/************************************************************************
5729 * *
5730 * Utilities for parsing *
5731 * *
5732 ************************************************************************/
5733
Daniel Veillard4255d502002-04-16 15:50:10 +00005734/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005735 * xmlSchemaPValAttrNodeQNameValue:
5736 * @ctxt: a schema parser context
5737 * @schema: the schema context
5738 * @ownerDes: the designation of the parent element
5739 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005740 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00005741 * @local: the resulting local part if found, the attribute value otherwise
5742 * @uri: the resulting namespace URI if found
5743 *
5744 * Extracts the local name and the URI of a QName value and validates it.
5745 * This one is intended to be used on attribute values that
5746 * should resolve to schema components.
5747 *
5748 * Returns 0, in case the QName is valid, a positive error code
5749 * if not valid and -1 if an internal error occurs.
5750 */
5751static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005752xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005753 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005754 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005755 xmlAttrPtr attr,
5756 const xmlChar *value,
5757 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005758 const xmlChar **local)
5759{
5760 const xmlChar *pref;
5761 xmlNsPtr ns;
5762 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005763
Daniel Veillardc0826a72004-08-10 14:17:33 +00005764 *uri = NULL;
5765 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005766 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005767 if (ret > 0) {
5768 xmlSchemaPSimpleTypeErr(ctxt,
5769 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5770 ownerItem, (xmlNodePtr) attr,
5771 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5772 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005773 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005774 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005775 } else if (ret < 0)
5776 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005777
5778 if (!strchr((char *) value, ':')) {
Daniel Veillard24505b02005-07-28 23:49:35 +00005779 ns = xmlSearchNs(attr->doc, attr->parent, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005780 if (ns)
5781 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5782 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005783 /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5784 * parser context. */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005785 /*
5786 * This one takes care of included schemas with no
5787 * target namespace.
5788 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005789 *uri = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005790 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005791 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005792 return (0);
5793 }
5794 /*
5795 * At this point xmlSplitQName3 has to return a local name.
5796 */
5797 *local = xmlSplitQName3(value, &len);
5798 *local = xmlDictLookup(ctxt->dict, *local, -1);
5799 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005800 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5801 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005802 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005803 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005804 ownerItem, (xmlNodePtr) attr,
5805 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5806 "The value '%s' of simple type 'xs:QName' has no "
5807 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005808 return (ctxt->err);
5809 } else {
5810 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005811 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005812 return (0);
5813}
5814
5815/**
5816 * xmlSchemaPValAttrNodeQName:
5817 * @ctxt: a schema parser context
5818 * @schema: the schema context
5819 * @ownerDes: the designation of the owner element
5820 * @ownerItem: the owner as a schema object
5821 * @attr: the attribute node
5822 * @local: the resulting local part if found, the attribute value otherwise
5823 * @uri: the resulting namespace URI if found
5824 *
5825 * Extracts and validates the QName of an attribute value.
5826 * This one is intended to be used on attribute values that
5827 * should resolve to schema components.
5828 *
5829 * Returns 0, in case the QName is valid, a positive error code
5830 * if not valid and -1 if an internal error occurs.
5831 */
5832static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005833xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005834 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005835 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005836 xmlAttrPtr attr,
5837 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005838 const xmlChar **local)
5839{
5840 const xmlChar *value;
5841
5842 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005843 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005844 ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005845}
5846
5847/**
5848 * xmlSchemaPValAttrQName:
5849 * @ctxt: a schema parser context
5850 * @schema: the schema context
5851 * @ownerDes: the designation of the parent element
5852 * @ownerItem: the owner as a schema object
5853 * @ownerElem: the parent node of the attribute
5854 * @name: the name of the attribute
5855 * @local: the resulting local part if found, the attribute value otherwise
5856 * @uri: the resulting namespace URI if found
5857 *
5858 * Extracts and validates the QName of an attribute value.
5859 *
5860 * Returns 0, in case the QName is valid, a positive error code
5861 * if not valid and -1 if an internal error occurs.
5862 */
5863static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005864xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5865 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005866 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005867 xmlNodePtr ownerElem,
5868 const char *name,
5869 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005870 const xmlChar **local)
5871{
5872 xmlAttrPtr attr;
5873
5874 attr = xmlSchemaGetPropNode(ownerElem, name);
5875 if (attr == NULL) {
5876 *local = NULL;
5877 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005878 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005879 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005880 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005881 ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005882}
5883
5884/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005885 * xmlSchemaPValAttrID:
5886 * @ctxt: a schema parser context
5887 * @schema: the schema context
5888 * @ownerDes: the designation of the parent element
5889 * @ownerItem: the owner as a schema object
5890 * @ownerElem: the parent node of the attribute
5891 * @name: the name of the attribute
5892 *
5893 * Extracts and validates the ID of an attribute value.
5894 *
5895 * Returns 0, in case the ID is valid, a positive error code
5896 * if not valid and -1 if an internal error occurs.
5897 */
5898static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005899xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005900{
5901 int ret;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005902 const xmlChar *value;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005903
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005904 if (attr == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005905 return(0);
5906 value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5907 ret = xmlValidateNCName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005908 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005909 /*
5910 * NOTE: the IDness might have already be declared in the DTD
5911 */
5912 if (attr->atype != XML_ATTRIBUTE_ID) {
5913 xmlIDPtr res;
5914 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005915
5916 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005917 * TODO: Use xmlSchemaStrip here; it's not exported at this
5918 * moment.
5919 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005920 strip = xmlSchemaCollapseString(value);
5921 if (strip != NULL) {
5922 xmlFree((xmlChar *) value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005923 value = strip;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005924 }
5925 res = xmlAddID(NULL, attr->doc, value, attr);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005926 if (res == NULL) {
5927 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005928 xmlSchemaPSimpleTypeErr(ctxt,
5929 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005930 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005931 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5932 NULL, NULL, "Duplicate value '%s' of simple "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005933 "type 'xs:ID'", value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005934 } else
5935 attr->atype = XML_ATTRIBUTE_ID;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005936 }
5937 } else if (ret > 0) {
5938 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005939 xmlSchemaPSimpleTypeErr(ctxt,
5940 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005941 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005942 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5943 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5944 "not a valid 'xs:NCName'",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005945 value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005946 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005947 if (value != NULL)
5948 xmlFree((xmlChar *)value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005949
5950 return (ret);
5951}
5952
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005953static int
5954xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5955 xmlNodePtr ownerElem,
5956 const xmlChar *name)
5957{
5958 xmlAttrPtr attr;
5959
5960 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5961 if (attr == NULL)
5962 return(0);
5963 return(xmlSchemaPValAttrNodeID(ctxt, attr));
5964
5965}
5966
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005967/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005968 * xmlGetMaxOccurs:
5969 * @ctxt: a schema validation context
5970 * @node: a subtree containing XML Schema informations
5971 *
5972 * Get the maxOccurs property
5973 *
5974 * Returns the default if not found, or the value
5975 */
5976static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005977xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5978 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005979{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005980 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005981 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005982 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005983
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005984 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5985 if (attr == NULL)
5986 return (def);
5987 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005988
5989 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005990 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005991 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005992 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5993 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005994 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005995 val, NULL, NULL, NULL);
5996 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005997 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005998 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005999 }
6000
6001 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00006002 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006003 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006004 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006005 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006006 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6007 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006008 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006009 val, NULL, NULL, NULL);
6010 return (def);
6011 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006012 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006013 ret = ret * 10 + (*cur - '0');
6014 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00006015 }
William M. Brack76e95df2003-10-18 16:20:14 +00006016 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006017 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006018 /*
6019 * TODO: Restrict the maximal value to Integer.
6020 */
6021 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006022 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006023 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6024 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006025 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006026 val, NULL, NULL, NULL);
6027 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006028 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006029 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006030}
6031
6032/**
6033 * xmlGetMinOccurs:
6034 * @ctxt: a schema validation context
6035 * @node: a subtree containing XML Schema informations
6036 *
6037 * Get the minOccurs property
6038 *
6039 * Returns the default if not found, or the value
6040 */
6041static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006042xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006043 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006044{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006045 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00006046 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006047 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006048
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006049 attr = xmlSchemaGetPropNode(node, "minOccurs");
6050 if (attr == NULL)
6051 return (def);
6052 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00006053 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00006054 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006055 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006056 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006057 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006058 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6059 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006060 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006061 val, NULL, NULL, NULL);
6062 return (def);
6063 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006064 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006065 ret = ret * 10 + (*cur - '0');
6066 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00006067 }
William M. Brack76e95df2003-10-18 16:20:14 +00006068 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006069 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006070 /*
6071 * TODO: Restrict the maximal value to Integer.
6072 */
6073 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006074 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006075 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6076 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006077 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006078 val, NULL, NULL, NULL);
6079 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006080 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006081 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006082}
6083
6084/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006085 * xmlSchemaPGetBoolNodeValue:
6086 * @ctxt: a schema validation context
6087 * @ownerDes: owner designation
6088 * @ownerItem: the owner as a schema item
6089 * @node: the node holding the value
6090 *
6091 * Converts a boolean string value into 1 or 0.
6092 *
6093 * Returns 0 or 1.
6094 */
6095static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006096xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006097 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006098 xmlNodePtr node)
6099{
6100 xmlChar *value = NULL;
6101 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006102
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006103 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006104 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006105 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006106 * An instance of a datatype that is defined as ·boolean·
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006107 * can have the following legal literals {true, false, 1, 0}.
6108 */
6109 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6110 res = 1;
6111 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6112 res = 0;
6113 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6114 res = 1;
6115 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006116 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006117 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006118 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006119 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006120 ownerItem, node,
6121 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6122 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006123 NULL, NULL, NULL);
6124 }
6125 if (value != NULL)
6126 xmlFree(value);
6127 return (res);
6128}
6129
6130/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006131 * xmlGetBooleanProp:
6132 * @ctxt: a schema validation context
6133 * @node: a subtree containing XML Schema informations
6134 * @name: the attribute name
6135 * @def: the default value
6136 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006137 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00006138 *
6139 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006140 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00006141 */
6142static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006143xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006144 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006145 const char *name, int def)
6146{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006147 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00006148
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006149 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006150 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006151 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006152 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006153 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006154 * An instance of a datatype that is defined as ·boolean·
Daniel Veillardc0826a72004-08-10 14:17:33 +00006155 * can have the following legal literals {true, false, 1, 0}.
6156 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006157 if (xmlStrEqual(val, BAD_CAST "true"))
6158 def = 1;
6159 else if (xmlStrEqual(val, BAD_CAST "false"))
6160 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006161 else if (xmlStrEqual(val, BAD_CAST "1"))
6162 def = 1;
6163 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006164 def = 0;
6165 else {
6166 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006167 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006168 NULL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006169 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006170 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6171 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006172 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006173 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006174}
6175
6176/************************************************************************
6177 * *
6178 * Shema extraction from an Infoset *
6179 * *
6180 ************************************************************************/
6181static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6182 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006183 xmlNodePtr node,
6184 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006185static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6186 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00006187 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006188 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00006189 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006190static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6191 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00006192 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006193 xmlNodePtr node,
6194 xmlSchemaTypeType parentType);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006195static xmlSchemaBasicItemPtr
6196xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6197 xmlSchemaPtr schema,
6198 xmlNodePtr node,
6199 xmlSchemaItemListPtr uses,
6200 int parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00006201static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6202 xmlSchemaPtr schema,
6203 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00006204static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006205xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6206 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006207
6208/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006209 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006210 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00006211 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00006212 * @ownerDes: the designation of the parent element
6213 * @ownerItem: the schema object owner if existent
6214 * @attr: the schema attribute node being validated
6215 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006216 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00006217 *
6218 * Validates a value against the given built-in type.
6219 * This one is intended to be used internally for validation
6220 * of schema attribute values during parsing of the schema.
6221 *
6222 * Returns 0 if the value is valid, a positive error code
6223 * number otherwise and -1 in case of an internal or API error.
6224 */
6225static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006226xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006227 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006228 xmlAttrPtr attr,
6229 const xmlChar *value,
6230 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00006231{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006232
6233 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006234
6235 /*
6236 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6237 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006238 */
6239 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00006240 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006241 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6242 PERROR_INT("xmlSchemaPValAttrNodeValue",
6243 "the given type is not a built-in type");
6244 return (-1);
6245 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006246 switch (type->builtInType) {
6247 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006248 case XML_SCHEMAS_QNAME:
6249 case XML_SCHEMAS_ANYURI:
6250 case XML_SCHEMAS_TOKEN:
6251 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006252 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6253 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006254 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006255 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006256 PERROR_INT("xmlSchemaPValAttrNodeValue",
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +00006257 "validation using the given type is not supported while "
6258 "parsing a schema");
Daniel Veillard01fa6152004-06-29 17:04:39 +00006259 return (-1);
6260 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006261 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006262 /*
6263 * TODO: Should we use the S4S error codes instead?
6264 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006265 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006266 PERROR_INT("xmlSchemaPValAttrNodeValue",
6267 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006268 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006269 } else if (ret > 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006270 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006271 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6272 else
6273 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6274 xmlSchemaPSimpleTypeErr(pctxt,
6275 ret, ownerItem, (xmlNodePtr) attr,
6276 type, NULL, value, NULL, NULL, NULL);
6277 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006278 return (ret);
6279}
6280
6281/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006282 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006283 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006284 * @ctxt: a schema parser context
6285 * @ownerDes: the designation of the parent element
6286 * @ownerItem: the schema object owner if existent
6287 * @attr: the schema attribute node being validated
6288 * @type: the built-in type to be validated against
6289 * @value: the resulting value if any
6290 *
6291 * Extracts and validates a value against the given built-in type.
6292 * This one is intended to be used internally for validation
6293 * of schema attribute values during parsing of the schema.
6294 *
6295 * Returns 0 if the value is valid, a positive error code
6296 * number otherwise and -1 in case of an internal or API error.
6297 */
6298static int
6299xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006300 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006301 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006302 xmlSchemaTypePtr type,
6303 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006304{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006305 const xmlChar *val;
6306
6307 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006308 return (-1);
6309
Daniel Veillardc0826a72004-08-10 14:17:33 +00006310 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6311 if (value != NULL)
6312 *value = val;
6313
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006314 return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006315 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00006316}
6317
6318/**
6319 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006320 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006321 * @ctxt: a schema parser context
6322 * @node: the element node of the attribute
6323 * @ownerDes: the designation of the parent element
6324 * @ownerItem: the schema object owner if existent
6325 * @ownerElem: the owner element node
6326 * @name: the name of the schema attribute node
6327 * @type: the built-in type to be validated against
6328 * @value: the resulting value if any
6329 *
6330 * Extracts and validates a value against the given built-in type.
6331 * This one is intended to be used internally for validation
6332 * of schema attribute values during parsing of the schema.
6333 *
6334 * Returns 0 if the value is valid, a positive error code
6335 * number otherwise and -1 in case of an internal or API error.
6336 */
6337static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006338xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6339 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006340 xmlNodePtr ownerElem,
6341 const char *name,
6342 xmlSchemaTypePtr type,
6343 const xmlChar **value)
6344{
6345 xmlAttrPtr attr;
6346
6347 if ((ctxt == NULL) || (type == NULL)) {
6348 if (value != NULL)
6349 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006350 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006351 }
6352 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6353 if (value != NULL)
6354 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006355 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006356 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006357 "Internal error: xmlSchemaPValAttr, the given "
6358 "type '%s' is not a built-in type.\n",
6359 type->name, NULL);
6360 return (-1);
6361 }
6362 attr = xmlSchemaGetPropNode(ownerElem, name);
6363 if (attr == NULL) {
6364 if (value != NULL)
6365 *value = NULL;
6366 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006367 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006368 return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006369 type, value));
6370}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006371
6372static int
6373xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006374 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006375 xmlNodePtr node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006376 xmlAttrPtr attr,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006377 const xmlChar *namespaceName)
6378{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006379 /* TODO: Pointer comparison instead? */
6380 if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006381 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006382 if (xmlStrEqual(xmlSchemaNs, namespaceName))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006383 return (0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006384 /*
6385 * Check if the referenced namespace was <import>ed.
6386 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006387 if (WXS_BUCKET(pctxt)->relations != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006388 xmlSchemaSchemaRelationPtr rel;
6389
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006390 rel = WXS_BUCKET(pctxt)->relations;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006391 do {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006392 if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006393 xmlStrEqual(namespaceName, rel->importNamespace))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006394 return (0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006395 rel = rel->next;
6396 } while (rel != NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006397 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006398 /*
6399 * No matching <import>ed namespace found.
6400 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006401 {
6402 xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6403
6404 if (namespaceName == NULL)
6405 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6406 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6407 "References from this schema to components in no "
6408 "namespace are not allowed, since not indicated by an "
6409 "import statement", NULL, NULL);
6410 else
6411 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6412 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6413 "References from this schema to components in the "
6414 "namespace '%s' are not allowed, since not indicated by an "
6415 "import statement", namespaceName, NULL);
6416 }
6417 return (XML_SCHEMAP_SRC_RESOLVE);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006418}
6419
Daniel Veillardc0826a72004-08-10 14:17:33 +00006420/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006421 * xmlSchemaParseLocalAttributes:
Daniel Veillard4255d502002-04-16 15:50:10 +00006422 * @ctxt: a schema validation context
6423 * @schema: the schema being built
6424 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006425 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00006426 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006427 * Parses attribute uses and attribute declarations and
6428 * attribute group references.
Daniel Veillard4255d502002-04-16 15:50:10 +00006429 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006430static int
6431xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6432 xmlNodePtr *child, xmlSchemaItemListPtr *list,
6433 int parentType, int *hasRefs)
Daniel Veillard4255d502002-04-16 15:50:10 +00006434{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006435 void *item;
Daniel Veillard4255d502002-04-16 15:50:10 +00006436
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006437 while ((IS_SCHEMA((*child), "attribute")) ||
6438 (IS_SCHEMA((*child), "attributeGroup"))) {
6439 if (IS_SCHEMA((*child), "attribute")) {
6440 item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6441 *list, parentType);
6442 } else {
6443 item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6444 if ((item != NULL) && (hasRefs != NULL))
6445 *hasRefs = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006446 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006447 if (item != NULL) {
6448 if (*list == NULL) {
6449 /* TODO: Customize grow factor. */
6450 *list = xmlSchemaItemListCreate();
6451 if (*list == NULL)
6452 return(-1);
6453 }
6454 if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6455 return(-1);
6456 }
6457 *child = (*child)->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006458 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006459 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006460}
6461
6462/**
6463 * xmlSchemaParseAnnotation:
6464 * @ctxt: a schema validation context
6465 * @schema: the schema being built
6466 * @node: a subtree containing XML Schema informations
6467 *
6468 * parse a XML schema Attrribute declaration
6469 * *WARNING* this interface is highly subject to change
6470 *
William M. Bracke7091952004-05-11 15:09:58 +00006471 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006472 * 1 in case of success.
6473 */
6474static xmlSchemaAnnotPtr
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00006475xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
Daniel Veillard4255d502002-04-16 15:50:10 +00006476{
6477 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006478 xmlNodePtr child = NULL;
6479 xmlAttrPtr attr;
6480 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00006481
Daniel Veillardc0826a72004-08-10 14:17:33 +00006482 /*
6483 * INFO: S4S completed.
6484 */
6485 /*
6486 * id = ID
6487 * {any attributes with non-schema namespace . . .}>
6488 * Content: (appinfo | documentation)*
6489 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00006490 if ((ctxt == NULL) || (node == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00006491 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006492 if (needed)
6493 ret = xmlSchemaNewAnnot(ctxt, node);
6494 else
6495 ret = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006496 attr = node->properties;
6497 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006498 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006499 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006500 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006501 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006502
6503 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006504 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006505 }
6506 attr = attr->next;
6507 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006508 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006509 /*
6510 * And now for the children...
6511 */
6512 child = node->children;
6513 while (child != NULL) {
6514 if (IS_SCHEMA(child, "appinfo")) {
6515 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006516 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006517 * source = anyURI
6518 * {any attributes with non-schema namespace . . .}>
6519 * Content: ({any})*
6520 */
6521 attr = child->properties;
6522 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006523 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006524 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006525 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006526 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006527
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006528 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006529 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006530 }
6531 attr = attr->next;
6532 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006533 xmlSchemaPValAttr(ctxt, NULL, child, "source",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006534 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006535 child = child->next;
6536 } else if (IS_SCHEMA(child, "documentation")) {
6537 /* TODO: make available the content of "documentation". */
6538 /*
6539 * source = anyURI
6540 * {any attributes with non-schema namespace . . .}>
6541 * Content: ({any})*
6542 */
6543 attr = child->properties;
6544 while (attr != NULL) {
6545 if (attr->ns == NULL) {
6546 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006547 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006548 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006549 }
6550 } else {
6551 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6552 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
6553 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006554
6555 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006556 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006557 }
6558 }
6559 attr = attr->next;
6560 }
6561 /*
6562 * Attribute "xml:lang".
6563 */
6564 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6565 if (attr != NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006566 xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006567 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006568 child = child->next;
6569 } else {
6570 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006571 xmlSchemaPContentErr(ctxt,
6572 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006573 NULL, node, child, NULL, "(appinfo | documentation)*");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006574 barked = 1;
6575 child = child->next;
6576 }
6577 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006578
Daniel Veillard4255d502002-04-16 15:50:10 +00006579 return (ret);
6580}
6581
6582/**
6583 * xmlSchemaParseFacet:
6584 * @ctxt: a schema validation context
6585 * @schema: the schema being built
6586 * @node: a subtree containing XML Schema informations
6587 *
6588 * parse a XML schema Facet declaration
6589 * *WARNING* this interface is highly subject to change
6590 *
6591 * Returns the new type structure or NULL in case of error
6592 */
6593static xmlSchemaFacetPtr
6594xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006595 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006596{
6597 xmlSchemaFacetPtr facet;
6598 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006599 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00006600
6601 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6602 return (NULL);
6603
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006604 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006605 if (facet == NULL) {
6606 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6607 return (NULL);
6608 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006609 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006610 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00006611 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006612 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6613 "Facet %s has no value\n", node->name, NULL);
6614 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00006615 return (NULL);
6616 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006617 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006618 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006619 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006620 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006621 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006622 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006623 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006624 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006625 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006626 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006627 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006628 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006629 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006630 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006631 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006632 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006633 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006634 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006635 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006636 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006637 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006638 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6639 } else if (IS_SCHEMA(node, "minLength")) {
6640 facet->type = XML_SCHEMA_FACET_MINLENGTH;
6641 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006642 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6643 "Unknown facet type %s\n", node->name, NULL);
6644 xmlSchemaFreeFacet(facet);
6645 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006646 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006647 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006648 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006649 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6650 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6651 const xmlChar *fixed;
6652
6653 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6654 if (fixed != NULL) {
6655 if (xmlStrEqual(fixed, BAD_CAST "true"))
6656 facet->fixed = 1;
6657 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006658 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006659 child = node->children;
6660
6661 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00006662 facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006663 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006664 }
6665 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006666 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6667 "Facet %s has unexpected child content\n",
6668 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006669 }
6670 return (facet);
6671}
6672
6673/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006674 * xmlSchemaParseWildcardNs:
6675 * @ctxt: a schema parser context
6676 * @wildc: the wildcard, already created
6677 * @node: a subtree containing XML Schema informations
6678 *
6679 * Parses the attribute "processContents" and "namespace"
6680 * of a xsd:anyAttribute and xsd:any.
6681 * *WARNING* this interface is highly subject to change
6682 *
6683 * Returns 0 if everything goes fine, a positive error code
6684 * if something is not valid and -1 if an internal error occurs.
6685 */
6686static int
6687xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006688 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006689 xmlSchemaWildcardPtr wildc,
6690 xmlNodePtr node)
6691{
6692 const xmlChar *pc, *ns, *dictnsItem;
6693 int ret = 0;
6694 xmlChar *nsItem;
6695 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6696 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006697
Daniel Veillardc0826a72004-08-10 14:17:33 +00006698 pc = xmlSchemaGetProp(ctxt, node, "processContents");
6699 if ((pc == NULL)
6700 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6701 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6702 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6703 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6704 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6705 wildc->processContents = XML_SCHEMAS_ANY_LAX;
6706 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006707 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006708 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006709 NULL, node,
6710 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006711 NULL, NULL, NULL);
6712 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006713 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006714 }
6715 /*
6716 * Build the namespace constraints.
6717 */
6718 attr = xmlSchemaGetPropNode(node, "namespace");
6719 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006720 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00006721 wildc->any = 1;
6722 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6723 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006724 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006725 return (-1);
6726 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006727 wildc->negNsSet->value = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006728 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006729 const xmlChar *end, *cur;
6730
6731 cur = ns;
6732 do {
6733 while (IS_BLANK_CH(*cur))
6734 cur++;
6735 end = cur;
6736 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6737 end++;
6738 if (end == cur)
6739 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006740 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006741 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6742 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006743 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006744 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006745 NULL, (xmlNodePtr) attr,
6746 NULL,
6747 "((##any | ##other) | List of (xs:anyURI | "
6748 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006749 nsItem, NULL, NULL, NULL);
6750 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6751 } else {
6752 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006753 dictnsItem = ctxt->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006754 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6755 dictnsItem = NULL;
6756 } else {
6757 /*
6758 * Validate the item (anyURI).
6759 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006760 xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006761 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6762 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6763 }
6764 /*
6765 * Avoid dublicate namespaces.
6766 */
6767 tmp = wildc->nsSet;
6768 while (tmp != NULL) {
6769 if (dictnsItem == tmp->value)
6770 break;
6771 tmp = tmp->next;
6772 }
6773 if (tmp == NULL) {
6774 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6775 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006776 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006777 return (-1);
6778 }
6779 tmp->value = dictnsItem;
6780 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006781 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006782 wildc->nsSet = tmp;
6783 else
6784 lastNs->next = tmp;
6785 lastNs = tmp;
6786 }
6787
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006788 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006789 xmlFree(nsItem);
6790 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006791 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006792 }
6793 return (ret);
6794}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006795
6796static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006797xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6798 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006799 xmlNodePtr node,
6800 int minOccurs,
6801 int maxOccurs) {
6802
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006803 if ((maxOccurs == 0) && ( minOccurs == 0))
6804 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006805 if (maxOccurs != UNBOUNDED) {
6806 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006807 * TODO: Maybe we should better not create the particle,
6808 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006809 * content model.
6810 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006811 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006812 * 3.9.6 Schema Component Constraint: Particle Correct
6813 *
6814 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006815 if (maxOccurs < 1) {
6816 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006817 * 2.2 {max occurs} must be greater than or equal to 1.
6818 */
6819 xmlSchemaPCustomAttrErr(ctxt,
6820 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006821 NULL, NULL,
6822 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006823 "The value must be greater than or equal to 1");
6824 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6825 } else if (minOccurs > maxOccurs) {
6826 /*
6827 * 2.1 {min occurs} must not be greater than {max occurs}.
6828 */
6829 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006830 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006831 NULL, NULL,
6832 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006833 "The value must not be greater than the value of 'maxOccurs'");
6834 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6835 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006836 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006837 return (0);
6838}
6839
Daniel Veillardc0826a72004-08-10 14:17:33 +00006840/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006841 * xmlSchemaParseAny:
6842 * @ctxt: a schema validation context
6843 * @schema: the schema being built
6844 * @node: a subtree containing XML Schema informations
6845 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006846 * Parsea a XML schema <any> element. A particle and wildcard
6847 * will be created (except if minOccurs==maxOccurs==0, in this case
6848 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006849 * *WARNING* this interface is highly subject to change
6850 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006851 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006852 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006853static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006854xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6855 xmlNodePtr node)
6856{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006857 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006858 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006859 xmlSchemaWildcardPtr wild;
6860 int min, max;
6861 xmlAttrPtr attr;
6862 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006863
6864 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6865 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006866 /*
6867 * Check for illegal attributes.
6868 */
6869 attr = node->properties;
6870 while (attr != NULL) {
6871 if (attr->ns == NULL) {
6872 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6873 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6874 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6875 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6876 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006877 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006878 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006879 }
6880 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006881 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006882 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006883 }
6884 attr = attr->next;
6885 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006886 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006887 /*
6888 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006889 */
6890 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6891 "(xs:nonNegativeInteger | unbounded)");
6892 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6893 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006894 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6895 /*
6896 * Create & parse the wildcard.
6897 */
6898 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6899 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006900 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006901 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006902 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006903 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006904 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006905 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006906 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00006907 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006908 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006909 }
6910 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006911 xmlSchemaPContentErr(ctxt,
6912 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006913 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006914 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006915 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006916 /*
6917 * No component if minOccurs==maxOccurs==0.
6918 */
6919 if ((min == 0) && (max == 0)) {
6920 /* Don't free the wildcard, since it's already on the list. */
6921 return (NULL);
6922 }
6923 /*
6924 * Create the particle.
6925 */
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +00006926 particle = xmlSchemaAddParticle(ctxt, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006927 if (particle == NULL)
6928 return (NULL);
6929 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006930 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006931
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006932 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006933}
6934
6935/**
6936 * xmlSchemaParseNotation:
6937 * @ctxt: a schema validation context
6938 * @schema: the schema being built
6939 * @node: a subtree containing XML Schema informations
6940 *
6941 * parse a XML schema Notation declaration
6942 *
6943 * Returns the new structure or NULL in case of error
6944 */
6945static xmlSchemaNotationPtr
6946xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006947 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006948{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006949 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006950 xmlSchemaNotationPtr ret;
6951 xmlNodePtr child = NULL;
6952
6953 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6954 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006955 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006956 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006957 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6958 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006959 return (NULL);
6960 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006961 ret = xmlSchemaAddNotation(ctxt, schema, name,
6962 ctxt->targetNamespace, node);
6963 if (ret == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00006964 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006965 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006966
6967 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00006968 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006969 child = child->next;
6970 }
6971
Daniel Veillard4255d502002-04-16 15:50:10 +00006972 child = node->children;
6973 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00006974 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006975 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006976 }
6977 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006978 xmlSchemaPContentErr(ctxt,
6979 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006980 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006981 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006982 }
6983
6984 return (ret);
6985}
6986
6987/**
6988 * xmlSchemaParseAnyAttribute:
6989 * @ctxt: a schema validation context
6990 * @schema: the schema being built
6991 * @node: a subtree containing XML Schema informations
6992 *
6993 * parse a XML schema AnyAttrribute declaration
6994 * *WARNING* this interface is highly subject to change
6995 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006996 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006997 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006998static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006999xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7000 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007001{
Daniel Veillard3646d642004-06-02 19:19:14 +00007002 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00007003 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007004 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007005
7006 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7007 return (NULL);
7008
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007009 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7010 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007011 if (ret == NULL) {
7012 return (NULL);
7013 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007014 /*
7015 * Check for illegal attributes.
7016 */
7017 attr = node->properties;
7018 while (attr != NULL) {
7019 if (attr->ns == NULL) {
7020 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7021 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7022 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007023 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007024 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007025 }
7026 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007027 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007028 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007029 }
7030 attr = attr->next;
7031 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007032 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007033 /*
7034 * Parse the namespace list.
7035 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007036 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007037 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007038 /*
7039 * And now for the children...
7040 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007041 child = node->children;
7042 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007043 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007044 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007045 }
7046 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007047 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007048 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007049 NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007050 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007051 }
7052
7053 return (ret);
7054}
7055
7056
7057/**
7058 * xmlSchemaParseAttribute:
7059 * @ctxt: a schema validation context
7060 * @schema: the schema being built
7061 * @node: a subtree containing XML Schema informations
7062 *
7063 * parse a XML schema Attrribute declaration
7064 * *WARNING* this interface is highly subject to change
7065 *
William M. Bracke7091952004-05-11 15:09:58 +00007066 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007067 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007068static xmlSchemaBasicItemPtr
7069xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7070 xmlSchemaPtr schema,
7071 xmlNodePtr node,
7072 xmlSchemaItemListPtr uses,
7073 int parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00007074{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007075 const xmlChar *attrValue, *name = NULL, *ns = NULL;
7076 xmlSchemaAttributeUsePtr use = NULL;
7077 xmlNodePtr child = NULL;
7078 xmlAttrPtr attr;
7079 const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7080 int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7081 int nberrors, hasForm = 0, defValueType = 0;
7082
7083#define WXS_ATTR_DEF_VAL_DEFAULT 1
7084#define WXS_ATTR_DEF_VAL_FIXED 2
7085
7086 /*
7087 * 3.2.3 Constraints on XML Representations of Attribute Declarations
7088 */
7089
7090 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7091 return (NULL);
7092 attr = xmlSchemaGetPropNode(node, "ref");
7093 if (attr != NULL) {
7094 if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7095 NULL, attr, &tmpNs, &tmpName) != 0) {
7096 return (NULL);
7097 }
7098 if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7099 return(NULL);
7100 isRef = 1;
7101 }
7102 nberrors = pctxt->nberrors;
7103 /*
7104 * Check for illegal attributes.
7105 */
7106 attr = node->properties;
7107 while (attr != NULL) {
7108 if (attr->ns == NULL) {
7109 if (isRef) {
7110 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7111 xmlSchemaPValAttrNodeID(pctxt, attr);
7112 goto attr_next;
7113 } else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7114 goto attr_next;
7115 }
7116 } else {
7117 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7118 goto attr_next;
7119 } else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7120 xmlSchemaPValAttrNodeID(pctxt, attr);
7121 goto attr_next;
7122 } else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7123 xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7124 attr, &tmpNs, &tmpName);
7125 goto attr_next;
7126 } else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7127 /*
7128 * Evaluate the target namespace
7129 */
7130 hasForm = 1;
7131 attrValue = xmlSchemaGetNodeContent(pctxt,
7132 (xmlNodePtr) attr);
7133 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7134 ns = pctxt->targetNamespace;
7135 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7136 {
7137 xmlSchemaPSimpleTypeErr(pctxt,
7138 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7139 NULL, (xmlNodePtr) attr,
7140 NULL, "(qualified | unqualified)",
7141 attrValue, NULL, NULL, NULL);
7142 }
7143 goto attr_next;
7144 }
7145 }
7146 if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7147
7148 attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7149 /* TODO: Maybe we need to normalize the value beforehand. */
7150 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7151 occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7152 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7153 occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7154 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7155 occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7156 else {
7157 xmlSchemaPSimpleTypeErr(pctxt,
7158 XML_SCHEMAP_INVALID_ATTR_USE,
7159 NULL, (xmlNodePtr) attr,
7160 NULL, "(optional | prohibited | required)",
7161 attrValue, NULL, NULL, NULL);
7162 }
7163 goto attr_next;
7164 } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7165 /*
7166 * 3.2.3 : 1
7167 * default and fixed must not both be present.
7168 */
7169 if (defValue) {
7170 xmlSchemaPMutualExclAttrErr(pctxt,
7171 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7172 NULL, attr, "default", "fixed");
7173 } else {
7174 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7175 defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7176 }
7177 goto attr_next;
7178 } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7179 /*
7180 * 3.2.3 : 1
7181 * default and fixed must not both be present.
7182 */
7183 if (defValue) {
7184 xmlSchemaPMutualExclAttrErr(pctxt,
7185 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7186 NULL, attr, "default", "fixed");
7187 } else {
7188 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7189 defValueType = WXS_ATTR_DEF_VAL_FIXED;
7190 }
7191 goto attr_next;
7192 }
7193 } else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7194 goto attr_next;
7195
7196 xmlSchemaPIllegalAttrErr(pctxt,
7197 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7198
7199attr_next:
7200 attr = attr->next;
7201 }
7202 /*
7203 * 3.2.3 : 2
7204 * If default and use are both present, use must have
7205 * the actual value optional.
7206 */
7207 if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7208 (occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7209 xmlSchemaPSimpleTypeErr(pctxt,
7210 XML_SCHEMAP_SRC_ATTRIBUTE_2,
7211 NULL, node, NULL,
7212 "(optional | prohibited | required)", NULL,
7213 "The value of the attribute 'use' must be 'optional' "
7214 "if the attribute 'default' is present",
7215 NULL, NULL);
7216 }
7217 /*
7218 * We want correct attributes.
7219 */
7220 if (nberrors != pctxt->nberrors)
7221 return(NULL);
7222 if (! isRef) {
7223 xmlSchemaAttributePtr attrDecl;
7224
7225 /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7226 if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7227 ns = pctxt->targetNamespace;
7228 /*
7229 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7230 * TODO: Move this to the component layer.
7231 */
7232 if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7233 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7234 XML_SCHEMAP_NO_XSI,
7235 node, NULL,
7236 "The target namespace must not match '%s'",
7237 xmlSchemaInstanceNs, NULL);
7238 }
7239 attr = xmlSchemaGetPropNode(node, "name");
7240 if (attr == NULL) {
7241 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7242 NULL, node, "name", NULL);
7243 return (NULL);
7244 }
7245 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7246 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7247 return (NULL);
7248 }
7249 /*
7250 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7251 * TODO: Move this to the component layer.
7252 */
7253 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7254 xmlSchemaPSimpleTypeErr(pctxt,
7255 XML_SCHEMAP_NO_XMLNS,
7256 NULL, (xmlNodePtr) attr,
7257 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7258 "The value of the attribute must not match 'xmlns'",
7259 NULL, NULL);
7260 return (NULL);
7261 }
7262 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7263 goto check_children;
7264 /*
7265 * Create the attribute use component.
7266 */
7267 use = xmlSchemaAddAttributeUse(pctxt, node);
7268 if (use == NULL)
7269 return(NULL);
7270 use->occurs = occurs;
7271 /*
7272 * Create the attribute declaration.
7273 */
7274 attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7275 if (attrDecl == NULL)
7276 return (NULL);
7277 if (tmpName != NULL) {
7278 attrDecl->typeName = tmpName;
7279 attrDecl->typeNs = tmpNs;
7280 }
7281 use->attrDecl = attrDecl;
7282 /*
7283 * Value constraint.
7284 */
7285 if (defValue != NULL) {
7286 attrDecl->defValue = defValue;
7287 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7288 attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7289 }
7290 } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7291 xmlSchemaQNameRefPtr ref;
7292
7293 /*
7294 * Create the attribute use component.
7295 */
7296 use = xmlSchemaAddAttributeUse(pctxt, node);
7297 if (use == NULL)
7298 return(NULL);
7299 /*
7300 * We need to resolve the reference at later stage.
7301 */
7302 WXS_ADD_PENDING(pctxt, use);
7303 use->occurs = occurs;
7304 /*
7305 * Create a QName reference to the attribute declaration.
7306 */
7307 ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7308 tmpName, tmpNs);
7309 if (ref == NULL)
7310 return(NULL);
7311 /*
7312 * Assign the reference. This will be substituted for the
7313 * referenced attribute declaration when the QName is resolved.
7314 */
7315 use->attrDecl = WXS_ATTR_CAST ref;
7316 /*
7317 * Value constraint.
7318 */
7319 if (defValue != NULL)
7320 use->defValue = defValue;
7321 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7322 use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7323 }
7324
7325check_children:
7326 /*
7327 * And now for the children...
7328 */
7329 child = node->children;
7330 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7331 xmlSchemaAttributeUseProhibPtr prohib;
7332
7333 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007334 xmlSchemaParseAnnotation(pctxt, child, 0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007335 child = child->next;
7336 }
7337 if (child != NULL) {
7338 xmlSchemaPContentErr(pctxt,
7339 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7340 NULL, node, child, NULL,
7341 "(annotation?)");
7342 }
7343 /*
7344 * Check for pointlessness of attribute prohibitions.
7345 */
7346 if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7347 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7348 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7349 node, NULL,
7350 "Skipping attribute use prohibition, since it is "
7351 "pointless inside an <attributeGroup>",
7352 NULL, NULL, NULL);
7353 return(NULL);
7354 } else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7355 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7356 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7357 node, NULL,
7358 "Skipping attribute use prohibition, since it is "
7359 "pointless when extending a type",
7360 NULL, NULL, NULL);
7361 return(NULL);
7362 }
7363 if (! isRef) {
7364 tmpName = name;
7365 tmpNs = ns;
7366 }
7367 /*
7368 * Check for duplicate attribute prohibitions.
7369 */
7370 if (uses) {
7371 int i;
7372
7373 for (i = 0; i < uses->nbItems; i++) {
7374 use = uses->items[i];
7375 if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7376 (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7377 (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7378 {
7379 xmlChar *str = NULL;
7380
7381 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7382 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7383 node, NULL,
7384 "Skipping duplicate attribute use prohibition '%s'",
7385 xmlSchemaFormatQName(&str, tmpNs, tmpName),
7386 NULL, NULL);
7387 FREE_AND_NULL(str)
7388 return(NULL);
7389 }
7390 }
7391 }
7392 /*
7393 * Create the attribute prohibition helper component.
7394 */
7395 prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7396 if (prohib == NULL)
7397 return(NULL);
7398 prohib->node = node;
7399 prohib->name = tmpName;
7400 prohib->targetNamespace = tmpNs;
7401 if (isRef) {
7402 /*
7403 * We need at least to resolve to the attribute declaration.
7404 */
7405 WXS_ADD_PENDING(pctxt, prohib);
7406 }
7407 return(WXS_BASIC_CAST prohib);
7408 } else {
7409 if (IS_SCHEMA(child, "annotation")) {
7410 /*
7411 * TODO: Should this go into the attr decl?
7412 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007413 use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007414 child = child->next;
7415 }
7416 if (isRef) {
7417 if (child != NULL) {
7418 if (IS_SCHEMA(child, "simpleType"))
7419 /*
7420 * 3.2.3 : 3.2
7421 * If ref is present, then all of <simpleType>,
7422 * form and type must be absent.
7423 */
7424 xmlSchemaPContentErr(pctxt,
7425 XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7426 NULL, node, child, NULL,
7427 "(annotation?)");
7428 else
7429 xmlSchemaPContentErr(pctxt,
7430 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7431 NULL, node, child, NULL,
7432 "(annotation?)");
7433 }
7434 } else {
7435 if (IS_SCHEMA(child, "simpleType")) {
7436 if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7437 /*
7438 * 3.2.3 : 4
7439 * type and <simpleType> must not both be present.
7440 */
7441 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7442 NULL, node, child,
7443 "The attribute 'type' and the <simpleType> child "
7444 "are mutually exclusive", NULL);
7445 } else
7446 WXS_ATTRUSE_TYPEDEF(use) =
7447 xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7448 child = child->next;
7449 }
7450 if (child != NULL)
7451 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7452 NULL, node, child, NULL,
7453 "(annotation?, simpleType?)");
7454 }
7455 }
7456 return (WXS_BASIC_CAST use);
7457}
7458
7459
7460static xmlSchemaAttributePtr
7461xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7462 xmlSchemaPtr schema,
7463 xmlNodePtr node)
7464{
7465 const xmlChar *attrValue;
Daniel Veillard4255d502002-04-16 15:50:10 +00007466 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007467 xmlNodePtr child = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007468 xmlAttrPtr attr;
William M. Bracke7091952004-05-11 15:09:58 +00007469
7470 /*
7471 * Note that the w3c spec assumes the schema to be validated with schema
7472 * for schemas beforehand.
7473 *
7474 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00007475 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007476 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7477 return (NULL);
7478 /*
7479 * 3.2.3 : 3.1
7480 * One of ref or name must be present, but not both
7481 */
7482 attr = xmlSchemaGetPropNode(node, "name");
7483 if (attr == NULL) {
7484 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7485 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007486 return (NULL);
7487 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007488 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7489 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7490 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007491 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007492 /*
7493 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7494 * TODO: Move this to the component layer.
7495 */
7496 if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7497 xmlSchemaPSimpleTypeErr(pctxt,
7498 XML_SCHEMAP_NO_XMLNS,
7499 NULL, (xmlNodePtr) attr,
7500 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7501 "The value of the attribute must not match 'xmlns'",
7502 NULL, NULL);
7503 return (NULL);
7504 }
7505 /*
7506 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7507 * TODO: Move this to the component layer.
7508 * Or better leave it here and add it to the component layer
7509 * if we have a schema construction API.
7510 */
7511 if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7512 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7513 XML_SCHEMAP_NO_XSI, node, NULL,
7514 "The target namespace must not match '%s'",
7515 xmlSchemaInstanceNs, NULL);
7516 }
7517
7518 ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7519 pctxt->targetNamespace, node, 1);
7520 if (ret == NULL)
7521 return (NULL);
7522 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7523
7524 /*
7525 * Check for illegal attributes.
7526 */
7527 attr = node->properties;
7528 while (attr != NULL) {
7529 if (attr->ns == NULL) {
7530 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7531 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7532 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7533 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7534 (!xmlStrEqual(attr->name, BAD_CAST "type")))
7535 {
7536 xmlSchemaPIllegalAttrErr(pctxt,
7537 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7538 }
7539 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7540 xmlSchemaPIllegalAttrErr(pctxt,
7541 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7542 }
7543 attr = attr->next;
7544 }
7545 xmlSchemaPValAttrQName(pctxt, schema, NULL,
7546 node, "type", &ret->typeNs, &ret->typeName);
7547
7548 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00007549 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007550 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00007551 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007552 ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007553 if (ret->defValue != NULL)
7554 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007555 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007556 * Attribute "default".
7557 */
7558 attr = xmlSchemaGetPropNode(node, "default");
7559 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007560 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007561 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007562 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007563 */
7564 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007565 xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7566 WXS_BASIC_CAST ret, attr, "default", "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007567 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007568 ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007569 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007570 /*
7571 * And now for the children...
7572 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007573 child = node->children;
7574 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007575 ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007576 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007577 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007578 if (IS_SCHEMA(child, "simpleType")) {
7579 if (ret->typeName != NULL) {
7580 /*
7581 * 3.2.3 : 4
7582 * type and <simpleType> must not both be present.
7583 */
7584 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7585 NULL, node, child,
7586 "The attribute 'type' and the <simpleType> child "
7587 "are mutually exclusive", NULL);
7588 } else
7589 ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7590 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007591 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007592 if (child != NULL)
7593 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7594 NULL, node, child, NULL,
7595 "(annotation?, simpleType?)");
7596
Daniel Veillard4255d502002-04-16 15:50:10 +00007597 return (ret);
7598}
7599
7600/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007601 * xmlSchemaParseAttributeGroupRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00007602 * @ctxt: a schema validation context
7603 * @schema: the schema being built
7604 * @node: a subtree containing XML Schema informations
7605 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007606 * Parse an attribute group definition reference.
7607 * Note that a reference to an attribute group does not
7608 * correspond to any component at all.
Daniel Veillard4255d502002-04-16 15:50:10 +00007609 * *WARNING* this interface is highly subject to change
7610 *
7611 * Returns the attribute group or NULL in case of error.
7612 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007613static xmlSchemaQNameRefPtr
7614xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7615 xmlSchemaPtr schema,
7616 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007617{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007618 xmlSchemaQNameRefPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00007619 xmlNodePtr child = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007620 xmlAttrPtr attr;
7621 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007622
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007623 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00007624 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007625
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007626 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007627 if (attr == NULL) {
7628 xmlSchemaPMissingAttrErr(pctxt,
7629 XML_SCHEMAP_S4S_ATTR_MISSING,
7630 NULL, node, "ref", NULL);
7631 return (NULL);
7632 }
7633 xmlSchemaPValAttrNodeQName(pctxt, schema,
7634 NULL, attr, &refNs, &ref);
7635 if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7636 return(NULL);
7637
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007638 /*
7639 * Check for illegal attributes.
7640 */
7641 attr = node->properties;
7642 while (attr != NULL) {
7643 if (attr->ns == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007644 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007645 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007646 {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007647 xmlSchemaPIllegalAttrErr(pctxt,
7648 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007649 }
7650 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007651 xmlSchemaPIllegalAttrErr(pctxt,
7652 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007653 }
7654 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007655 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00007656 /* Attribute ID */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007657 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7658
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007659 /*
7660 * And now for the children...
7661 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007662 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00007663 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007664 /*
7665 * TODO: We do not have a place to store the annotation, do we?
7666 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007667 xmlSchemaParseAnnotation(pctxt, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007668 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007669 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007670 if (child != NULL) {
7671 xmlSchemaPContentErr(pctxt,
7672 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7673 NULL, node, child, NULL,
7674 "(annotation?)");
7675 }
7676
7677 /*
7678 * Handle attribute group redefinitions.
7679 */
7680 if (pctxt->isRedefine && pctxt->redef &&
7681 (pctxt->redef->item->type ==
7682 XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7683 (ref == pctxt->redef->refName) &&
7684 (refNs == pctxt->redef->refTargetNs))
7685 {
7686 /*
7687 * SPEC src-redefine:
7688 * (7.1) "If it has an <attributeGroup> among its contents
7689 * the ·actual value· of whose ref [attribute] is the same
7690 * as the ·actual value· of its own name attribute plus
7691 * target namespace, then it must have exactly one such group."
7692 */
7693 if (pctxt->redefCounter != 0) {
7694 xmlChar *str = NULL;
7695
7696 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7697 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7698 "The redefining attribute group definition "
7699 "'%s' must not contain more than one "
7700 "reference to the redefined definition",
7701 xmlSchemaFormatQName(&str, refNs, ref), NULL);
7702 FREE_AND_NULL(str);
7703 return(NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007704 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007705 pctxt->redefCounter++;
7706 /*
7707 * URGENT TODO: How to ensure that the reference will not be
7708 * handled by the normal component resolution mechanism?
7709 */
7710 ret = xmlSchemaNewQNameRef(pctxt,
7711 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7712 if (ret == NULL)
7713 return(NULL);
7714 ret->node = node;
7715 pctxt->redef->reference = WXS_BASIC_CAST ret;
7716 } else {
7717 /*
7718 * Create a QName-reference helper component. We will substitute this
7719 * component for the attribute uses of the referenced attribute group
7720 * definition.
7721 */
7722 ret = xmlSchemaNewQNameRef(pctxt,
7723 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7724 if (ret == NULL)
7725 return(NULL);
7726 ret->node = node;
7727 /* Add to pending items, to be able to resolve the reference. */
7728 WXS_ADD_PENDING(pctxt, ret);
7729 }
7730 return (ret);
7731}
7732
7733/**
7734 * xmlSchemaParseAttributeGroupDefinition:
7735 * @pctxt: a schema validation context
7736 * @schema: the schema being built
7737 * @node: a subtree containing XML Schema informations
7738 *
7739 * parse a XML schema Attribute Group declaration
7740 * *WARNING* this interface is highly subject to change
7741 *
7742 * Returns the attribute group definition or NULL in case of error.
7743 */
7744static xmlSchemaAttributeGroupPtr
7745xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7746 xmlSchemaPtr schema,
7747 xmlNodePtr node)
7748{
7749 const xmlChar *name;
7750 xmlSchemaAttributeGroupPtr ret;
7751 xmlNodePtr child = NULL;
7752 xmlAttrPtr attr;
7753 int hasRefs = 0;
7754
7755 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7756 return (NULL);
7757
7758 attr = xmlSchemaGetPropNode(node, "name");
7759 if (attr == NULL) {
7760 xmlSchemaPMissingAttrErr(pctxt,
7761 XML_SCHEMAP_S4S_ATTR_MISSING,
7762 NULL, node, "name", NULL);
7763 return (NULL);
7764 }
7765 /*
7766 * The name is crucial, exit if invalid.
7767 */
7768 if (xmlSchemaPValAttrNode(pctxt,
7769 NULL, attr,
7770 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7771 return (NULL);
7772 }
7773 ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7774 name, pctxt->targetNamespace, node);
7775 if (ret == NULL)
7776 return (NULL);
7777 /*
7778 * Check for illegal attributes.
7779 */
7780 attr = node->properties;
7781 while (attr != NULL) {
7782 if (attr->ns == NULL) {
7783 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7784 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7785 {
7786 xmlSchemaPIllegalAttrErr(pctxt,
7787 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7788 }
7789 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7790 xmlSchemaPIllegalAttrErr(pctxt,
7791 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7792 }
7793 attr = attr->next;
7794 }
7795 /* Attribute ID */
7796 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7797 /*
7798 * And now for the children...
7799 */
7800 child = node->children;
7801 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007802 ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007803 child = child->next;
7804 }
7805 /*
7806 * Parse contained attribute decls/refs.
7807 */
7808 if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7809 (xmlSchemaItemListPtr *) &(ret->attrUses),
7810 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7811 return(NULL);
7812 if (hasRefs)
7813 ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7814 /*
7815 * Parse the attribute wildcard.
7816 */
7817 if (IS_SCHEMA(child, "anyAttribute")) {
7818 ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7819 schema, child);
7820 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007821 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007822 if (child != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007823 xmlSchemaPContentErr(pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007824 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007825 NULL, node, child, NULL,
7826 "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007827 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007828 return (ret);
7829}
7830
7831/**
William M. Brack2f2a6632004-08-20 23:09:47 +00007832 * xmlSchemaPValAttrFormDefault:
7833 * @value: the value
7834 * @flags: the flags to be modified
7835 * @flagQualified: the specific flag for "qualified"
7836 *
7837 * Returns 0 if the value is valid, 1 otherwise.
7838 */
7839static int
7840xmlSchemaPValAttrFormDefault(const xmlChar *value,
7841 int *flags,
7842 int flagQualified)
7843{
7844 if (xmlStrEqual(value, BAD_CAST "qualified")) {
7845 if ((*flags & flagQualified) == 0)
7846 *flags |= flagQualified;
7847 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007848 return (1);
7849
William M. Brack2f2a6632004-08-20 23:09:47 +00007850 return (0);
7851}
7852
7853/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00007854 * xmlSchemaPValAttrBlockFinal:
7855 * @value: the value
7856 * @flags: the flags to be modified
7857 * @flagAll: the specific flag for "#all"
7858 * @flagExtension: the specific flag for "extension"
7859 * @flagRestriction: the specific flag for "restriction"
7860 * @flagSubstitution: the specific flag for "substitution"
7861 * @flagList: the specific flag for "list"
7862 * @flagUnion: the specific flag for "union"
7863 *
7864 * Validates the value of the attribute "final" and "block". The value
7865 * is converted into the specified flag values and returned in @flags.
7866 *
7867 * Returns 0 if the value is valid, 1 otherwise.
7868 */
7869
7870static int
7871xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007872 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007873 int flagAll,
7874 int flagExtension,
7875 int flagRestriction,
7876 int flagSubstitution,
7877 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007878 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007879{
7880 int ret = 0;
7881
7882 /*
7883 * TODO: This does not check for dublicate entries.
7884 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007885 if ((flags == NULL) || (value == NULL))
7886 return (-1);
7887 if (value[0] == 0)
7888 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007889 if (xmlStrEqual(value, BAD_CAST "#all")) {
7890 if (flagAll != -1)
7891 *flags |= flagAll;
7892 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007893 if (flagExtension != -1)
7894 *flags |= flagExtension;
7895 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007896 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007897 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007898 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007899 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007900 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007901 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007902 *flags |= flagUnion;
7903 }
7904 } else {
7905 const xmlChar *end, *cur = value;
7906 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007907
Daniel Veillardc0826a72004-08-10 14:17:33 +00007908 do {
7909 while (IS_BLANK_CH(*cur))
7910 cur++;
7911 end = cur;
7912 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7913 end++;
7914 if (end == cur)
7915 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007916 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007917 if (xmlStrEqual(item, BAD_CAST "extension")) {
7918 if (flagExtension != -1) {
7919 if ((*flags & flagExtension) == 0)
7920 *flags |= flagExtension;
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 "restriction")) {
7924 if (flagRestriction != -1) {
7925 if ((*flags & flagRestriction) == 0)
7926 *flags |= flagRestriction;
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 "substitution")) {
7930 if (flagSubstitution != -1) {
7931 if ((*flags & flagSubstitution) == 0)
7932 *flags |= flagSubstitution;
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 "list")) {
7936 if (flagList != -1) {
7937 if ((*flags & flagList) == 0)
7938 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007939 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007940 ret = 1;
7941 } else if (xmlStrEqual(item, BAD_CAST "union")) {
7942 if (flagUnion != -1) {
7943 if ((*flags & flagUnion) == 0)
7944 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007945 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007946 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007947 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007948 ret = 1;
7949 if (item != NULL)
7950 xmlFree(item);
7951 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007952 } while ((ret == 0) && (*cur != 0));
7953 }
7954
Daniel Veillardc0826a72004-08-10 14:17:33 +00007955 return (ret);
7956}
7957
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007958static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007959xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007960 xmlSchemaIDCPtr idc,
7961 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007962 xmlAttrPtr attr,
7963 int isField)
7964{
7965 xmlNodePtr node;
7966
7967 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007968 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007969 * Schema Component Constraint: Selector Value OK
7970 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007971 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007972 * in [XPath].
7973 */
7974 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007975 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007976 XML_SCHEMAP_INTERNAL,
7977 "Internal error: xmlSchemaCheckCSelectorXPath, "
7978 "the selector is not specified.\n", NULL, NULL);
7979 return (-1);
7980 }
7981 if (attr == NULL)
7982 node = idc->node;
7983 else
7984 node = (xmlNodePtr) attr;
7985 if (selector->xpath == NULL) {
7986 xmlSchemaPCustomErr(ctxt,
7987 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007988 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007989 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007990 "The XPath expression of the selector is not valid", NULL);
7991 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
7992 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007993 const xmlChar **nsArray = NULL;
7994 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007995 /*
7996 * Compile the XPath expression.
7997 */
7998 /*
7999 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008000 * TODO: Call xmlPatterncompile with different options for selector/
8001 * field.
8002 */
Daniel Veillard14b56432006-03-09 18:41:40 +00008003 if (attr == NULL)
Daniel Veillardaac7c682006-03-10 13:40:16 +00008004 nsList = NULL;
Daniel Veillard14b56432006-03-09 18:41:40 +00008005 else
8006 nsList = xmlGetNsList(attr->doc, attr->parent);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008007 /*
8008 * Build an array of prefixes and namespaces.
8009 */
8010 if (nsList != NULL) {
8011 int i, count = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008012
8013 for (i = 0; nsList[i] != NULL; i++)
8014 count++;
8015
8016 nsArray = (const xmlChar **) xmlMalloc(
8017 (count * 2 + 1) * sizeof(const xmlChar *));
8018 if (nsArray == NULL) {
8019 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8020 NULL);
Kasimier T. Buchcik940ab0c2005-10-19 17:00:53 +00008021 xmlFree(nsList);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008022 return (-1);
8023 }
8024 for (i = 0; i < count; i++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008025 nsArray[2 * i] = nsList[i]->href;
8026 nsArray[2 * i + 1] = nsList[i]->prefix;
8027 }
8028 nsArray[count * 2] = NULL;
8029 xmlFree(nsList);
8030 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008031 /*
8032 * TODO: Differentiate between "selector" and "field".
8033 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008034 if (isField)
8035 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008036 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008037 else
8038 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008039 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008040 if (nsArray != NULL)
8041 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008042
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00008043 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008044 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00008045 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008046 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008047 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008048 "The XPath expression '%s' could not be "
8049 "compiled", selector->xpath);
8050 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008051 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008052 }
8053 return (0);
8054}
8055
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008056#define ADD_ANNOTATION(annot) \
8057 xmlSchemaAnnotPtr cur = item->annot; \
8058 if (item->annot == NULL) { \
8059 item->annot = annot; \
8060 return (annot); \
8061 } \
8062 cur = item->annot; \
8063 if (cur->next != NULL) { \
8064 cur = cur->next; \
8065 } \
8066 cur->next = annot;
8067
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008068/**
8069 * xmlSchemaAssignAnnotation:
8070 * @item: the schema component
8071 * @annot: the annotation
8072 *
8073 * Adds the annotation to the given schema component.
8074 *
8075 * Returns the given annotaion.
8076 */
8077static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008078xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8079 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008080{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008081 if ((annItem == NULL) || (annot == NULL))
8082 return (NULL);
8083 switch (annItem->type) {
8084 case XML_SCHEMA_TYPE_ELEMENT: {
8085 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8086 ADD_ANNOTATION(annot)
8087 }
8088 break;
8089 case XML_SCHEMA_TYPE_ATTRIBUTE: {
8090 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8091 ADD_ANNOTATION(annot)
8092 }
8093 break;
8094 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8095 case XML_SCHEMA_TYPE_ANY: {
8096 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8097 ADD_ANNOTATION(annot)
8098 }
8099 break;
8100 case XML_SCHEMA_TYPE_PARTICLE:
8101 case XML_SCHEMA_TYPE_IDC_KEY:
8102 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008103 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008104 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8105 ADD_ANNOTATION(annot)
8106 }
8107 break;
8108 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8109 xmlSchemaAttributeGroupPtr item =
8110 (xmlSchemaAttributeGroupPtr) annItem;
8111 ADD_ANNOTATION(annot)
8112 }
8113 break;
8114 case XML_SCHEMA_TYPE_NOTATION: {
8115 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8116 ADD_ANNOTATION(annot)
8117 }
8118 break;
8119 case XML_SCHEMA_FACET_MININCLUSIVE:
8120 case XML_SCHEMA_FACET_MINEXCLUSIVE:
8121 case XML_SCHEMA_FACET_MAXINCLUSIVE:
8122 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8123 case XML_SCHEMA_FACET_TOTALDIGITS:
8124 case XML_SCHEMA_FACET_FRACTIONDIGITS:
8125 case XML_SCHEMA_FACET_PATTERN:
8126 case XML_SCHEMA_FACET_ENUMERATION:
8127 case XML_SCHEMA_FACET_WHITESPACE:
8128 case XML_SCHEMA_FACET_LENGTH:
8129 case XML_SCHEMA_FACET_MAXLENGTH:
8130 case XML_SCHEMA_FACET_MINLENGTH: {
8131 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8132 ADD_ANNOTATION(annot)
8133 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008134 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008135 case XML_SCHEMA_TYPE_SIMPLE:
8136 case XML_SCHEMA_TYPE_COMPLEX: {
8137 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8138 ADD_ANNOTATION(annot)
8139 }
8140 break;
8141 case XML_SCHEMA_TYPE_GROUP: {
8142 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8143 ADD_ANNOTATION(annot)
8144 }
8145 break;
8146 case XML_SCHEMA_TYPE_SEQUENCE:
8147 case XML_SCHEMA_TYPE_CHOICE:
8148 case XML_SCHEMA_TYPE_ALL: {
8149 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8150 ADD_ANNOTATION(annot)
8151 }
8152 break;
8153 default:
8154 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008155 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008156 NULL, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008157 "Internal error: xmlSchemaAddAnnotation, "
8158 "The item is not a annotated schema component", NULL);
8159 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008160 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008161 return (annot);
8162}
8163
8164/**
8165 * xmlSchemaParseIDCSelectorAndField:
8166 * @ctxt: a schema validation context
8167 * @schema: the schema being built
8168 * @node: a subtree containing XML Schema informations
8169 *
8170 * Parses a XML Schema identity-contraint definition's
8171 * <selector> and <field> elements.
8172 *
8173 * Returns the parsed identity-constraint definition.
8174 */
8175static xmlSchemaIDCSelectPtr
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008176xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008177 xmlSchemaIDCPtr idc,
8178 xmlNodePtr node,
8179 int isField)
8180{
8181 xmlSchemaIDCSelectPtr item;
8182 xmlNodePtr child = NULL;
8183 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008184
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008185 /*
8186 * Check for illegal attributes.
8187 */
8188 attr = node->properties;
8189 while (attr != NULL) {
8190 if (attr->ns == NULL) {
8191 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8192 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008193 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008194 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008195 }
8196 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008197 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008198 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008199 }
8200 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008201 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008202 /*
8203 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008204 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008205 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8206 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008207 xmlSchemaPErrMemory(ctxt,
8208 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008209 NULL);
8210 return (NULL);
8211 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008212 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008213 /*
8214 * Attribute "xpath" (mandatory).
8215 */
8216 attr = xmlSchemaGetPropNode(node, "xpath");
8217 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008218 xmlSchemaPMissingAttrErr(ctxt,
8219 XML_SCHEMAP_S4S_ATTR_MISSING,
8220 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008221 "name", NULL);
8222 } else {
8223 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8224 /*
8225 * URGENT TODO: "field"s have an other syntax than "selector"s.
8226 */
8227
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008228 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8229 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008230 xmlSchemaPErr(ctxt,
8231 (xmlNodePtr) attr,
8232 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008233 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008234 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008235 NULL, NULL);
8236 }
8237
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008238 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008239 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008240 /*
8241 * And now for the children...
8242 */
8243 child = node->children;
8244 if (IS_SCHEMA(child, "annotation")) {
8245 /*
8246 * Add the annotation to the parent IDC.
8247 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008248 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008249 xmlSchemaParseAnnotation(ctxt, child, 1));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008250 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008251 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008252 if (child != NULL) {
8253 xmlSchemaPContentErr(ctxt,
8254 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008255 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008256 NULL, "(annotation?)");
8257 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008258
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008259 return (item);
8260}
8261
8262/**
8263 * xmlSchemaParseIDC:
8264 * @ctxt: a schema validation context
8265 * @schema: the schema being built
8266 * @node: a subtree containing XML Schema informations
8267 *
8268 * Parses a XML Schema identity-contraint definition.
8269 *
8270 * Returns the parsed identity-constraint definition.
8271 */
8272static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008273xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008274 xmlSchemaPtr schema,
8275 xmlNodePtr node,
8276 xmlSchemaTypeType idcCategory,
8277 const xmlChar *targetNamespace)
8278{
8279 xmlSchemaIDCPtr item = NULL;
8280 xmlNodePtr child = NULL;
8281 xmlAttrPtr attr;
8282 const xmlChar *name = NULL;
8283 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008284
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008285 /*
8286 * Check for illegal attributes.
8287 */
8288 attr = node->properties;
8289 while (attr != NULL) {
8290 if (attr->ns == NULL) {
8291 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8292 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8293 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8294 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008295 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008296 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008297 }
8298 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008299 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008300 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008301 }
8302 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008303 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008304 /*
8305 * Attribute "name" (mandatory).
8306 */
8307 attr = xmlSchemaGetPropNode(node, "name");
8308 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008309 xmlSchemaPMissingAttrErr(ctxt,
8310 XML_SCHEMAP_S4S_ATTR_MISSING,
8311 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008312 "name", NULL);
8313 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008314 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008315 NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008316 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8317 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008318 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008319 /* Create the component. */
8320 item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8321 idcCategory, node);
8322 if (item == NULL)
8323 return(NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008324
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008325 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008326 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8327 /*
8328 * Attribute "refer" (mandatory).
8329 */
8330 attr = xmlSchemaGetPropNode(node, "refer");
8331 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008332 xmlSchemaPMissingAttrErr(ctxt,
8333 XML_SCHEMAP_S4S_ATTR_MISSING,
8334 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008335 "refer", NULL);
8336 } else {
8337 /*
8338 * Create a reference item.
8339 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008340 item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008341 NULL, NULL);
8342 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008343 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008344 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008345 NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008346 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008347 &(item->ref->name));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008348 xmlSchemaCheckReference(ctxt, schema, node, attr,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008349 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008350 }
8351 }
8352 /*
8353 * And now for the children...
8354 */
8355 child = node->children;
8356 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008357 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008358 child = child->next;
8359 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00008360 if (child == NULL) {
8361 xmlSchemaPContentErr(ctxt,
8362 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008363 NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00008364 "A child element is missing",
8365 "(annotation?, (selector, field+))");
8366 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008367 /*
8368 * Child element <selector>.
8369 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008370 if (IS_SCHEMA(child, "selector")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008371 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008372 item, child, 0);
8373 child = child->next;
8374 /*
8375 * Child elements <field>.
8376 */
8377 if (IS_SCHEMA(child, "field")) {
8378 do {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008379 field = xmlSchemaParseIDCSelectorAndField(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008380 item, child, 1);
8381 if (field != NULL) {
8382 field->index = item->nbFields;
8383 item->nbFields++;
8384 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008385 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008386 else
8387 item->fields = field;
8388 lastField = field;
8389 }
8390 child = child->next;
8391 } while (IS_SCHEMA(child, "field"));
8392 } else {
8393 xmlSchemaPContentErr(ctxt,
8394 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008395 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008396 NULL, "(annotation?, (selector, field+))");
8397 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008398 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008399 if (child != NULL) {
8400 xmlSchemaPContentErr(ctxt,
8401 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008402 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008403 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008404 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008405
8406 return (item);
8407}
8408
Daniel Veillardc0826a72004-08-10 14:17:33 +00008409/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008410 * xmlSchemaParseElement:
8411 * @ctxt: a schema validation context
8412 * @schema: the schema being built
8413 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008414 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00008415 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008416 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00008417 * *WARNING* this interface is highly subject to change
8418 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008419 * Returns the element declaration or a particle; NULL in case
8420 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00008421 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008422static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00008423xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008424 xmlNodePtr node, int *isElemRef, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008425{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008426 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008427 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008428 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008429 xmlNodePtr child = NULL;
8430 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008431 int min, max, isRef = 0;
8432 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00008433
8434 /* 3.3.3 Constraints on XML Representations of Element Declarations */
8435 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008436
Daniel Veillard4255d502002-04-16 15:50:10 +00008437 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008438 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008439
8440 if (isElemRef != NULL)
8441 *isElemRef = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008442 /*
8443 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008444 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008445 * robust.
8446 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008447 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008448 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008449 if ((topLevel) || (attr == NULL)) {
8450 if (nameAttr == NULL) {
8451 xmlSchemaPMissingAttrErr(ctxt,
8452 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008453 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008454 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008455 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008456 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00008457 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008458
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008459 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008460 child = node->children;
8461 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008462 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008463 child = child->next;
8464 }
8465 /*
8466 * Skip particle part if a global declaration.
8467 */
8468 if (topLevel)
8469 goto declaration_part;
8470 /*
8471 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008472 */
8473 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8474 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8475 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +00008476 particle = xmlSchemaAddParticle(ctxt, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008477 if (particle == NULL)
8478 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008479
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008480 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8481
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008482 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008483 const xmlChar *refNs = NULL, *ref = NULL;
8484 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008485 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008486 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00008487 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008488 if (isElemRef != NULL)
8489 *isElemRef = 1;
8490
Daniel Veillardc0826a72004-08-10 14:17:33 +00008491 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008492 NULL, attr, &refNs, &ref);
8493 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008494 /*
8495 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00008496 */
8497 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008498 xmlSchemaPMutualExclAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008499 XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008500 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008501 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008502 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008503 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008504 attr = node->properties;
8505 while (attr != NULL) {
8506 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008507 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8508 xmlStrEqual(attr->name, BAD_CAST "name") ||
8509 xmlStrEqual(attr->name, BAD_CAST "id") ||
8510 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8511 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8512 {
8513 attr = attr->next;
8514 continue;
8515 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008516 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008517 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008518 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008519 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008520 "Only the attributes 'minOccurs', 'maxOccurs' and "
8521 "'id' are allowed in addition to 'ref'");
8522 break;
8523 }
8524 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8525 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008526 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008527 }
8528 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008529 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008530 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008531 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008532 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008533 if (child != NULL) {
8534 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008535 NULL, node, child, NULL, "(annotation?)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008536 }
8537 if ((min == 0) && (max == 0))
8538 goto return_null;
8539 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008540 * Create the reference item and attach it to the particle.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008541 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008542 refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008543 ref, refNs);
8544 if (refer == NULL)
8545 goto return_null;
8546 particle->children = (xmlSchemaTreeItemPtr) refer;
8547 particle->annot = annot;
8548 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008549 * Add the particle to pending components, since the reference
8550 * need to be resolved.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008551 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008552 WXS_ADD_PENDING(ctxt, particle);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008553 return ((xmlSchemaBasicItemPtr) particle);
8554 }
8555 /*
8556 * The declaration part ===============================================
8557 */
8558declaration_part:
8559 {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008560 const xmlChar *ns = NULL, *fixed, *name, *attrValue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008561 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8562
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008563 if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008564 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008565 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008566 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008567 * Evaluate the target namespace.
8568 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008569 if (topLevel) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008570 ns = ctxt->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008571 } else {
8572 attr = xmlSchemaGetPropNode(node, "form");
8573 if (attr != NULL) {
8574 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8575 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008576 ns = ctxt->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008577 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008578 xmlSchemaPSimpleTypeErr(ctxt,
8579 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8580 NULL, (xmlNodePtr) attr,
8581 NULL, "(qualified | unqualified)",
8582 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008583 }
8584 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008585 ns = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008586 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008587 decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008588 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008589 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00008590 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008591 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008592 * Check for illegal attributes.
8593 */
William M. Bracke7091952004-05-11 15:09:58 +00008594 attr = node->properties;
8595 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008596 if (attr->ns == NULL) {
8597 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8598 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008599 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008600 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008601 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008602 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008603 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8604 {
8605 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008606 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008607 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008608 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008609 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008610 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008611 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008612 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008613 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8614 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008615 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8616
8617 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008618 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008619 }
8620 }
8621 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008622
Daniel Veillardc0826a72004-08-10 14:17:33 +00008623 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008624 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Bracke7091952004-05-11 15:09:58 +00008625 }
8626 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008627 }
William M. Bracke7091952004-05-11 15:09:58 +00008628 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008629 * Extract/validate attributes.
8630 */
8631 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008632 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008633 * Process top attributes of global element declarations here.
8634 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008635 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8636 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008637 xmlSchemaPValAttrQName(ctxt, schema,
8638 NULL, node, "substitutionGroup",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008639 &(decl->substGroupNs), &(decl->substGroup));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008640 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008641 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008642 /*
8643 * Attribute "final".
8644 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008645 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008646 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008647 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8648 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8649 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8650 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008651 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008652 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8653 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00008654 -1,
8655 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8656 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008657 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008658 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008659 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008660 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008661 attrValue, NULL, NULL, NULL);
8662 }
8663 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008664 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008665 /*
8666 * Attribute "block".
8667 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008668 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008669 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00008670 /*
8671 * Apply default "block" values.
8672 */
8673 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8674 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8675 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8676 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8677 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8678 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008679 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008680 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8681 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00008682 -1,
8683 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008684 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008685 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8686 xmlSchemaPSimpleTypeErr(ctxt,
8687 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008688 NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00008689 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008690 "restriction | substitution))", attrValue,
8691 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008692 }
8693 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008694 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008695 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008696
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008697 attr = xmlSchemaGetPropNode(node, "type");
8698 if (attr != NULL) {
8699 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008700 NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008701 &(decl->namedTypeNs), &(decl->namedType));
8702 xmlSchemaCheckReference(ctxt, schema, node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008703 attr, decl->namedTypeNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008704 }
8705 decl->value = xmlSchemaGetProp(ctxt, node, "default");
8706 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008707 if (attr != NULL) {
8708 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008709 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008710 /*
8711 * 3.3.3 : 1
8712 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008713 */
8714 xmlSchemaPMutualExclAttrErr(ctxt,
8715 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008716 NULL, attr, "default", "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008717 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008718 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8719 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008720 }
William M. Bracke7091952004-05-11 15:09:58 +00008721 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008722 /*
8723 * And now for the children...
8724 */
William M. Bracke7091952004-05-11 15:09:58 +00008725 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008726 /*
8727 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00008728 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008729 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00008730 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008731 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008732 xmlSchemaPContentErr(ctxt,
8733 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008734 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008735 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008736 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008737 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008738 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00008739 child = child->next;
8740 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008741 /*
8742 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00008743 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008744 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00008745 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008746 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008747 xmlSchemaPContentErr(ctxt,
8748 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008749 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008750 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008751 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008752 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008753 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00008754 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008755 }
William M. Bracke7091952004-05-11 15:09:58 +00008756 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00008757 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008758 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008759 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008760 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008761 } else if (IS_SCHEMA(child, "key")) {
8762 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008763 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008764 } else if (IS_SCHEMA(child, "keyref")) {
8765 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008766 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008767 }
8768 if (lastIDC != NULL)
8769 lastIDC->next = curIDC;
8770 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008771 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008772 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008773 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00008774 }
8775 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008776 xmlSchemaPContentErr(ctxt,
8777 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008778 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008779 NULL, "(annotation?, ((simpleType | complexType)?, "
8780 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008781 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008782 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008783 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008784 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008785 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00008786 * different layer.
8787 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008788 FREE_AND_NULL(des)
8789 if (topLevel)
8790 return ((xmlSchemaBasicItemPtr) decl);
8791 else {
8792 particle->children = (xmlSchemaTreeItemPtr) decl;
8793 return ((xmlSchemaBasicItemPtr) particle);
8794 }
8795
8796return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008797 FREE_AND_NULL(des);
8798 if (annot != NULL) {
8799 if (particle != NULL)
8800 particle->annot = NULL;
8801 if (decl != NULL)
8802 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008803 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008804 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008805 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008806}
8807
8808/**
8809 * xmlSchemaParseUnion:
8810 * @ctxt: a schema validation context
8811 * @schema: the schema being built
8812 * @node: a subtree containing XML Schema informations
8813 *
8814 * parse a XML schema Union definition
8815 * *WARNING* this interface is highly subject to change
8816 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008817 * Returns -1 in case of internal error, 0 in case of success and a positive
8818 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00008819 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008820static int
Daniel Veillard4255d502002-04-16 15:50:10 +00008821xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008822 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008823{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008824 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008825 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008826 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008827 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008828
8829 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008830 return (-1);
8831 /* Not a component, don't create it. */
8832 type = ctxt->ctxtType;
8833 /*
8834 * Mark the simple type as being of variety "union".
8835 */
8836 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008837 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008838 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8839 * then the ·simple ur-type definition·."
8840 */
8841 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008842 /*
8843 * Check for illegal attributes.
8844 */
8845 attr = node->properties;
8846 while (attr != NULL) {
8847 if (attr->ns == NULL) {
8848 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8849 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008850 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008851 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008852 }
8853 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008854 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008855 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008856 }
8857 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008858 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008859 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008860 /*
8861 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008862 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00008863 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008864 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008865 if (attr != NULL) {
8866 const xmlChar *end;
8867 xmlChar *tmp;
8868 const xmlChar *localName, *nsName;
8869 xmlSchemaTypeLinkPtr link, lastLink = NULL;
8870 xmlSchemaQNameRefPtr ref;
8871
8872 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008873 type->base = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008874 do {
8875 while (IS_BLANK_CH(*cur))
8876 cur++;
8877 end = cur;
8878 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8879 end++;
8880 if (end == cur)
8881 break;
8882 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008883 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008884 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008885 /*
8886 * Create the member type link.
8887 */
8888 link = (xmlSchemaTypeLinkPtr)
8889 xmlMalloc(sizeof(xmlSchemaTypeLink));
8890 if (link == NULL) {
8891 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8892 "allocating a type link", NULL);
8893 return (-1);
8894 }
8895 link->type = NULL;
8896 link->next = NULL;
8897 if (lastLink == NULL)
8898 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008899 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008900 lastLink->next = link;
8901 lastLink = link;
8902 /*
8903 * Create a reference item.
8904 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008905 ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008906 localName, nsName);
8907 if (ref == NULL) {
8908 FREE_AND_NULL(tmp)
8909 return (-1);
8910 }
8911 /*
8912 * Assign the reference to the link, it will be resolved
8913 * later during fixup of the union simple type.
8914 */
8915 link->type = (xmlSchemaTypePtr) ref;
8916 }
8917 FREE_AND_NULL(tmp)
8918 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008919 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008920
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008921 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008922 /*
8923 * And now for the children...
8924 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008925 child = node->children;
8926 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008927 /*
8928 * Add the annotation to the simple type ancestor.
8929 */
8930 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008931 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008932 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008933 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008934 if (IS_SCHEMA(child, "simpleType")) {
8935 xmlSchemaTypePtr subtype, last = NULL;
8936
8937 /*
8938 * Anchor the member types in the "subtypes" field of the
8939 * simple type.
8940 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008941 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008942 subtype = (xmlSchemaTypePtr)
8943 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8944 if (subtype != NULL) {
8945 if (last == NULL) {
8946 type->subtypes = subtype;
8947 last = subtype;
8948 } else {
8949 last->next = subtype;
8950 last = subtype;
8951 }
8952 last->next = NULL;
8953 }
8954 child = child->next;
8955 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008956 }
8957 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008958 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008959 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008960 NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008961 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008962 if ((attr == NULL) && (type->subtypes == NULL)) {
8963 /*
8964 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008965 * Either the memberTypes [attribute] of the <union> element must
8966 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008967 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008968 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008969 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008970 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008971 "Either the attribute 'memberTypes' or "
8972 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008973 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008974 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00008975}
8976
8977/**
8978 * xmlSchemaParseList:
8979 * @ctxt: a schema validation context
8980 * @schema: the schema being built
8981 * @node: a subtree containing XML Schema informations
8982 *
8983 * parse a XML schema List definition
8984 * *WARNING* this interface is highly subject to change
8985 *
William M. Bracke7091952004-05-11 15:09:58 +00008986 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008987 * 1 in case of success.
8988 */
8989static xmlSchemaTypePtr
8990xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008991 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008992{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008993 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008994 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008995 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008996
8997 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8998 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008999 /* Not a component, don't create it. */
9000 type = ctxt->ctxtType;
9001 /*
9002 * Mark the type as being of variety "list".
9003 */
9004 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009005 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009006 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
9007 * then the ·simple ur-type definition·."
9008 */
9009 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00009010 /*
9011 * Check for illegal attributes.
9012 */
9013 attr = node->properties;
9014 while (attr != NULL) {
9015 if (attr->ns == NULL) {
9016 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9017 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009018 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009019 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009020 }
9021 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009022 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009023 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009024 }
9025 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009026 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009027
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009028 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009029
William M. Brack2f2a6632004-08-20 23:09:47 +00009030 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009031 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9032 * fields for holding the reference to the itemType.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009033 *
9034 * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9035 * the "ref" fields.
William M. Brack2f2a6632004-08-20 23:09:47 +00009036 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009037 xmlSchemaPValAttrQName(ctxt, schema, NULL,
9038 node, "itemType", &(type->baseNs), &(type->base));
William M. Brack2f2a6632004-08-20 23:09:47 +00009039 /*
9040 * And now for the children...
9041 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009042 child = node->children;
9043 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009044 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009045 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009046 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009047 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009048 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009049 /*
9050 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009051 * Either the itemType [attribute] or the <simpleType> [child] of
9052 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009053 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009054 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009055 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009056 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009057 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00009058 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009059 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009060 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009061 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009062 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009063 child = child->next;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009064 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009065 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009066 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009067 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009068 "Either the attribute 'itemType' or the <simpleType> child "
9069 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009070 }
9071 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009072 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009073 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009074 NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00009075 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009076 if ((type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009077 (type->subtypes == NULL) &&
9078 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009079 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009080 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009081 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009082 "Either the attribute 'itemType' or the <simpleType> child "
9083 "must be present", NULL);
9084 }
9085 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009086}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009087
Daniel Veillard4255d502002-04-16 15:50:10 +00009088/**
9089 * xmlSchemaParseSimpleType:
9090 * @ctxt: a schema validation context
9091 * @schema: the schema being built
9092 * @node: a subtree containing XML Schema informations
9093 *
9094 * parse a XML schema Simple Type definition
9095 * *WARNING* this interface is highly subject to change
9096 *
William M. Bracke7091952004-05-11 15:09:58 +00009097 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00009098 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00009099 */
9100static xmlSchemaTypePtr
9101xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00009102 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00009103{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009104 xmlSchemaTypePtr type, oldCtxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009105 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009106 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009107 xmlAttrPtr attr;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009108 int hasRestriction = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009109
9110 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9111 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009112
Daniel Veillardc0826a72004-08-10 14:17:33 +00009113 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009114 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009115 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009116 xmlSchemaPMissingAttrErr(ctxt,
9117 XML_SCHEMAP_S4S_ATTR_MISSING,
9118 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009119 "name", NULL);
9120 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009121 } else {
9122 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009123 NULL, attr,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009124 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9125 return (NULL);
9126 /*
9127 * Skip built-in types.
9128 */
9129 if (ctxt->isS4S) {
9130 xmlSchemaTypePtr biType;
9131
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009132 if (ctxt->isRedefine) {
9133 /*
9134 * REDEFINE: Disallow redefinition of built-in-types.
9135 * TODO: It seems that the spec does not say anything
9136 * about this case.
9137 */
9138 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009139 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009140 "Redefinition of built-in simple types is not "
9141 "supported", NULL);
9142 return(NULL);
9143 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009144 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9145 if (biType != NULL)
9146 return (biType);
9147 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009148 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009149 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009150 /*
9151 * TargetNamespace:
9152 * SPEC "The ·actual value· of the targetNamespace [attribute]
9153 * of the <schema> ancestor element information item if present,
9154 * otherwise ·absent·.
9155 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009156 if (topLevel == 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009157#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009158 char buf[40];
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009159#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +00009160 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00009161 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009162 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009163#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009164 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009165 type = xmlSchemaAddType(ctxt, schema,
9166 XML_SCHEMA_TYPE_SIMPLE,
9167 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009168 ctxt->targetNamespace, node, 0);
9169#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009170 type = xmlSchemaAddType(ctxt, schema,
9171 XML_SCHEMA_TYPE_SIMPLE,
9172 NULL, ctxt->targetNamespace, node, 0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009173#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +00009174 if (type == NULL)
9175 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009176 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009177 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009178 /*
9179 * Check for illegal attributes.
9180 */
9181 attr = node->properties;
9182 while (attr != NULL) {
9183 if (attr->ns == NULL) {
9184 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009185 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009186 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009187 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009188 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009189 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009190 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009191 }
9192 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009193 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009194 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009195 /*
9196 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009197 *
9198 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009199 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009200 type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9201 attrValue, ctxt->targetNamespace, node, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009202 if (type == NULL)
9203 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009204 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009205 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009206 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9207 /*
9208 * Check for illegal attributes.
9209 */
9210 attr = node->properties;
9211 while (attr != NULL) {
9212 if (attr->ns == NULL) {
9213 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9214 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009215 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009216 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009217 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009218 }
9219 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009220 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009221 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009222 }
9223 attr = attr->next;
9224 }
9225 /*
9226 * Attribute "final".
9227 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009228 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009229 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009230 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9231 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9232 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9233 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9234 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9235 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009236 } else {
9237 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009238 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9239 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009240 XML_SCHEMAS_TYPE_FINAL_LIST,
9241 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9242
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009243 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009244 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009245 WXS_BASIC_CAST type, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009246 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00009247 attrValue, NULL, NULL, NULL);
9248 }
9249 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009250 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009251 type->targetNamespace = ctxt->targetNamespace;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009252 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009253 /*
9254 * And now for the children...
9255 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009256 oldCtxtType = ctxt->ctxtType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009257
Daniel Veillardc0826a72004-08-10 14:17:33 +00009258 ctxt->ctxtType = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009259
Daniel Veillard4255d502002-04-16 15:50:10 +00009260 child = node->children;
9261 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009262 type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009263 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009264 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009265 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009266 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009267 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009268 "(annotation?, (restriction | list | union))");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009269 } else if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009270 xmlSchemaParseRestriction(ctxt, schema, child,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009271 XML_SCHEMA_TYPE_SIMPLE);
9272 hasRestriction = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009273 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009274 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009275 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009276 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009277 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009278 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009279 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009280 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009281 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009282 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009283 NULL, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009284 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00009285 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009286 /*
9287 * REDEFINE: SPEC src-redefine (5)
9288 * "Within the [children], each <simpleType> must have a
9289 * <restriction> among its [children] ... the ·actual value· of whose
9290 * base [attribute] must be the same as the ·actual value· of its own
9291 * name attribute plus target namespace;"
9292 */
9293 if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9294 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009295 NULL, node, "This is a redefinition, thus the "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009296 "<simpleType> must have a <restriction> child", NULL);
9297 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009298
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009299 ctxt->ctxtType = oldCtxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009300 return (type);
9301}
9302
Daniel Veillard4255d502002-04-16 15:50:10 +00009303/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009304 * xmlSchemaParseModelGroupDefRef:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009305 * @ctxt: the parser context
9306 * @schema: the schema being built
9307 * @node: the node
Daniel Veillard4255d502002-04-16 15:50:10 +00009308 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009309 * Parses a reference to a model group definition.
Daniel Veillard4255d502002-04-16 15:50:10 +00009310 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009311 * We will return a particle component with a qname-component or
9312 * NULL in case of an error.
Daniel Veillard4255d502002-04-16 15:50:10 +00009313 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009314static xmlSchemaTreeItemPtr
9315xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9316 xmlSchemaPtr schema,
9317 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00009318{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009319 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009320 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009321 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009322 const xmlChar *ref = NULL, *refNs = NULL;
9323 int min, max;
9324
9325 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009326 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009327
9328 attr = xmlSchemaGetPropNode(node, "ref");
9329 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009330 xmlSchemaPMissingAttrErr(ctxt,
9331 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009332 NULL, node, "ref", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009333 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009334 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009335 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009336 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009337 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009338 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009339 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009340 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009341 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009342 /*
9343 * Check for illegal attributes.
9344 */
9345 attr = node->properties;
9346 while (attr != NULL) {
9347 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009348 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009349 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9350 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9351 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009352 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009353 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009354 }
9355 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009356 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009357 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009358 }
9359 attr = attr->next;
9360 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009361 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +00009362 item = xmlSchemaAddParticle(ctxt, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009363 if (item == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009364 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009365 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009366 * Create a qname-reference and set as the term; it will be substituted
9367 * for the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009368 */
9369 item->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009370 xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009371 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9372 /*
9373 * And now for the children...
9374 */
9375 child = node->children;
9376 /* TODO: Is annotation even allowed for a model group reference? */
9377 if (IS_SCHEMA(child, "annotation")) {
9378 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009379 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009380 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009381 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009382 child = child->next;
9383 }
9384 if (child != NULL) {
9385 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009386 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009387 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009388 "(annotation?)");
9389 }
9390 /*
9391 * Corresponds to no component at all if minOccurs==maxOccurs==0.
9392 */
9393 if ((min == 0) && (max == 0))
9394 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009395
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009396 return ((xmlSchemaTreeItemPtr) item);
9397}
9398
9399/**
9400 * xmlSchemaParseModelGroupDefinition:
9401 * @ctxt: a schema validation context
9402 * @schema: the schema being built
9403 * @node: a subtree containing XML Schema informations
9404 *
9405 * Parses a XML schema model group definition.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009406 *
9407 * Note that the contraint src-redefine (6.2) can't be applied until
9408 * references have been resolved. So we will do this at the
9409 * component fixup level.
9410 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009411 * *WARNING* this interface is highly subject to change
9412 *
9413 * Returns -1 in case of error, 0 if the declaration is improper and
9414 * 1 in case of success.
9415 */
9416static xmlSchemaModelGroupDefPtr
9417xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9418 xmlSchemaPtr schema,
9419 xmlNodePtr node)
9420{
9421 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009422 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009423 xmlAttrPtr attr;
9424 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00009425
9426 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009427 return (NULL);
9428
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009429 attr = xmlSchemaGetPropNode(node, "name");
9430 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009431 xmlSchemaPMissingAttrErr(ctxt,
9432 XML_SCHEMAP_S4S_ATTR_MISSING,
9433 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009434 "name", NULL);
9435 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009436 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009437 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9438 return (NULL);
9439 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009440 item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9441 ctxt->targetNamespace, node);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009442 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009443 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009444 /*
9445 * Check for illegal attributes.
9446 */
9447 attr = node->properties;
9448 while (attr != NULL) {
9449 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009450 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009451 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009452 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009453 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009454 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009455 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009456 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009457 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009458 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009459 attr = attr->next;
9460 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009461 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009462 /*
9463 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009464 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009465 child = node->children;
9466 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009467 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009468 child = child->next;
9469 }
9470 if (IS_SCHEMA(child, "all")) {
9471 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9472 XML_SCHEMA_TYPE_ALL, 0);
9473 child = child->next;
9474 } else if (IS_SCHEMA(child, "choice")) {
9475 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9476 XML_SCHEMA_TYPE_CHOICE, 0);
9477 child = child->next;
9478 } else if (IS_SCHEMA(child, "sequence")) {
9479 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9480 XML_SCHEMA_TYPE_SEQUENCE, 0);
9481 child = child->next;
9482 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009483
9484
9485
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009486 if (child != NULL) {
9487 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009488 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009489 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009490 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009491 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009492 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009493}
9494
9495/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009496 * xmlSchemaCleanupDoc:
9497 * @ctxt: a schema validation context
9498 * @node: the root of the document.
9499 *
9500 * removes unwanted nodes in a schemas document tree
9501 */
9502static void
9503xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9504{
9505 xmlNodePtr delete, cur;
9506
9507 if ((ctxt == NULL) || (root == NULL)) return;
9508
9509 /*
9510 * Remove all the blank text nodes
9511 */
9512 delete = NULL;
9513 cur = root;
9514 while (cur != NULL) {
9515 if (delete != NULL) {
9516 xmlUnlinkNode(delete);
9517 xmlFreeNode(delete);
9518 delete = NULL;
9519 }
9520 if (cur->type == XML_TEXT_NODE) {
9521 if (IS_BLANK_NODE(cur)) {
9522 if (xmlNodeGetSpacePreserve(cur) != 1) {
9523 delete = cur;
9524 }
9525 }
9526 } else if ((cur->type != XML_ELEMENT_NODE) &&
9527 (cur->type != XML_CDATA_SECTION_NODE)) {
9528 delete = cur;
9529 goto skip_children;
9530 }
9531
9532 /*
9533 * Skip to next node
9534 */
9535 if (cur->children != NULL) {
9536 if ((cur->children->type != XML_ENTITY_DECL) &&
9537 (cur->children->type != XML_ENTITY_REF_NODE) &&
9538 (cur->children->type != XML_ENTITY_NODE)) {
9539 cur = cur->children;
9540 continue;
9541 }
9542 }
9543 skip_children:
9544 if (cur->next != NULL) {
9545 cur = cur->next;
9546 continue;
9547 }
9548
9549 do {
9550 cur = cur->parent;
9551 if (cur == NULL)
9552 break;
9553 if (cur == root) {
9554 cur = NULL;
9555 break;
9556 }
9557 if (cur->next != NULL) {
9558 cur = cur->next;
9559 break;
9560 }
9561 } while (cur != NULL);
9562 }
9563 if (delete != NULL) {
9564 xmlUnlinkNode(delete);
9565 xmlFreeNode(delete);
9566 delete = NULL;
9567 }
9568}
9569
William M. Brack2f2a6632004-08-20 23:09:47 +00009570
William M. Brack2f2a6632004-08-20 23:09:47 +00009571static void
9572xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9573{
9574 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9575 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9576
9577 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9578 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9579
9580 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9581 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9582 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9583 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9584 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9585 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9586 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9587 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9588
9589 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9590 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9591 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9592 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9593 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9594 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9595}
9596
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009597static int
9598xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009599 xmlSchemaPtr schema,
9600 xmlNodePtr node)
9601{
9602 xmlAttrPtr attr;
9603 const xmlChar *val;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009604 int res = 0, oldErrs = ctxt->nberrors;
William M. Brack2f2a6632004-08-20 23:09:47 +00009605
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009606 /*
9607 * Those flags should be moved to the parser context flags,
9608 * since they are not visible at the component level. I.e.
9609 * they are used if processing schema *documents* only.
9610 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009611 res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009612 HFAILURE;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009613
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009614 /*
9615 * Since the version is of type xs:token, we won't bother to
9616 * check it.
9617 */
9618 /* REMOVED:
9619 attr = xmlSchemaGetPropNode(node, "version");
9620 if (attr != NULL) {
9621 res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9622 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9623 HFAILURE;
9624 }
9625 */
9626 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9627 if (attr != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009628 res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009629 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9630 HFAILURE;
9631 if (res != 0) {
9632 ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9633 goto exit;
9634 }
9635 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009636 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009637 if (attr != NULL) {
9638 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009639 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9640 XML_SCHEMAS_QUALIF_ELEM);
9641 HFAILURE;
9642 if (res != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009643 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009644 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009645 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009646 "(qualified | unqualified)", val, NULL, NULL, NULL);
9647 }
9648 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009649 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009650 if (attr != NULL) {
9651 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009652 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9653 XML_SCHEMAS_QUALIF_ATTR);
9654 HFAILURE;
9655 if (res != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009656 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009657 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009658 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009659 "(qualified | unqualified)", val, NULL, NULL, NULL);
9660 }
9661 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009662 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009663 if (attr != NULL) {
9664 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009665 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
William M. Brack2f2a6632004-08-20 23:09:47 +00009666 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9667 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9668 -1,
9669 XML_SCHEMAS_FINAL_DEFAULT_LIST,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009670 XML_SCHEMAS_FINAL_DEFAULT_UNION);
9671 HFAILURE;
9672 if (res != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009673 xmlSchemaPSimpleTypeErr(ctxt,
9674 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009675 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009676 "(#all | List of (extension | restriction | list | union))",
9677 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009678 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009679 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009680 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009681 if (attr != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009682 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9683 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
William M. Brack2f2a6632004-08-20 23:09:47 +00009684 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9685 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009686 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9687 HFAILURE;
9688 if (res != 0) {
9689 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009690 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009691 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009692 "(#all | List of (extension | restriction | substitution))",
9693 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009694 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009695 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009696
9697exit:
9698 if (oldErrs != ctxt->nberrors)
9699 res = ctxt->err;
9700 return(res);
9701exit_failure:
9702 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009703}
9704
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009705/**
9706 * xmlSchemaParseSchemaTopLevel:
9707 * @ctxt: a schema validation context
9708 * @schema: the schemas
9709 * @nodes: the list of top level nodes
9710 *
9711 * Returns the internal XML Schema structure built from the resource or
9712 * NULL in case of error
9713 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009714static int
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009715xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9716 xmlSchemaPtr schema, xmlNodePtr nodes)
9717{
9718 xmlNodePtr child;
9719 xmlSchemaAnnotPtr annot;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009720 int res = 0, oldErrs, tmpOldErrs;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009721
9722 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009723 return(-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009724
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009725 oldErrs = ctxt->nberrors;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009726 child = nodes;
9727 while ((IS_SCHEMA(child, "include")) ||
9728 (IS_SCHEMA(child, "import")) ||
9729 (IS_SCHEMA(child, "redefine")) ||
9730 (IS_SCHEMA(child, "annotation"))) {
9731 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009732 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009733 if (schema->annot == NULL)
9734 schema->annot = annot;
9735 else
9736 xmlSchemaFreeAnnot(annot);
9737 } else if (IS_SCHEMA(child, "import")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009738 tmpOldErrs = ctxt->nberrors;
9739 res = xmlSchemaParseImport(ctxt, schema, child);
9740 HFAILURE;
9741 HSTOP(ctxt);
9742 if (tmpOldErrs != ctxt->nberrors)
9743 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009744 } else if (IS_SCHEMA(child, "include")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009745 tmpOldErrs = ctxt->nberrors;
9746 res = xmlSchemaParseInclude(ctxt, schema, child);
9747 HFAILURE;
9748 HSTOP(ctxt);
9749 if (tmpOldErrs != ctxt->nberrors)
9750 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009751 } else if (IS_SCHEMA(child, "redefine")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009752 tmpOldErrs = ctxt->nberrors;
9753 res = xmlSchemaParseRedefine(ctxt, schema, child);
9754 HFAILURE;
9755 HSTOP(ctxt);
9756 if (tmpOldErrs != ctxt->nberrors)
9757 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009758 }
9759 child = child->next;
9760 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009761 /*
9762 * URGENT TODO: Change the functions to return int results.
9763 * We need especially to catch internal errors.
9764 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009765 while (child != NULL) {
9766 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009767 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009768 child = child->next;
9769 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009770 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009771 child = child->next;
9772 } else if (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009773 xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009774 child = child->next;
9775 } else if (IS_SCHEMA(child, "attribute")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009776 xmlSchemaParseGlobalAttribute(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009777 child = child->next;
9778 } else if (IS_SCHEMA(child, "attributeGroup")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009779 xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009780 child = child->next;
9781 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009782 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009783 child = child->next;
9784 } else if (IS_SCHEMA(child, "notation")) {
9785 xmlSchemaParseNotation(ctxt, schema, child);
9786 child = child->next;
9787 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009788 xmlSchemaPContentErr(ctxt,
9789 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009790 NULL, child->parent, child,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009791 NULL, "((include | import | redefine | annotation)*, "
9792 "(((simpleType | complexType | group | attributeGroup) "
9793 "| element | attribute | notation), annotation*)*)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009794 child = child->next;
9795 }
9796 while (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009797 /*
9798 * TODO: We should add all annotations.
9799 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009800 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009801 if (schema->annot == NULL)
9802 schema->annot = annot;
9803 else
9804 xmlSchemaFreeAnnot(annot);
9805 child = child->next;
9806 }
9807 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009808exit:
Daniel Veillard01fa6152004-06-29 17:04:39 +00009809 ctxt->ctxtType = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009810 if (oldErrs != ctxt->nberrors)
9811 res = ctxt->err;
9812 return(res);
9813exit_failure:
9814 return(-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009815}
9816
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009817static xmlSchemaSchemaRelationPtr
9818xmlSchemaSchemaRelationCreate(void)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009819{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009820 xmlSchemaSchemaRelationPtr ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009821
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009822 ret = (xmlSchemaSchemaRelationPtr)
9823 xmlMalloc(sizeof(xmlSchemaSchemaRelation));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009824 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009825 xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009826 return(NULL);
9827 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009828 memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009829 return(ret);
9830}
9831
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009832#if 0
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009833static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009834xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009835{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009836 xmlFree(rel);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009837}
9838#endif
9839
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009840static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009841xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9842{
9843 xmlSchemaRedefPtr prev;
9844
9845 while (redef != NULL) {
9846 prev = redef;
9847 redef = redef->next;
9848 xmlFree(prev);
9849 }
9850}
9851
9852static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009853xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9854{
9855 /*
9856 * After the construction context has been freed, there will be
9857 * no schema graph available any more. Only the schema buckets
9858 * will stay alive, which are put into the "schemasImports" and
9859 * "includes" slots of the xmlSchema.
9860 */
9861 if (con->buckets != NULL)
9862 xmlSchemaItemListFree(con->buckets);
9863 if (con->pending != NULL)
9864 xmlSchemaItemListFree(con->pending);
9865 if (con->substGroups != NULL)
9866 xmlHashFree(con->substGroups,
9867 (xmlHashDeallocator) xmlSchemaSubstGroupFree);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009868 if (con->redefs != NULL)
9869 xmlSchemaRedefListFree(con->redefs);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009870 if (con->dict != NULL)
9871 xmlDictFree(con->dict);
9872 xmlFree(con);
9873}
9874
9875static xmlSchemaConstructionCtxtPtr
9876xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9877{
9878 xmlSchemaConstructionCtxtPtr ret;
9879
9880 ret = (xmlSchemaConstructionCtxtPtr)
9881 xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9882 if (ret == NULL) {
9883 xmlSchemaPErrMemory(NULL,
9884 "allocating schema construction context", NULL);
9885 return (NULL);
9886 }
9887 memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9888
9889 ret->buckets = xmlSchemaItemListCreate();
9890 if (ret->buckets == NULL) {
9891 xmlSchemaPErrMemory(NULL,
9892 "allocating list of schema buckets", NULL);
9893 xmlFree(ret);
9894 return (NULL);
9895 }
9896 ret->pending = xmlSchemaItemListCreate();
9897 if (ret->pending == NULL) {
9898 xmlSchemaPErrMemory(NULL,
9899 "allocating list of pending global components", NULL);
9900 xmlSchemaConstructionCtxtFree(ret);
9901 return (NULL);
9902 }
9903 ret->dict = dict;
9904 xmlDictReference(dict);
9905 return(ret);
9906}
9907
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009908static xmlSchemaParserCtxtPtr
9909xmlSchemaParserCtxtCreate(void)
9910{
9911 xmlSchemaParserCtxtPtr ret;
9912
9913 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9914 if (ret == NULL) {
9915 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9916 NULL);
9917 return (NULL);
9918 }
9919 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9920 ret->type = XML_SCHEMA_CTXT_PARSER;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009921 ret->attrProhibs = xmlSchemaItemListCreate();
9922 if (ret->attrProhibs == NULL) {
9923 xmlFree(ret);
9924 return(NULL);
9925 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009926 return(ret);
9927}
9928
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009929/**
9930 * xmlSchemaNewParserCtxtUseDict:
9931 * @URL: the location of the schema
9932 * @dict: the dictionary to be used
9933 *
9934 * Create an XML Schemas parse context for that file/resource expected
9935 * to contain an XML Schemas file.
9936 *
9937 * Returns the parser context or NULL in case of error
9938 */
9939static xmlSchemaParserCtxtPtr
9940xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9941{
9942 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009943
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009944 ret = xmlSchemaParserCtxtCreate();
9945 if (ret == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009946 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009947 ret->dict = dict;
9948 xmlDictReference(dict);
9949 if (URL != NULL)
9950 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009951 return (ret);
9952}
9953
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009954static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009955xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
9956{
9957 if (vctxt->pctxt == NULL) {
9958 if (vctxt->schema != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009959 vctxt->pctxt =
9960 xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009961 else
9962 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
9963 if (vctxt->pctxt == NULL) {
9964 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
9965 "failed to create a temp. parser context");
9966 return (-1);
9967 }
9968 /* TODO: Pass user data. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009969 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00009970 vctxt->warning, vctxt->errCtxt);
9971 xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
9972 vctxt->errCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009973 }
9974 return (0);
9975}
9976
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009977/**
9978 * xmlSchemaGetSchemaBucket:
9979 * @pctxt: the schema parser context
9980 * @schemaLocation: the URI of the schema document
9981 *
9982 * Returns a schema bucket if it was already parsed.
9983 *
9984 * Returns a schema bucket if it was already parsed from
9985 * @schemaLocation, NULL otherwise.
9986 */
9987static xmlSchemaBucketPtr
9988xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
9989 const xmlChar *schemaLocation)
9990{
9991 xmlSchemaBucketPtr cur;
9992 xmlSchemaItemListPtr list;
9993
9994 list = pctxt->constructor->buckets;
9995 if (list->nbItems == 0)
9996 return(NULL);
9997 else {
9998 int i;
9999 for (i = 0; i < list->nbItems; i++) {
10000 cur = (xmlSchemaBucketPtr) list->items[i];
10001 /* Pointer comparison! */
10002 if (cur->schemaLocation == schemaLocation)
10003 return(cur);
10004 }
10005 }
10006 return(NULL);
10007}
10008
10009static xmlSchemaBucketPtr
10010xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10011 const xmlChar *schemaLocation,
10012 const xmlChar *targetNamespace)
10013{
10014 xmlSchemaBucketPtr cur;
10015 xmlSchemaItemListPtr list;
10016
10017 list = pctxt->constructor->buckets;
10018 if (list->nbItems == 0)
10019 return(NULL);
10020 else {
10021 int i;
10022 for (i = 0; i < list->nbItems; i++) {
10023 cur = (xmlSchemaBucketPtr) list->items[i];
10024 /* Pointer comparison! */
10025 if ((cur->origTargetNamespace == NULL) &&
10026 (cur->schemaLocation == schemaLocation) &&
10027 (cur->targetNamespace == targetNamespace))
10028 return(cur);
10029 }
10030 }
10031 return(NULL);
10032}
10033
10034
10035#define IS_BAD_SCHEMA_DOC(b) \
10036 (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10037
10038static xmlSchemaBucketPtr
10039xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10040 const xmlChar *targetNamespace,
10041 int imported)
10042{
10043 xmlSchemaBucketPtr cur;
10044 xmlSchemaItemListPtr list;
10045
10046 list = pctxt->constructor->buckets;
10047 if (list->nbItems == 0)
10048 return(NULL);
10049 else {
10050 int i;
10051 for (i = 0; i < list->nbItems; i++) {
10052 cur = (xmlSchemaBucketPtr) list->items[i];
10053 if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10054 (cur->origTargetNamespace == targetNamespace) &&
10055 ((imported && cur->imported) ||
10056 ((!imported) && (!cur->imported))))
10057 return(cur);
10058 }
10059 }
10060 return(NULL);
10061}
10062
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010063static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010064xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10065 xmlSchemaPtr schema,
10066 xmlSchemaBucketPtr bucket)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010067{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010068 int oldFlags;
10069 xmlDocPtr oldDoc;
10070 xmlNodePtr node;
10071 int ret, oldErrs;
10072 xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10073
10074 /*
10075 * Save old values; reset the *main* schema.
10076 * URGENT TODO: This is not good; move the per-document information
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000010077 * to the parser. Get rid of passing the main schema to the
10078 * parsing functions.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010079 */
10080 oldFlags = schema->flags;
10081 oldDoc = schema->doc;
10082 if (schema->flags != 0)
10083 xmlSchemaClearSchemaDefaults(schema);
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000010084 schema->doc = bucket->doc;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010085 pctxt->schema = schema;
10086 /*
10087 * Keep the current target namespace on the parser *not* on the
10088 * main schema.
10089 */
10090 pctxt->targetNamespace = bucket->targetNamespace;
10091 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010092
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010093 if ((bucket->targetNamespace != NULL) &&
10094 xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010095 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010096 * We are parsing the schema for schemas!
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010097 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010098 pctxt->isS4S = 1;
10099 }
10100 /* Mark it as parsed, even if parsing fails. */
10101 bucket->parsed++;
10102 /* Compile the schema doc. */
10103 node = xmlDocGetRootElement(bucket->doc);
10104 ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10105 if (ret != 0)
10106 goto exit;
10107 /* An empty schema; just get out. */
10108 if (node->children == NULL)
10109 goto exit;
10110 oldErrs = pctxt->nberrors;
10111 ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10112 if (ret != 0)
10113 goto exit;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010114 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010115 * TODO: Not nice, but I'm not 100% sure we will get always an error
10116 * as a result of the obove functions; so better rely on pctxt->err
10117 * as well.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010118 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010119 if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10120 ret = pctxt->err;
10121 goto exit;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010122 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010123
10124exit:
10125 WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10126 /* Restore schema values. */
10127 schema->doc = oldDoc;
10128 schema->flags = oldFlags;
10129 return(ret);
10130}
10131
10132static int
10133xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10134 xmlSchemaPtr schema,
10135 xmlSchemaBucketPtr bucket)
10136{
10137 xmlSchemaParserCtxtPtr newpctxt;
10138 int res = 0;
10139
10140 if (bucket == NULL)
10141 return(0);
10142 if (bucket->parsed) {
10143 PERROR_INT("xmlSchemaParseNewDoc",
10144 "reparsing a schema doc");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010145 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010146 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010147 if (bucket->doc == NULL) {
10148 PERROR_INT("xmlSchemaParseNewDoc",
10149 "parsing a schema doc, but there's no doc");
10150 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000010151 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010152 if (pctxt->constructor == NULL) {
10153 PERROR_INT("xmlSchemaParseNewDoc",
10154 "no constructor");
10155 return(-1);
10156 }
10157 /* Create and init the temporary parser context. */
10158 newpctxt = xmlSchemaNewParserCtxtUseDict(
10159 (const char *) bucket->schemaLocation, pctxt->dict);
10160 if (newpctxt == NULL)
10161 return(-1);
10162 newpctxt->constructor = pctxt->constructor;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010163 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010164 * TODO: Can we avoid that the parser knows about the main schema?
10165 * It would be better if he knows about the current schema bucket
10166 * only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010167 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010168 newpctxt->schema = schema;
10169 xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000010170 pctxt->errCtxt);
10171 xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10172 pctxt->errCtxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010173 newpctxt->counter = pctxt->counter;
10174
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010175
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010176 res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10177
10178 /* Channel back errors and cleanup the temporary parser context. */
10179 if (res != 0)
10180 pctxt->err = res;
10181 pctxt->nberrors += newpctxt->nberrors;
10182 pctxt->counter = newpctxt->counter;
10183 newpctxt->constructor = NULL;
10184 /* Free the parser context. */
10185 xmlSchemaFreeParserCtxt(newpctxt);
10186 return(res);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010187}
William M. Brack2f2a6632004-08-20 23:09:47 +000010188
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010189static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010190xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10191 xmlSchemaSchemaRelationPtr rel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010192{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010193 xmlSchemaSchemaRelationPtr cur = bucket->relations;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010194
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010195 if (cur == NULL) {
10196 bucket->relations = rel;
10197 return;
10198 }
10199 while (cur->next != NULL)
10200 cur = cur->next;
10201 cur->next = rel;
10202}
10203
10204
10205static const xmlChar *
10206xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10207 xmlNodePtr ctxtNode)
10208{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010209 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010210 * Build an absolue location URI.
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010211 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010212 if (location != NULL) {
10213 if (ctxtNode == NULL)
10214 return(location);
10215 else {
10216 xmlChar *base, *URI;
10217 const xmlChar *ret = NULL;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010218
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010219 base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10220 if (base == NULL) {
10221 URI = xmlBuildURI(location, ctxtNode->doc->URL);
10222 } else {
10223 URI = xmlBuildURI(location, base);
10224 xmlFree(base);
10225 }
10226 if (URI != NULL) {
10227 ret = xmlDictLookup(dict, URI, -1);
10228 xmlFree(URI);
10229 return(ret);
10230 }
10231 }
10232 }
10233 return(NULL);
10234}
10235
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010236
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010237
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010238/**
10239 * xmlSchemaAddSchemaDoc:
10240 * @pctxt: a schema validation context
10241 * @schema: the schema being built
10242 * @node: a subtree containing XML Schema informations
10243 *
10244 * Parse an included (and to-be-redefined) XML schema document.
10245 *
10246 * Returns 0 on success, a positive error code on errors and
10247 * -1 in case of an internal or API error.
10248 */
10249
10250static int
10251xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10252 int type, /* import or include or redefine */
10253 const xmlChar *schemaLocation,
10254 xmlDocPtr schemaDoc,
10255 const char *schemaBuffer,
10256 int schemaBufferLen,
10257 xmlNodePtr invokingNode,
10258 const xmlChar *sourceTargetNamespace,
10259 const xmlChar *importNamespace,
10260 xmlSchemaBucketPtr *bucket)
10261{
10262 const xmlChar *targetNamespace = NULL;
10263 xmlSchemaSchemaRelationPtr relation = NULL;
10264 xmlDocPtr doc = NULL;
10265 int res = 0, err = 0, located = 0, preserveDoc = 0;
10266 xmlSchemaBucketPtr bkt = NULL;
10267
10268 if (bucket != NULL)
10269 *bucket = NULL;
10270
10271 switch (type) {
10272 case XML_SCHEMA_SCHEMA_IMPORT:
10273 case XML_SCHEMA_SCHEMA_MAIN:
10274 err = XML_SCHEMAP_SRC_IMPORT;
10275 break;
10276 case XML_SCHEMA_SCHEMA_INCLUDE:
10277 err = XML_SCHEMAP_SRC_INCLUDE;
10278 break;
10279 case XML_SCHEMA_SCHEMA_REDEFINE:
10280 err = XML_SCHEMAP_SRC_REDEFINE;
10281 break;
10282 }
10283
10284
10285 /* Special handling for the main schema:
10286 * skip the location and relation logic and just parse the doc.
10287 * We need just a bucket to be returned in this case.
10288 */
10289 if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10290 goto doc_load;
10291
10292 /* Note that we expect the location to be an absulute URI. */
10293 if (schemaLocation != NULL) {
10294 bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10295 if ((bkt != NULL) &&
10296 (pctxt->constructor->bucket == bkt)) {
10297 /* Report self-imports/inclusions/redefinitions. */
10298
10299 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10300 invokingNode, NULL,
10301 "The schema must not import/include/redefine itself",
10302 NULL, NULL);
10303 goto exit;
10304 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010305 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010306 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010307 * Create a relation for the graph of schemas.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010308 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010309 relation = xmlSchemaSchemaRelationCreate();
10310 if (relation == NULL)
10311 return(-1);
10312 xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10313 relation);
10314 relation->type = type;
10315
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010316 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010317 * Save the namespace import information.
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010318 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010319 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010320 relation->importNamespace = importNamespace;
10321 if (schemaLocation == NULL) {
10322 /*
10323 * No location; this is just an import of the namespace.
10324 * Note that we don't assign a bucket to the relation
10325 * in this case.
10326 */
10327 goto exit;
10328 }
10329 targetNamespace = importNamespace;
10330 }
10331
10332 /* Did we already fetch the doc? */
10333 if (bkt != NULL) {
10334 /* TODO: The following nasty cases will produce an error. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010335 if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010336 /* We included/redefined and then try to import a schema. */
10337 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10338 invokingNode, NULL,
10339 "The schema document '%s' cannot be imported, since "
10340 "it was already included or redefined",
10341 schemaLocation, NULL);
10342 goto exit;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010343 } else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010344 /* We imported and then try to include/redefine a schema. */
10345 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10346 invokingNode, NULL,
10347 "The schema document '%s' cannot be included or "
10348 "redefined, since it was already imported",
10349 schemaLocation, NULL);
10350 goto exit;
10351 }
10352 }
10353
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010354 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010355 /*
10356 * Given that the schemaLocation [attribute] is only a hint, it is open
10357 * to applications to ignore all but the first <import> for a given
10358 * namespace, regardless of the ·actual value· of schemaLocation, but
10359 * such a strategy risks missing useful information when new
10360 * schemaLocations are offered.
10361 *
10362 * We will use the first <import> that comes with a location.
10363 * Further <import>s *with* a location, will result in an error.
10364 * TODO: Better would be to just report a warning here, but
10365 * we'll try it this way until someone complains.
10366 *
10367 * Schema Document Location Strategy:
10368 * 3 Based on the namespace name, identify an existing schema document,
10369 * either as a resource which is an XML document or a <schema> element
10370 * information item, in some local schema repository;
10371 * 5 Attempt to resolve the namespace name to locate such a resource.
10372 *
10373 * NOTE: (3) and (5) are not supported.
10374 */
10375 if (bkt != NULL) {
10376 relation->bucket = bkt;
10377 goto exit;
10378 }
10379 bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10380 importNamespace, 1);
10381
10382 if (bkt != NULL) {
10383 relation->bucket = bkt;
10384 if (bkt->schemaLocation == NULL) {
10385 /* First given location of the schema; load the doc. */
10386 bkt->schemaLocation = schemaLocation;
10387 } else {
10388 if (!xmlStrEqual(schemaLocation,
10389 bkt->schemaLocation)) {
10390 /*
10391 * Additional location given; just skip it.
10392 * URGENT TODO: We should report a warning here.
10393 * res = XML_SCHEMAP_SRC_IMPORT;
10394 */
10395 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10396 XML_SCHEMAP_WARN_SKIP_SCHEMA,
10397 invokingNode, NULL,
10398 "Skipping import of schema located at '%s' for the "
10399 "namespace '%s', since this namespace was already "
10400 "imported with the schema located at '%s'",
10401 schemaLocation, importNamespace, bkt->schemaLocation);
10402 }
10403 goto exit;
10404 }
10405 }
10406 /*
10407 * No bucket + first location: load the doc and create a
10408 * bucket.
10409 */
10410 } else {
10411 /* <include> and <redefine> */
10412 if (bkt != NULL) {
10413
10414 if ((bkt->origTargetNamespace == NULL) &&
10415 (bkt->targetNamespace != sourceTargetNamespace)) {
10416 xmlSchemaBucketPtr chamel;
10417
10418 /*
10419 * Chameleon include/redefine: skip loading only if it was
10420 * aleady build for the targetNamespace of the including
10421 * schema.
10422 */
10423 /*
10424 * URGENT TODO: If the schema is a chameleon-include then copy
10425 * the components into the including schema and modify the
10426 * targetNamespace of those components, do nothing otherwise.
10427 * NOTE: This is currently worked-around by compiling the
10428 * chameleon for every destinct including targetNamespace; thus
10429 * not performant at the moment.
10430 * TODO: Check when the namespace in wildcards for chameleons
10431 * needs to be converted: before we built wildcard intersections
10432 * or after.
10433 * Answer: after!
10434 */
10435 chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10436 schemaLocation, sourceTargetNamespace);
10437 if (chamel != NULL) {
10438 /* A fitting chameleon was already parsed; NOP. */
10439 relation->bucket = chamel;
10440 goto exit;
10441 }
10442 /*
10443 * We need to parse the chameleon again for a different
10444 * targetNamespace.
10445 * CHAMELEON TODO: Optimize this by only parsing the
10446 * chameleon once, and then copying the components to
10447 * the new targetNamespace.
10448 */
10449 bkt = NULL;
10450 } else {
10451 relation->bucket = bkt;
10452 goto exit;
10453 }
10454 }
10455 }
10456 if ((bkt != NULL) && (bkt->doc != NULL)) {
10457 PERROR_INT("xmlSchemaAddSchemaDoc",
10458 "trying to load a schema doc, but a doc is already "
10459 "assigned to the schema bucket");
10460 goto exit_failure;
10461 }
10462
10463doc_load:
10464 /*
10465 * Load the document.
10466 */
10467 if (schemaDoc != NULL) {
10468 doc = schemaDoc;
10469 /* Don' free this one, since it was provided by the caller. */
10470 preserveDoc = 1;
10471 /* TODO: Does the context or the doc hold the location? */
10472 if (schemaDoc->URL != NULL)
10473 schemaLocation = xmlDictLookup(pctxt->dict,
10474 schemaDoc->URL, -1);
10475
10476 } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10477 xmlParserCtxtPtr parserCtxt;
10478
10479 parserCtxt = xmlNewParserCtxt();
10480 if (parserCtxt == NULL) {
10481 xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10482 "allocating a parser context", NULL);
10483 goto exit_failure;
10484 }
10485 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10486 /*
10487 * TODO: Do we have to burden the schema parser dict with all
10488 * the content of the schema doc?
10489 */
10490 xmlDictFree(parserCtxt->dict);
10491 parserCtxt->dict = pctxt->dict;
10492 xmlDictReference(parserCtxt->dict);
10493 }
10494 if (schemaLocation != NULL) {
10495 /* Parse from file. */
10496 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10497 NULL, SCHEMAS_PARSE_OPTIONS);
10498 } else if (schemaBuffer != NULL) {
10499 /* Parse from memory buffer. */
10500 doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10501 NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10502 schemaLocation = xmlStrdup(BAD_CAST "in_memory_buffer");
10503 if (doc != NULL)
10504 doc->URL = schemaLocation;
10505 }
10506 /*
10507 * For <import>:
10508 * 2.1 The referent is (a fragment of) a resource which is an
10509 * XML document (see clause 1.1), which in turn corresponds to
10510 * a <schema> element information item in a well-formed information
10511 * set, which in turn corresponds to a valid schema.
10512 * TODO: (2.1) fragments of XML documents are not supported.
10513 *
10514 * 2.2 The referent is a <schema> element information item in
10515 * a well-formed information set, which in turn corresponds
10516 * to a valid schema.
10517 * TODO: (2.2) is not supported.
10518 */
10519 if (doc == NULL) {
10520 xmlErrorPtr lerr;
10521 lerr = xmlGetLastError();
10522 /*
10523 * Check if this a parser error, or if the document could
10524 * just not be located.
10525 * TODO: Try to find specific error codes to react only on
10526 * localisation failures.
10527 */
10528 if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10529 /*
10530 * We assume a parser error here.
10531 */
10532 located = 1;
10533 /* TODO: Error code ?? */
10534 res = XML_SCHEMAP_SRC_IMPORT_2_1;
10535 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10536 invokingNode, NULL,
10537 "Failed to parse the XML resource '%s'",
10538 schemaLocation, NULL);
10539 }
10540 }
10541 xmlFreeParserCtxt(parserCtxt);
10542 if ((doc == NULL) && located)
10543 goto exit_error;
10544 } else {
10545 xmlSchemaPErr(pctxt, NULL,
10546 XML_SCHEMAP_NOTHING_TO_PARSE,
10547 "No information for parsing was provided with the "
10548 "given schema parser context.\n",
10549 NULL, NULL);
10550 goto exit_failure;
10551 }
10552 /*
10553 * Preprocess the document.
10554 */
10555 if (doc != NULL) {
10556 xmlNodePtr docElem = NULL;
10557
10558 located = 1;
10559 docElem = xmlDocGetRootElement(doc);
10560 if (docElem == NULL) {
10561 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10562 invokingNode, NULL,
10563 "The document '%s' has no document element",
10564 schemaLocation, NULL);
10565 xmlFreeDoc(doc);
10566 doc = NULL;
10567 goto exit_error;
10568 }
10569 /*
10570 * Remove all the blank text nodes.
10571 */
10572 xmlSchemaCleanupDoc(pctxt, docElem);
10573 /*
10574 * Check the schema's top level element.
10575 */
10576 if (!IS_SCHEMA(docElem, "schema")) {
10577 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10578 invokingNode, NULL,
10579 "The XML document '%s' is not a schema document",
10580 schemaLocation, NULL);
10581 xmlFreeDoc(doc);
10582 doc = NULL;
10583 goto exit_error;
10584 }
10585 /*
10586 * Note that we don't apply a type check for the
10587 * targetNamespace value here.
10588 */
10589 targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10590 "targetNamespace");
10591 }
10592
10593/* after_doc_loading: */
10594 if ((bkt == NULL) && located) {
10595 /* Only create a bucket if the schema was located. */
10596 bkt = xmlSchemaBucketCreate(pctxt, type,
10597 targetNamespace);
10598 if (bkt == NULL)
10599 goto exit_failure;
10600 }
10601 if (bkt != NULL) {
10602 bkt->schemaLocation = schemaLocation;
10603 bkt->located = located;
10604 if (doc != NULL) {
10605 bkt->doc = doc;
10606 bkt->targetNamespace = targetNamespace;
10607 bkt->origTargetNamespace = targetNamespace;
10608 if (preserveDoc)
10609 bkt->preserveDoc = 1;
10610 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010611 if (WXS_IS_BUCKET_IMPMAIN(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010612 bkt->imported++;
10613 /*
10614 * Add it to the graph of schemas.
10615 */
10616 if (relation != NULL)
10617 relation->bucket = bkt;
10618 }
10619
10620exit:
10621 /*
10622 * Return the bucket explicitely; this is needed for the
10623 * main schema.
10624 */
10625 if (bucket != NULL)
10626 *bucket = bkt;
10627 return (0);
10628
10629exit_error:
10630 if ((doc != NULL) && (! preserveDoc)) {
10631 xmlFreeDoc(doc);
10632 if (bkt != NULL)
10633 bkt->doc = NULL;
10634 }
10635 return(pctxt->err);
10636
10637exit_failure:
10638 if ((doc != NULL) && (! preserveDoc)) {
10639 xmlFreeDoc(doc);
10640 if (bkt != NULL)
10641 bkt->doc = NULL;
10642 }
10643 return (-1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010644}
10645
William M. Brack2f2a6632004-08-20 23:09:47 +000010646/**
10647 * xmlSchemaParseImport:
10648 * @ctxt: a schema validation context
10649 * @schema: the schema being built
10650 * @node: a subtree containing XML Schema informations
10651 *
10652 * parse a XML schema Import definition
10653 * *WARNING* this interface is highly subject to change
10654 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010655 * Returns 0 in case of success, a positive error code if
10656 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +000010657 */
10658static int
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010659xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +000010660 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010661{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010662 xmlNodePtr child;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010663 const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10664 const xmlChar *thisTargetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +000010665 xmlAttrPtr attr;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010666 int ret = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010667 xmlSchemaBucketPtr bucket = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000010668
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010669 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
William M. Brack2f2a6632004-08-20 23:09:47 +000010670 return (-1);
10671
10672 /*
10673 * Check for illegal attributes.
10674 */
10675 attr = node->properties;
10676 while (attr != NULL) {
10677 if (attr->ns == NULL) {
10678 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10679 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10680 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010681 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010682 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010683 }
10684 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010685 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010686 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010687 }
10688 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010689 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010690 /*
10691 * Extract and validate attributes.
10692 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010693 if (xmlSchemaPValAttr(pctxt, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010694 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010695 &namespaceName) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010696 xmlSchemaPSimpleTypeErr(pctxt,
10697 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010698 NULL, node,
10699 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010700 NULL, namespaceName, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010701 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010702 }
10703
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010704 if (xmlSchemaPValAttr(pctxt, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010705 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +000010706 &schemaLocation) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010707 xmlSchemaPSimpleTypeErr(pctxt,
10708 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010709 NULL, node,
10710 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010711 NULL, namespaceName, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010712 return (pctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010713 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010714 /*
10715 * And now for the children...
10716 */
10717 child = node->children;
10718 if (IS_SCHEMA(child, "annotation")) {
10719 /*
10720 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010721 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +000010722 */
10723 child = child->next;
10724 }
10725 if (child != NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010726 xmlSchemaPContentErr(pctxt,
10727 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010728 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010729 "(annotation?)");
10730 }
10731 /*
10732 * Apply additional constraints.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010733 *
10734 * Note that it is important to use the original @targetNamespace
10735 * (or none at all), to rule out imports of schemas _with_ a
10736 * @targetNamespace if the importing schema is a chameleon schema
10737 * (with no @targetNamespace).
William M. Brack2f2a6632004-08-20 23:09:47 +000010738 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010739 thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010740 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000010741 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010742 * 1.1 If the namespace [attribute] is present, then its ·actual value·
10743 * must not match the ·actual value· of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +000010744 * targetNamespace [attribute].
10745 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010746 if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010747 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000010748 XML_SCHEMAP_SRC_IMPORT_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010749 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +000010750 "The value of the attribute 'namespace' must not match "
10751 "the target namespace '%s' of the importing schema",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010752 thisTargetNamespace);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010753 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010754 }
10755 } else {
10756 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010757 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +000010758 * <schema> must have a targetNamespace [attribute].
10759 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010760 if (thisTargetNamespace == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010761 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000010762 XML_SCHEMAP_SRC_IMPORT_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010763 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +000010764 "The attribute 'namespace' must be existent if "
10765 "the importing schema has no target namespace",
10766 NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010767 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010768 }
10769 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010770 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000010771 * Locate and acquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +000010772 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010773 if (schemaLocation != NULL)
10774 schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10775 schemaLocation, node);
10776 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010777 schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010778 namespaceName, &bucket);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010779
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010780 if (ret != 0)
10781 return(ret);
10782
10783 /*
10784 * For <import>: "It is *not* an error for the application
10785 * schema reference strategy to fail."
10786 * So just don't parse if no schema document was found.
10787 * Note that we will get no bucket if the schema could not be
10788 * located or if there was no schemaLocation.
10789 */
10790 if ((bucket == NULL) && (schemaLocation != NULL)) {
10791 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10792 XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10793 node, NULL,
10794 "Failed to locate a schema at location '%s'. "
10795 "Skipping the import", schemaLocation, NULL, NULL);
10796 }
10797
10798 if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10799 ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10800 }
10801
10802 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000010803}
10804
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010805static int
10806xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10807 xmlSchemaPtr schema,
10808 xmlNodePtr node,
10809 xmlChar **schemaLocation,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010810 int type)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010811{
10812 xmlAttrPtr attr;
10813
10814 if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10815 (schemaLocation == NULL))
10816 return (-1);
10817
10818 *schemaLocation = NULL;
10819 /*
10820 * Check for illegal attributes.
10821 * Applies for both <include> and <redefine>.
10822 */
10823 attr = node->properties;
10824 while (attr != NULL) {
10825 if (attr->ns == NULL) {
10826 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10827 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10828 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010829 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010830 }
10831 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10832 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010833 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010834 }
10835 attr = attr->next;
10836 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010837 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010838 /*
10839 * Preliminary step, extract the URI-Reference and make an URI
10840 * from the base.
10841 */
10842 /*
10843 * Attribute "schemaLocation" is mandatory.
10844 */
10845 attr = xmlSchemaGetPropNode(node, "schemaLocation");
10846 if (attr != NULL) {
10847 xmlChar *base = NULL;
10848 xmlChar *uri = NULL;
10849
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010850 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010851 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10852 (const xmlChar **) schemaLocation) != 0)
10853 goto exit_error;
10854 base = xmlNodeGetBase(node->doc, node);
10855 if (base == NULL) {
10856 uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10857 } else {
10858 uri = xmlBuildURI(*schemaLocation, base);
10859 xmlFree(base);
10860 }
10861 if (uri == NULL) {
10862 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10863 "could not build an URI from the schemaLocation")
10864 goto exit_failure;
10865 }
10866 (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10867 xmlFree(uri);
10868 } else {
10869 xmlSchemaPMissingAttrErr(pctxt,
10870 XML_SCHEMAP_S4S_ATTR_MISSING,
10871 NULL, node, "schemaLocation", NULL);
10872 goto exit_error;
10873 }
10874 /*
10875 * Report self-inclusion and self-redefinition.
10876 */
10877 if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010878 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010879 xmlSchemaPCustomErr(pctxt,
10880 XML_SCHEMAP_SRC_REDEFINE,
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 redefine itself.",
10883 *schemaLocation);
10884 } else {
10885 xmlSchemaPCustomErr(pctxt,
10886 XML_SCHEMAP_SRC_INCLUDE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010887 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010888 "The schema document '%s' cannot include itself.",
10889 *schemaLocation);
10890 }
10891 goto exit_error;
10892 }
10893
10894 return(0);
10895exit_error:
10896 return(pctxt->err);
10897exit_failure:
10898 return(-1);
10899}
10900
10901static int
10902xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10903 xmlSchemaPtr schema,
10904 xmlNodePtr node,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010905 int type)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010906{
10907 xmlNodePtr child = NULL;
10908 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000010909 int res = 0; /* hasRedefinitions = 0 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010910 int isChameleon = 0, wasChameleon = 0;
10911 xmlSchemaBucketPtr bucket = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010912
10913 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10914 return (-1);
10915
10916 /*
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010917 * Parse attributes. Note that the returned schemaLocation will
10918 * be already converted to an absolute URI.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010919 */
10920 res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010921 node, (xmlChar **) (&schemaLocation), type);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010922 if (res != 0)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010923 return(res);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010924 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010925 * Load and add the schema document.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010926 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010927 res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10928 NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010929 if (res != 0)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010930 return(res);
10931 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010932 * If we get no schema bucket back, then this means that the schema
10933 * document could not be located or was broken XML or was not
10934 * a schema document.
10935 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010936 if ((bucket == NULL) || (bucket->doc == NULL)) {
10937 if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10938 /*
10939 * WARNING for <include>:
10940 * We will raise an error if the schema cannot be located
10941 * for inclusions, since the that was the feedback from the
10942 * schema people. I.e. the following spec piece will *not* be
10943 * satisfied:
10944 * SPEC src-include: "It is not an error for the ·actual value· of the
10945 * schemaLocation [attribute] to fail to resolve it all, in which
10946 * case no corresponding inclusion is performed.
10947 * So do we need a warning report here?"
10948 */
10949 res = XML_SCHEMAP_SRC_INCLUDE;
10950 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10951 node, NULL,
10952 "Failed to load the document '%s' for inclusion",
10953 schemaLocation, NULL);
10954 } else {
10955 /*
10956 * NOTE: This was changed to raise an error even if no redefinitions
10957 * are specified.
10958 *
10959 * SPEC src-redefine (1)
10960 * "If there are any element information items among the [children]
10961 * other than <annotation> then the ·actual value· of the
10962 * schemaLocation [attribute] must successfully resolve."
10963 * TODO: Ask the WG if a the location has always to resolve
10964 * here as well!
10965 */
10966 res = XML_SCHEMAP_SRC_REDEFINE;
10967 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10968 node, NULL,
10969 "Failed to load the document '%s' for redefinition",
10970 schemaLocation, NULL);
10971 }
10972 } else {
10973 /*
10974 * Check targetNamespace sanity before parsing the new schema.
10975 * TODO: Note that we won't check further content if the
10976 * targetNamespace was bad.
10977 */
10978 if (bucket->origTargetNamespace != NULL) {
10979 /*
10980 * SPEC src-include (2.1)
10981 * "SII has a targetNamespace [attribute], and its ·actual
10982 * value· is identical to the ·actual value· of the targetNamespace
10983 * [attribute] of SIIÂ’ (which must have such an [attribute])."
10984 */
10985 if (pctxt->targetNamespace == NULL) {
10986 xmlSchemaCustomErr(ACTXT_CAST pctxt,
10987 XML_SCHEMAP_SRC_INCLUDE,
10988 node, NULL,
10989 "The target namespace of the included/redefined schema "
10990 "'%s' has to be absent, since the including/redefining "
10991 "schema has no target namespace",
10992 schemaLocation, NULL);
10993 goto exit_error;
10994 } else if (!xmlStrEqual(bucket->origTargetNamespace,
10995 pctxt->targetNamespace)) {
10996 /* TODO: Change error function. */
10997 xmlSchemaPCustomErrExt(pctxt,
10998 XML_SCHEMAP_SRC_INCLUDE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010999 NULL, node,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011000 "The target namespace '%s' of the included/redefined "
11001 "schema '%s' differs from '%s' of the "
11002 "including/redefining schema",
11003 bucket->origTargetNamespace, schemaLocation,
11004 pctxt->targetNamespace);
11005 goto exit_error;
11006 }
11007 } else if (pctxt->targetNamespace != NULL) {
11008 /*
11009 * Chameleons: the original target namespace will
11010 * differ from the resulting namespace.
11011 */
11012 isChameleon = 1;
11013 if (bucket->parsed &&
11014 (bucket->targetNamespace != pctxt->targetNamespace)) {
11015 /*
11016 * This is a sanity check, I dunno yet if this can happen.
11017 */
11018 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
11019 "trying to use an already parsed schema for a "
11020 "different targetNamespace");
11021 return(-1);
11022 }
11023 bucket->targetNamespace = pctxt->targetNamespace;
11024 }
11025 }
11026 /*
11027 * Parse the schema.
11028 */
11029 if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11030 if (isChameleon) {
11031 /* TODO: Get rid of this flag on the schema itself. */
11032 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11033 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11034 } else
11035 wasChameleon = 1;
11036 }
11037 xmlSchemaParseNewDoc(pctxt, schema, bucket);
11038 /* Restore chameleon flag. */
11039 if (isChameleon && (!wasChameleon))
11040 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11041 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011042 /*
11043 * And now for the children...
11044 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011045 child = node->children;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011046 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011047 /*
11048 * Parse (simpleType | complexType | group | attributeGroup))*
11049 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011050 pctxt->redefined = bucket;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011051 /*
11052 * How to proceed if the redefined schema was not located?
11053 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011054 pctxt->isRedefine = 1;
11055 while (IS_SCHEMA(child, "annotation") ||
11056 IS_SCHEMA(child, "simpleType") ||
11057 IS_SCHEMA(child, "complexType") ||
11058 IS_SCHEMA(child, "group") ||
11059 IS_SCHEMA(child, "attributeGroup")) {
11060 if (IS_SCHEMA(child, "annotation")) {
11061 /*
11062 * TODO: discard or not?
11063 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011064 } else if (IS_SCHEMA(child, "simpleType")) {
11065 xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11066 } else if (IS_SCHEMA(child, "complexType")) {
11067 xmlSchemaParseComplexType(pctxt, schema, child, 1);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011068 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011069 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011070 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011071 xmlSchemaParseModelGroupDefinition(pctxt,
11072 schema, child);
11073 } else if (IS_SCHEMA(child, "attributeGroup")) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011074 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011075 xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11076 child);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011077 }
11078 child = child->next;
11079 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011080 pctxt->redefined = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011081 pctxt->isRedefine = 0;
11082 } else {
11083 if (IS_SCHEMA(child, "annotation")) {
11084 /*
11085 * TODO: discard or not?
11086 */
11087 child = child->next;
11088 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011089 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011090 if (child != NULL) {
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011091 res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011092 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11093 xmlSchemaPContentErr(pctxt, res,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011094 NULL, node, child, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011095 "(annotation | (simpleType | complexType | group | attributeGroup))*");
11096 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011097 xmlSchemaPContentErr(pctxt, res,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011098 NULL, node, child, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011099 "(annotation?)");
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011100 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011101 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011102 return(res);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011103
11104exit_error:
11105 return(pctxt->err);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011106}
11107
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011108static int
11109xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11110 xmlNodePtr node)
11111{
11112 int res;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011113#ifndef ENABLE_REDEFINE
11114 TODO
11115 return(0);
11116#endif
11117 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11118 XML_SCHEMA_SCHEMA_REDEFINE);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011119 if (res != 0)
11120 return(res);
11121 return(0);
11122}
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011123
11124static int
11125xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11126 xmlNodePtr node)
11127{
11128 int res;
11129
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011130 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11131 XML_SCHEMA_SCHEMA_INCLUDE);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011132 if (res != 0)
11133 return(res);
11134 return(0);
11135}
11136
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011137/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011138 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011139 * @ctxt: a schema validation context
11140 * @schema: the schema being built
11141 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011142 * @type: the "compositor" type
11143 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +000011144 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011145 * parse a XML schema Sequence definition.
11146 * Applies parts of:
11147 * Schema Representation Constraint:
11148 * Redefinition Constraints and Semantics (src-redefine)
11149 * (6.1), (6.1.1), (6.1.2)
11150 *
11151 * Schema Component Constraint:
11152 * All Group Limited (cos-all-limited) (2)
11153 * TODO: Actually this should go to component-level checks,
11154 * but is done here due to performance. Move it to an other layer
11155 * is schema construction via an API is implemented.
11156 *
Daniel Veillard4255d502002-04-16 15:50:10 +000011157 * *WARNING* this interface is highly subject to change
11158 *
William M. Bracke7091952004-05-11 15:09:58 +000011159 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +000011160 * 1 in case of success.
11161 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011162static xmlSchemaTreeItemPtr
11163xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11164 xmlNodePtr node, xmlSchemaTypeType type,
11165 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +000011166{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011167 xmlSchemaModelGroupPtr item;
11168 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011169 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000011170 xmlAttrPtr attr;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011171 int min = 1, max = 1, isElemRef, hasRefs = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000011172
11173 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011174 return (NULL);
11175 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011176 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +000011177 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011178 item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011179 if (item == NULL)
11180 return (NULL);
11181
11182 if (withParticle) {
11183 if (type == XML_SCHEMA_TYPE_ALL) {
11184 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011185 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011186 } else {
11187 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011188 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11189 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11190 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011191 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011192 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11193 /*
11194 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011195 */
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000011196 particle = xmlSchemaAddParticle(ctxt, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011197 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011198 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011199 particle->children = (xmlSchemaTreeItemPtr) item;
11200 /*
11201 * Check for illegal attributes.
11202 */
11203 attr = node->properties;
11204 while (attr != NULL) {
11205 if (attr->ns == NULL) {
11206 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11207 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11208 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011209 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011210 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011211 }
11212 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011213 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011214 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011215 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011216 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000011217 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011218 } else {
11219 /*
11220 * Check for illegal attributes.
11221 */
11222 attr = node->properties;
11223 while (attr != NULL) {
11224 if (attr->ns == NULL) {
11225 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011226 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011227 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011228 }
11229 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011230 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011231 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011232 }
11233 attr = attr->next;
11234 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011235 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011236
William M. Brack2f2a6632004-08-20 23:09:47 +000011237 /*
11238 * Extract and validate attributes.
11239 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011240 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000011241 /*
11242 * And now for the children...
11243 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011244 child = node->children;
11245 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000011246 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011247 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011248 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011249 if (type == XML_SCHEMA_TYPE_ALL) {
11250 xmlSchemaParticlePtr part, last = NULL;
11251
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011252 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011253 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011254 schema, child, &isElemRef, 0);
11255 /*
11256 * SPEC cos-all-limited (2)
11257 * "The {max occurs} of all the particles in the {particles}
11258 * of the ('all') group must be 0 or 1.
11259 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011260 if (part != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011261 if (isElemRef)
11262 hasRefs++;
11263 if (part->minOccurs > 1) {
11264 xmlSchemaPCustomErr(ctxt,
11265 XML_SCHEMAP_COS_ALL_LIMITED,
11266 NULL, child,
11267 "Invalid value for minOccurs (must be 0 or 1)",
11268 NULL);
11269 /* Reset to 1. */
11270 part->minOccurs = 1;
11271 }
11272 if (part->maxOccurs > 1) {
11273 xmlSchemaPCustomErr(ctxt,
11274 XML_SCHEMAP_COS_ALL_LIMITED,
11275 NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011276 "Invalid value for maxOccurs (must be 0 or 1)",
11277 NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011278 /* Reset to 1. */
11279 part->maxOccurs = 1;
11280 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011281 if (last == NULL)
11282 item->children = (xmlSchemaTreeItemPtr) part;
11283 else
11284 last->next = (xmlSchemaTreeItemPtr) part;
11285 last = part;
11286 }
11287 child = child->next;
11288 }
11289 if (child != NULL) {
11290 xmlSchemaPContentErr(ctxt,
11291 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011292 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011293 "(annotation?, (annotation?, element*)");
11294 }
11295 } else {
11296 /* choice + sequence */
11297 xmlSchemaTreeItemPtr part = NULL, last = NULL;
11298
11299 while ((IS_SCHEMA(child, "element")) ||
11300 (IS_SCHEMA(child, "group")) ||
11301 (IS_SCHEMA(child, "any")) ||
11302 (IS_SCHEMA(child, "choice")) ||
11303 (IS_SCHEMA(child, "sequence"))) {
11304
11305 if (IS_SCHEMA(child, "element")) {
11306 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011307 xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11308 if (part && isElemRef)
11309 hasRefs++;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011310 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011311 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011312 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011313 if (part != NULL)
11314 hasRefs++;
11315 /*
11316 * Handle redefinitions.
11317 */
11318 if (ctxt->isRedefine && ctxt->redef &&
11319 (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11320 part && part->children)
11321 {
11322 if ((xmlSchemaGetQNameRefName(part->children) ==
11323 ctxt->redef->refName) &&
11324 (xmlSchemaGetQNameRefTargetNs(part->children) ==
11325 ctxt->redef->refTargetNs))
11326 {
11327 /*
11328 * SPEC src-redefine:
11329 * (6.1) "If it has a <group> among its contents at
11330 * some level the ·actual value· of whose ref
11331 * [attribute] is the same as the ·actual value· of
11332 * its own name attribute plus target namespace, then
11333 * all of the following must be true:"
11334 * (6.1.1) "It must have exactly one such group."
11335 */
11336 if (ctxt->redefCounter != 0) {
11337 xmlChar *str = NULL;
11338
11339 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11340 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11341 "The redefining model group definition "
11342 "'%s' must not contain more than one "
11343 "reference to the redefined definition",
11344 xmlSchemaFormatQName(&str,
11345 ctxt->redef->refTargetNs,
11346 ctxt->redef->refName),
11347 NULL);
11348 FREE_AND_NULL(str)
11349 part = NULL;
11350 } else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11351 ((WXS_PARTICLE(part))->maxOccurs != 1))
11352 {
11353 xmlChar *str = NULL;
11354 /*
11355 * SPEC src-redefine:
11356 * (6.1.2) "The ·actual value· of both that
11357 * group's minOccurs and maxOccurs [attribute]
11358 * must be 1 (or ·absent·).
11359 */
11360 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11361 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11362 "The redefining model group definition "
11363 "'%s' must not contain a reference to the "
11364 "redefined definition with a "
11365 "maxOccurs/minOccurs other than 1",
11366 xmlSchemaFormatQName(&str,
11367 ctxt->redef->refTargetNs,
11368 ctxt->redef->refName),
11369 NULL);
11370 FREE_AND_NULL(str)
11371 part = NULL;
11372 }
11373 ctxt->redef->reference = WXS_BASIC_CAST part;
11374 ctxt->redefCounter++;
11375 }
11376 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011377 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011378 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011379 xmlSchemaParseAny(ctxt, schema, child);
11380 } else if (IS_SCHEMA(child, "choice")) {
11381 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11382 XML_SCHEMA_TYPE_CHOICE, 1);
11383 } else if (IS_SCHEMA(child, "sequence")) {
11384 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11385 XML_SCHEMA_TYPE_SEQUENCE, 1);
11386 }
11387 if (part != NULL) {
11388 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011389 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011390 else
11391 last->next = part;
11392 last = part;
11393 }
11394 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011395 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011396 if (child != NULL) {
11397 xmlSchemaPContentErr(ctxt,
11398 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011399 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011400 "(annotation?, (element | group | choice | sequence | any)*)");
11401 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011402 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011403 if ((max == 0) && (min == 0))
11404 return (NULL);
11405 if (hasRefs) {
11406 /*
11407 * We need to resolve references.
11408 */
11409 WXS_ADD_PENDING(ctxt, item);
11410 }
11411 if (withParticle)
11412 return ((xmlSchemaTreeItemPtr) particle);
11413 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011414 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +000011415}
11416
11417/**
11418 * xmlSchemaParseRestriction:
11419 * @ctxt: a schema validation context
11420 * @schema: the schema being built
11421 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +000011422 *
11423 * parse a XML schema Restriction definition
11424 * *WARNING* this interface is highly subject to change
11425 *
11426 * Returns the type definition or NULL in case of error
11427 */
11428static xmlSchemaTypePtr
11429xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011430 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000011431{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011432 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011433 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000011434 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011435
11436 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11437 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011438 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011439 type = ctxt->ctxtType;
11440 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011441
11442 /*
William M. Brack2f2a6632004-08-20 23:09:47 +000011443 * Check for illegal attributes.
11444 */
11445 attr = node->properties;
11446 while (attr != NULL) {
11447 if (attr->ns == NULL) {
11448 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11449 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011450 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011451 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011452 }
11453 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011454 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011455 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011456 }
11457 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011458 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011459 /*
11460 * Extract and validate attributes.
11461 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011462 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000011463 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011464 * Attribute
William M. Brack2f2a6632004-08-20 23:09:47 +000011465 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011466 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011467 * Extract the base type. The "base" attribute is mandatory if inside
11468 * a complex type or if redefining.
11469 *
11470 * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011471 * among its [children]), the simple type definition which is
11472 * the {content type} of the type definition ·resolved· to by
11473 * the ·actual value· of the base [attribute]"
11474 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011475 if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011476 &(type->baseNs), &(type->base)) == 0)
11477 {
11478 if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11479 xmlSchemaPMissingAttrErr(ctxt,
11480 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011481 NULL, node, "base", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011482 } else if ((ctxt->isRedefine) &&
11483 (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11484 {
11485 if (type->base == NULL) {
11486 xmlSchemaPMissingAttrErr(ctxt,
11487 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011488 NULL, node, "base", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011489 } else if ((! xmlStrEqual(type->base, type->name)) ||
11490 (! xmlStrEqual(type->baseNs, type->targetNamespace)))
11491 {
11492 xmlChar *str1 = NULL, *str2 = NULL;
11493 /*
11494 * REDEFINE: SPEC src-redefine (5)
11495 * "Within the [children], each <simpleType> must have a
11496 * <restriction> among its [children] ... the ·actual value· of
11497 * whose base [attribute] must be the same as the ·actual value·
11498 * of its own name attribute plus target namespace;"
11499 */
11500 xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011501 NULL, node, "This is a redefinition, but the QName "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011502 "value '%s' of the 'base' attribute does not match the "
11503 "type's designation '%s'",
11504 xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11505 xmlSchemaFormatQName(&str1, type->targetNamespace,
11506 type->name), NULL);
11507 FREE_AND_NULL(str1);
11508 FREE_AND_NULL(str2);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011509 /* Avoid confusion and erase the values. */
11510 type->base = NULL;
11511 type->baseNs = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011512 }
11513 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011514 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011515 /*
11516 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011517 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011518 child = node->children;
11519 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011520 /*
11521 * Add the annotation to the simple type ancestor.
11522 */
11523 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000011524 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011525 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011526 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011527 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11528 /*
11529 * Corresponds to <simpleType><restriction><simpleType>.
11530 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011531 if (IS_SCHEMA(child, "simpleType")) {
11532 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011533 /*
William M. Brack2f2a6632004-08-20 23:09:47 +000011534 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011535 * Either the base [attribute] or the simpleType [child] of the
11536 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +000011537 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011538 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000011539 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011540 NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +000011541 "The attribute 'base' and the <simpleType> child are "
11542 "mutually exclusive", NULL);
11543 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011544 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +000011545 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011546 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011547 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011548 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011549 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011550 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011551 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011552 "Either the attribute 'base' or a <simpleType> child "
11553 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000011554 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011555 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11556 /*
11557 * Corresponds to <complexType><complexContent><restriction>...
11558 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011559 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011560 * Model groups <all>, <choice> and <sequence>.
11561 */
11562 if (IS_SCHEMA(child, "all")) {
11563 type->subtypes = (xmlSchemaTypePtr)
11564 xmlSchemaParseModelGroup(ctxt, schema, child,
11565 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011566 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011567 } else if (IS_SCHEMA(child, "choice")) {
11568 type->subtypes = (xmlSchemaTypePtr)
11569 xmlSchemaParseModelGroup(ctxt,
11570 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11571 child = child->next;
11572 } else if (IS_SCHEMA(child, "sequence")) {
11573 type->subtypes = (xmlSchemaTypePtr)
11574 xmlSchemaParseModelGroup(ctxt, schema, child,
11575 XML_SCHEMA_TYPE_SEQUENCE, 1);
11576 child = child->next;
11577 /*
11578 * Model group reference <group>.
11579 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011580 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011581 type->subtypes = (xmlSchemaTypePtr)
11582 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011583 /*
11584 * Note that the reference will be resolved in
11585 * xmlSchemaResolveTypeReferences();
11586 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011587 child = child->next;
11588 }
11589 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011590 /*
11591 * Corresponds to <complexType><simpleContent><restriction>...
11592 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011593 * "1.1 the simple type definition corresponding to the <simpleType>
11594 * among the [children] of <restriction> if there is one;"
11595 */
11596 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011597 /*
11598 * We will store the to-be-restricted simple type in
11599 * type->contentTypeDef *temporarily*.
11600 */
11601 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011602 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011603 if ( type->contentTypeDef == NULL)
11604 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011605 child = child->next;
11606 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011607 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011608
11609 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011610 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011611 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011612 /*
11613 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011614 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011615 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011616
Daniel Veillard01fa6152004-06-29 17:04:39 +000011617 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011618 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011619 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011620 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011621 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11622 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +000011623 * *Single Facet Value*
11624 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011625 while ((IS_SCHEMA(child, "minInclusive")) ||
11626 (IS_SCHEMA(child, "minExclusive")) ||
11627 (IS_SCHEMA(child, "maxInclusive")) ||
11628 (IS_SCHEMA(child, "maxExclusive")) ||
11629 (IS_SCHEMA(child, "totalDigits")) ||
11630 (IS_SCHEMA(child, "fractionDigits")) ||
11631 (IS_SCHEMA(child, "pattern")) ||
11632 (IS_SCHEMA(child, "enumeration")) ||
11633 (IS_SCHEMA(child, "whiteSpace")) ||
11634 (IS_SCHEMA(child, "length")) ||
11635 (IS_SCHEMA(child, "maxLength")) ||
11636 (IS_SCHEMA(child, "minLength"))) {
11637 facet = xmlSchemaParseFacet(ctxt, schema, child);
11638 if (facet != NULL) {
11639 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011640 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011641 else
11642 lastfacet->next = facet;
11643 lastfacet = facet;
11644 lastfacet->next = NULL;
11645 }
11646 child = child->next;
11647 }
11648 /*
11649 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011650 */
11651 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011652 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11653
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011654 facet = type->facets;
11655 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011656 facetLink = (xmlSchemaFacetLinkPtr)
11657 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +000011658 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011659 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011660 xmlFree(facetLink);
11661 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011662 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011663 facetLink->facet = facet;
11664 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011665 if (lastFacetLink == NULL)
11666 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011667 else
11668 lastFacetLink->next = facetLink;
11669 lastFacetLink = facetLink;
11670 facet = facet->next;
11671 } while (facet != NULL);
11672 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011673 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011674 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11675 /*
11676 * Attribute uses/declarations.
11677 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011678 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11679 (xmlSchemaItemListPtr *) &(type->attrUses),
11680 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11681 return(NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011682 /*
11683 * Attribute wildcard.
11684 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011685 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011686 type->attributeWildcard =
11687 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011688 child = child->next;
11689 }
11690 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011691 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011692 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11693 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?, (group | all | choice | sequence)?, "
11697 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011698 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011699 xmlSchemaPContentErr(ctxt,
11700 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011701 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011702 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11703 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11704 "length | minLength | maxLength | enumeration | whiteSpace | "
11705 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11706 } else {
11707 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011708 xmlSchemaPContentErr(ctxt,
11709 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011710 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011711 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11712 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11713 "length | minLength | maxLength | enumeration | whiteSpace | "
11714 "pattern)*))");
11715 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011716 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011717 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011718}
11719
11720/**
11721 * xmlSchemaParseExtension:
11722 * @ctxt: a schema validation context
11723 * @schema: the schema being built
11724 * @node: a subtree containing XML Schema informations
11725 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011726 * Parses an <extension>, which is found inside a
11727 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011728 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000011729 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011730 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000011731 */
11732static xmlSchemaTypePtr
11733xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011734 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000011735{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011736 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011737 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011738 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011739
11740 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11741 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011742 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011743 type = ctxt->ctxtType;
11744 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000011745
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011746 /*
11747 * Check for illegal attributes.
11748 */
11749 attr = node->properties;
11750 while (attr != NULL) {
11751 if (attr->ns == NULL) {
11752 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11753 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011754 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011755 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011756 }
11757 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011758 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011759 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011760 }
11761 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011762 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011763
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011764 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011765
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011766 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011767 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011768 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011769 if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11770 "base", &(type->baseNs), &(type->base)) == 0) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011771 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011772 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011773 XML_SCHEMAP_S4S_ATTR_MISSING,
11774 NULL, node, "base", NULL);
11775 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011776 /*
11777 * And now for the children...
11778 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011779 child = node->children;
11780 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011781 /*
11782 * Add the annotation to the type ancestor.
11783 */
11784 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000011785 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011786 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011787 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011788 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11789 /*
11790 * Corresponds to <complexType><complexContent><extension>... and:
11791 *
11792 * Model groups <all>, <choice>, <sequence> and <group>.
11793 */
11794 if (IS_SCHEMA(child, "all")) {
11795 type->subtypes = (xmlSchemaTypePtr)
11796 xmlSchemaParseModelGroup(ctxt, schema,
11797 child, XML_SCHEMA_TYPE_ALL, 1);
11798 child = child->next;
11799 } else if (IS_SCHEMA(child, "choice")) {
11800 type->subtypes = (xmlSchemaTypePtr)
11801 xmlSchemaParseModelGroup(ctxt, schema,
11802 child, XML_SCHEMA_TYPE_CHOICE, 1);
11803 child = child->next;
11804 } else if (IS_SCHEMA(child, "sequence")) {
11805 type->subtypes = (xmlSchemaTypePtr)
11806 xmlSchemaParseModelGroup(ctxt, schema,
11807 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11808 child = child->next;
11809 } else if (IS_SCHEMA(child, "group")) {
11810 type->subtypes = (xmlSchemaTypePtr)
11811 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011812 /*
11813 * Note that the reference will be resolved in
11814 * xmlSchemaResolveTypeReferences();
11815 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011816 child = child->next;
11817 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011818 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011819 if (child != NULL) {
11820 /*
11821 * Attribute uses/declarations.
11822 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011823 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11824 (xmlSchemaItemListPtr *) &(type->attrUses),
11825 XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11826 return(NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011827 /*
11828 * Attribute wildcard.
11829 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011830 if (IS_SCHEMA(child, "anyAttribute")) {
11831 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011832 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11833 child = child->next;
11834 }
11835 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011836 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011837 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11838 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011839 xmlSchemaPContentErr(ctxt,
11840 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011841 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011842 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011843 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011844 } else {
11845 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011846 xmlSchemaPContentErr(ctxt,
11847 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011848 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011849 "(annotation?, ((attribute | attributeGroup)*, "
11850 "anyAttribute?))");
11851 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011852 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011853 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011854}
11855
11856/**
11857 * xmlSchemaParseSimpleContent:
11858 * @ctxt: a schema validation context
11859 * @schema: the schema being built
11860 * @node: a subtree containing XML Schema informations
11861 *
11862 * parse a XML schema SimpleContent definition
11863 * *WARNING* this interface is highly subject to change
11864 *
11865 * Returns the type definition or NULL in case of error
11866 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011867static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011868xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011869 xmlSchemaPtr schema, xmlNodePtr node,
11870 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000011871{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011872 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011873 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011874 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011875
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011876 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11877 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011878 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011879 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011880 /* Not a component, don't create it. */
11881 type = ctxt->ctxtType;
11882 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11883 /*
11884 * Check for illegal attributes.
11885 */
11886 attr = node->properties;
11887 while (attr != NULL) {
11888 if (attr->ns == NULL) {
11889 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011890 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011891 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011892 }
11893 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011894 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011895 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011896 }
11897 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011898 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011899
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011900 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000011901
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011902 /*
11903 * And now for the children...
11904 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011905 child = node->children;
11906 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011907 /*
11908 * Add the annotation to the complex type ancestor.
11909 */
11910 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000011911 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011912 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011913 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +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. Buchcik764b3d62005-08-12 12:25:23 +000011918 "(annotation?, (restriction | extension))");
11919 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011920 if (child == NULL) {
11921 xmlSchemaPContentErr(ctxt,
11922 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011923 NULL, node, NULL, NULL,
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011924 "(annotation?, (restriction | extension))");
11925 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011926 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011927 xmlSchemaParseRestriction(ctxt, schema, child,
11928 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011929 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011930 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011931 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011932 xmlSchemaParseExtension(ctxt, schema, child,
11933 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011934 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011935 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011936 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011937 if (child != NULL) {
11938 xmlSchemaPContentErr(ctxt,
11939 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011940 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011941 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000011942 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011943 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000011944}
11945
11946/**
11947 * xmlSchemaParseComplexContent:
11948 * @ctxt: a schema validation context
11949 * @schema: the schema being built
11950 * @node: a subtree containing XML Schema informations
11951 *
11952 * parse a XML schema ComplexContent definition
11953 * *WARNING* this interface is highly subject to change
11954 *
11955 * Returns the type definition or NULL in case of error
11956 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011957static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011958xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011959 xmlSchemaPtr schema, xmlNodePtr node,
11960 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000011961{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011962 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011963 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011964 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011965
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011966 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11967 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011968 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011969 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011970 /* Not a component, don't create it. */
11971 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011972 /*
11973 * Check for illegal attributes.
11974 */
11975 attr = node->properties;
11976 while (attr != NULL) {
11977 if (attr->ns == NULL) {
11978 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011979 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011980 {
11981 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011982 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011983 }
11984 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11985 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011986 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011987 }
11988 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011989 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011990
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011991 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011992
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011993 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011994 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011995 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011996 if (xmlGetBooleanProp(ctxt, node, "mixed", 0)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011997 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
11998 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011999 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012000 child = node->children;
12001 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012002 /*
12003 * Add the annotation to the complex type ancestor.
12004 */
12005 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000012006 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012007 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012008 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +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. Buchcik764b3d62005-08-12 12:25:23 +000012013 NULL, "(annotation?, (restriction | extension))");
12014 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012015 if (child == NULL) {
12016 xmlSchemaPContentErr(ctxt,
12017 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012018 NULL, node, NULL,
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012019 NULL, "(annotation?, (restriction | extension))");
12020 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012021 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012022 xmlSchemaParseRestriction(ctxt, schema, child,
12023 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012024 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012025 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012026 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012027 xmlSchemaParseExtension(ctxt, schema, child,
12028 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012029 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012030 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012031 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012032 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012033 xmlSchemaPContentErr(ctxt,
12034 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012035 NULL, node, child,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012036 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000012037 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012038 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000012039}
12040
12041/**
12042 * xmlSchemaParseComplexType:
12043 * @ctxt: a schema validation context
12044 * @schema: the schema being built
12045 * @node: a subtree containing XML Schema informations
12046 *
12047 * parse a XML schema Complex Type definition
12048 * *WARNING* this interface is highly subject to change
12049 *
12050 * Returns the type definition or NULL in case of error
12051 */
12052static xmlSchemaTypePtr
12053xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000012054 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000012055{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012056 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000012057 xmlNodePtr child = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012058 const xmlChar *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012059 xmlAttrPtr attr;
12060 const xmlChar *attrValue;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012061#ifdef ENABLE_NAMED_LOCALS
Daniel Veillard1a380b82004-10-21 16:00:06 +000012062 char buf[40];
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012063#endif
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012064 int final = 0, block = 0, hasRestrictionOrExtension = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000012065
Daniel Veillard4255d502002-04-16 15:50:10 +000012066
12067 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12068 return (NULL);
12069
Daniel Veillard01fa6152004-06-29 17:04:39 +000012070 ctxtType = ctxt->ctxtType;
12071
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012072 if (topLevel) {
12073 attr = xmlSchemaGetPropNode(node, "name");
12074 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012075 xmlSchemaPMissingAttrErr(ctxt,
12076 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012077 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012078 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012079 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12080 return (NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012081 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012082 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012083
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012084 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012085 /*
12086 * Parse as local complex type definition.
12087 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012088#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000012089 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012090 type = xmlSchemaAddType(ctxt, schema,
12091 XML_SCHEMA_TYPE_COMPLEX,
12092 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012093 ctxt->targetNamespace, node, 0);
12094#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012095 type = xmlSchemaAddType(ctxt, schema,
12096 XML_SCHEMA_TYPE_COMPLEX,
12097 NULL, ctxt->targetNamespace, node, 0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012098#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012099 if (type == NULL)
12100 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012101 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012102 type->node = node;
12103 type->type = XML_SCHEMA_TYPE_COMPLEX;
12104 /*
12105 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012106 */
12107 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012108 /*
12109 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012110 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012111 type = xmlSchemaAddType(ctxt, schema,
12112 XML_SCHEMA_TYPE_COMPLEX,
12113 name, ctxt->targetNamespace, node, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012114 if (type == NULL)
12115 return (NULL);
12116 type->node = node;
12117 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012118 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000012119 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012120 type->targetNamespace = ctxt->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012121 /*
12122 * Handle attributes.
12123 */
12124 attr = node->properties;
12125 while (attr != NULL) {
12126 if (attr->ns == NULL) {
12127 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12128 /*
12129 * Attribute "id".
12130 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012131 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012132 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12133 /*
12134 * Attribute "mixed".
12135 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012136 if (xmlSchemaPGetBoolNodeValue(ctxt,
12137 NULL, (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012138 type->flags |= XML_SCHEMAS_TYPE_MIXED;
12139 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012140 /*
12141 * Attributes of global complex type definitions.
12142 */
12143 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12144 /* Pass. */
12145 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12146 /*
12147 * Attribute "abstract".
12148 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012149 if (xmlSchemaPGetBoolNodeValue(ctxt,
12150 NULL, (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012151 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12152 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12153 /*
12154 * Attribute "final".
12155 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012156 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012157 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012158 if (xmlSchemaPValAttrBlockFinal(attrValue,
12159 &(type->flags),
12160 -1,
12161 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12162 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12163 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012164 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012165 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012166 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012167 NULL, (xmlNodePtr) attr, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012168 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012169 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012170 } else
12171 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012172 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12173 /*
12174 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012175 */
12176 attrValue = xmlSchemaGetNodeContent(ctxt,
12177 (xmlNodePtr) attr);
12178 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012179 -1,
12180 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012181 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012182 -1, -1, -1) != 0) {
12183 xmlSchemaPSimpleTypeErr(ctxt,
12184 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012185 NULL, (xmlNodePtr) attr, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012186 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012187 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012188 } else
12189 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012190 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012191 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012192 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012193 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012194 } else {
12195 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012196 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012197 }
12198 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012199 xmlSchemaPIllegalAttrErr(ctxt,
12200 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012201 }
12202 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012203 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012204 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000012205 /*
12206 * Apply default "block" values.
12207 */
12208 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12209 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12210 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12211 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12212 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012213 if (! final) {
12214 /*
12215 * Apply default "block" values.
12216 */
12217 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12218 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12219 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12220 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12221 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012222 /*
12223 * And now for the children...
12224 */
Daniel Veillard4255d502002-04-16 15:50:10 +000012225 child = node->children;
12226 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000012227 type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012228 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012229 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012230 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000012231 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012232 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012233 * <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012234 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012235 * Specifying mixed='true' when the <simpleContent>
12236 * alternative is chosen has no effect
12237 */
William M. Bracke7091952004-05-11 15:09:58 +000012238 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12239 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012240 xmlSchemaParseSimpleContent(ctxt, schema, child,
12241 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012242 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012243 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012244 /*
12245 * <complexType><complexContent>...
12246 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012247 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012248 xmlSchemaParseComplexContent(ctxt, schema, child,
12249 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012250 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012251 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012252 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012253 * E.g <complexType><sequence>... or <complexType><attribute>... etc.
12254 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012255 * SPEC
12256 * "...the third alternative (neither <simpleContent> nor
12257 * <complexContent>) is chosen. This case is understood as shorthand
12258 * for complex content restricting the ·ur-type definition·, and the
12259 * details of the mappings should be modified as necessary.
12260 */
12261 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12262 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012263 /*
12264 * Parse model groups.
12265 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012266 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012267 type->subtypes = (xmlSchemaTypePtr)
12268 xmlSchemaParseModelGroup(ctxt, schema, child,
12269 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012270 child = child->next;
12271 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012272 type->subtypes = (xmlSchemaTypePtr)
12273 xmlSchemaParseModelGroup(ctxt, schema, child,
12274 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012275 child = child->next;
12276 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012277 type->subtypes = (xmlSchemaTypePtr)
12278 xmlSchemaParseModelGroup(ctxt, schema, child,
12279 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012280 child = child->next;
12281 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012282 type->subtypes = (xmlSchemaTypePtr)
12283 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012284 /*
12285 * Note that the reference will be resolved in
12286 * xmlSchemaResolveTypeReferences();
12287 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012288 child = child->next;
12289 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012290 /*
12291 * Parse attribute decls/refs.
12292 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012293 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12294 (xmlSchemaItemListPtr *) &(type->attrUses),
12295 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12296 return(NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012297 /*
12298 * Parse attribute wildcard.
12299 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012300 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012301 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12302 child = child->next;
12303 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012304 }
12305 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012306 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012307 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012308 NULL, node, child,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012309 NULL, "(annotation?, (simpleContent | complexContent | "
12310 "((group | all | choice | sequence)?, ((attribute | "
12311 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000012312 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012313 /*
12314 * REDEFINE: SPEC src-redefine (5)
12315 */
12316 if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12317 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012318 NULL, node, "This is a redefinition, thus the "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012319 "<complexType> must have a <restriction> or <extension> "
12320 "grand-child", NULL);
12321 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012322 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000012323 return (type);
12324}
12325
Daniel Veillard4255d502002-04-16 15:50:10 +000012326/************************************************************************
12327 * *
12328 * Validating using Schemas *
12329 * *
12330 ************************************************************************/
12331
12332/************************************************************************
12333 * *
12334 * Reading/Writing Schemas *
12335 * *
12336 ************************************************************************/
12337
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012338#if 0 /* Will be enabled if it is clear what options are needed. */
12339/**
12340 * xmlSchemaParserCtxtSetOptions:
12341 * @ctxt: a schema parser context
12342 * @options: a combination of xmlSchemaParserOption
12343 *
12344 * Sets the options to be used during the parse.
12345 *
12346 * Returns 0 in case of success, -1 in case of an
12347 * API error.
12348 */
12349static int
12350xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12351 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012352
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012353{
12354 int i;
12355
12356 if (ctxt == NULL)
12357 return (-1);
12358 /*
12359 * WARNING: Change the start value if adding to the
12360 * xmlSchemaParseOption.
12361 */
12362 for (i = 1; i < (int) sizeof(int) * 8; i++) {
12363 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012364 return (-1);
12365 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012366 }
12367 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012368 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012369}
12370
12371/**
12372 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012373 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012374 *
12375 * Returns the option combination of the parser context.
12376 */
12377static int
12378xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012379
12380{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012381 if (ctxt == NULL)
12382 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012383 else
12384 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012385}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012386#endif
12387
Daniel Veillard4255d502002-04-16 15:50:10 +000012388/**
12389 * xmlSchemaNewParserCtxt:
12390 * @URL: the location of the schema
12391 *
12392 * Create an XML Schemas parse context for that file/resource expected
12393 * to contain an XML Schemas file.
12394 *
12395 * Returns the parser context or NULL in case of error
12396 */
12397xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012398xmlSchemaNewParserCtxt(const char *URL)
12399{
Daniel Veillard4255d502002-04-16 15:50:10 +000012400 xmlSchemaParserCtxtPtr ret;
12401
12402 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012403 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000012404
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012405 ret = xmlSchemaParserCtxtCreate();
12406 if (ret == NULL)
12407 return(NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012408 ret->dict = xmlDictCreate();
12409 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012410 return (ret);
12411}
12412
12413/**
Daniel Veillard6045c902002-10-09 21:13:59 +000012414 * xmlSchemaNewMemParserCtxt:
12415 * @buffer: a pointer to a char array containing the schemas
12416 * @size: the size of the array
12417 *
12418 * Create an XML Schemas parse context for that memory buffer expected
12419 * to contain an XML Schemas file.
12420 *
12421 * Returns the parser context or NULL in case of error
12422 */
12423xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012424xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12425{
Daniel Veillard6045c902002-10-09 21:13:59 +000012426 xmlSchemaParserCtxtPtr ret;
12427
12428 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012429 return (NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012430 ret = xmlSchemaParserCtxtCreate();
12431 if (ret == NULL)
12432 return(NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000012433 ret->buffer = buffer;
12434 ret->size = size;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012435 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000012436 return (ret);
12437}
12438
12439/**
Daniel Veillard9d751502003-10-29 13:21:47 +000012440 * xmlSchemaNewDocParserCtxt:
12441 * @doc: a preparsed document tree
12442 *
12443 * Create an XML Schemas parse context for that document.
12444 * NB. The document may be modified during the parsing process.
12445 *
12446 * Returns the parser context or NULL in case of error
12447 */
12448xmlSchemaParserCtxtPtr
12449xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12450{
12451 xmlSchemaParserCtxtPtr ret;
12452
12453 if (doc == NULL)
12454 return (NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012455 ret = xmlSchemaParserCtxtCreate();
12456 if (ret == NULL)
12457 return(NULL);
Daniel Veillard9d751502003-10-29 13:21:47 +000012458 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000012459 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000012460 /* The application has responsibility for the document */
12461 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000012462
12463 return (ret);
12464}
12465
12466/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012467 * xmlSchemaFreeParserCtxt:
12468 * @ctxt: the schema parser context
12469 *
12470 * Free the resources associated to the schema parser context
12471 */
12472void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012473xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12474{
Daniel Veillard4255d502002-04-16 15:50:10 +000012475 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012476 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000012477 if (ctxt->doc != NULL && !ctxt->preserve)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012478 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012479 if (ctxt->vctxt != NULL) {
12480 xmlSchemaFreeValidCtxt(ctxt->vctxt);
12481 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012482 if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12483 xmlSchemaConstructionCtxtFree(ctxt->constructor);
12484 ctxt->constructor = NULL;
12485 ctxt->ownsConstructor = 0;
12486 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012487 if (ctxt->attrProhibs != NULL)
12488 xmlSchemaItemListFree(ctxt->attrProhibs);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012489 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000012490 xmlFree(ctxt);
12491}
12492
12493/************************************************************************
12494 * *
12495 * Building the content models *
12496 * *
12497 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012498
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012499static void
12500xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012501 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012502{
Daniel Veillarda980bef2005-07-18 21:34:03 +000012503 xmlAutomataStatePtr start, tmp;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012504 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012505 xmlSchemaSubstGroupPtr substGroup;
12506 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012507
12508 elemDecl = (xmlSchemaElementPtr) particle->children;
12509 /*
12510 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012511 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012512 start = pctxt->state;
Daniel Veillarda980bef2005-07-18 21:34:03 +000012513 if (end == NULL)
12514 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012515 substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012516 if (substGroup == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012517 xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012518 XML_SCHEMAP_INTERNAL,
12519 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12520 "declaration is marked having a subst. group but none "
12521 "available.\n", elemDecl->name, NULL);
12522 return;
12523 }
Daniel Veillarda980bef2005-07-18 21:34:03 +000012524 if (counter >= 0) {
12525 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012526 * NOTE that we put the declaration in, even if it's abstract.
12527 * However, an error will be raised during *validation* if an element
12528 * information item shall be validated against an abstract element
12529 * declaration.
Daniel Veillarda980bef2005-07-18 21:34:03 +000012530 */
12531 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12532 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12533 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12534 /*
12535 * Add subst. group members.
12536 */
12537 for (i = 0; i < substGroup->members->nbItems; i++) {
12538 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12539 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12540 member->name, member->targetNamespace, member);
12541 }
12542 } else if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012543 /*
12544 * NOTE that we put the declaration in, even if it's abstract,
12545 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012546 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012547 xmlAutomataNewTransition2(pctxt->am,
12548 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012549 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12550 /*
12551 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012552 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012553 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012554 member = (xmlSchemaElementPtr) substGroup->members->items[i];
Daniel Veillarda980bef2005-07-18 21:34:03 +000012555 tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12556 member->name, member->targetNamespace,
12557 1, 1, member);
12558 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012559 }
12560 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012561 xmlAutomataStatePtr hop;
12562 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12563 UNBOUNDED : particle->maxOccurs - 1;
12564 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12565
12566 counter =
12567 xmlAutomataNewCounter(pctxt->am, minOccurs,
12568 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012569 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012570
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012571 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012572 xmlAutomataNewTransition2(pctxt->am,
12573 start, NULL,
12574 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012575 hop);
12576 /*
Daniel Veillarda980bef2005-07-18 21:34:03 +000012577 * Add subst. group members.
12578 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012579 for (i = 0; i < substGroup->members->nbItems; i++) {
12580 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12581 xmlAutomataNewEpsilon(pctxt->am,
12582 xmlAutomataNewTransition2(pctxt->am,
12583 start, NULL,
12584 member->name, member->targetNamespace, member),
12585 hop);
12586 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012587 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12588 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12589 }
12590 if (particle->minOccurs == 0)
12591 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012592 pctxt->state = end;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012593}
12594
12595static void
12596xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12597 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012598{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012599 if (((xmlSchemaElementPtr) particle->children)->flags &
12600 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012601 /*
12602 * Substitution groups.
12603 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000012604 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012605 } else {
12606 xmlSchemaElementPtr elemDecl;
12607 xmlAutomataStatePtr start;
12608
12609 elemDecl = (xmlSchemaElementPtr) particle->children;
12610
12611 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012612 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012613 if (particle->maxOccurs == 1) {
12614 start = ctxt->state;
12615 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012616 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12617 } else if ((particle->maxOccurs >= UNBOUNDED) &&
12618 (particle->minOccurs < 2)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012619 /* Special case. */
Kasimier T. Buchcik7ca5aed2005-12-12 15:13:40 +000012620 start = ctxt->state;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012621 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Kasimier T. Buchcik7ca5aed2005-12-12 15:13:40 +000012622 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12623 ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12624 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012625 } else {
12626 int counter;
12627 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12628 UNBOUNDED : particle->maxOccurs - 1;
12629 int minOccurs = particle->minOccurs < 1 ?
12630 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012631
12632 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012633 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12634 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12635 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12636 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12637 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12638 NULL, counter);
12639 }
12640 if (particle->minOccurs == 0)
12641 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12642 }
12643}
12644
Daniel Veillard4255d502002-04-16 15:50:10 +000012645/**
12646 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000012647 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012648 * @particle: the particle component
12649 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000012650 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012651 * Create the automaton for the {content type} of a complex type.
12652 *
Daniel Veillard4255d502002-04-16 15:50:10 +000012653 */
12654static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012655xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012656 xmlSchemaParticlePtr particle)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012657{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012658 if (particle == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012659 PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012660 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000012661 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012662 if (particle->children == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012663 /*
12664 * Just return in this case. A missing "term" of the particle
12665 * might arise due to an invalid "term" component.
12666 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012667 return;
12668 }
12669
12670 switch (particle->children->type) {
12671 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012672 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012673 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012674 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000012675
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012676 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012677
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012678 start = pctxt->state;
12679 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012680
12681 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012682 if (wild->any == 1) {
12683 /*
12684 * We need to add both transitions:
12685 *
12686 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012687 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012688 pctxt->state =
12689 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012690 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012691 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012692 /*
12693 * 2. the {"*"} for elements in no namespace.
12694 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012695 pctxt->state =
12696 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012697 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012698 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012699
12700 } else if (wild->nsSet != NULL) {
12701 ns = wild->nsSet;
12702 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012703 pctxt->state = start;
12704 pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12705 pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12706 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012707 ns = ns->next;
12708 } while (ns != NULL);
12709
12710 } else if (wild->negNsSet != NULL) {
Daniel Veillard6e65e152005-08-09 11:09:52 +000012711 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12712 start, end, BAD_CAST "*", wild->negNsSet->value,
12713 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012714 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012715 } else {
12716 int counter;
12717 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012718 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012719 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012720 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012721 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012722
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012723 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12724 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012725 if (wild->any == 1) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012726 pctxt->state =
12727 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012728 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012729 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12730 pctxt->state =
12731 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012732 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012733 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012734 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012735 ns = wild->nsSet;
12736 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012737 pctxt->state =
12738 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012739 start, NULL, BAD_CAST "*", ns->value, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012740 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012741 ns = ns->next;
12742 } while (ns != NULL);
12743
12744 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012745 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
Daniel Veillard9efc4762005-07-19 14:33:55 +000012746 start, hop, BAD_CAST "*", wild->negNsSet->value,
12747 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012748 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012749 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12750 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012751 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012752 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012753 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012754 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012755 pctxt->state = end;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012756 break;
12757 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012758 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012759 xmlSchemaBuildContentModelForElement(pctxt, particle);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012760 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012761 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012762 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012763
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012764 /*
12765 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012766 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012767 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012768 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12769 sub = particle->children->children;
12770 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012771 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012772 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012773 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012774 }
12775 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012776 xmlAutomataStatePtr oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012777
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012778 if (particle->maxOccurs >= UNBOUNDED) {
12779 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012780 xmlAutomataStatePtr tmp;
12781 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012782
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012783 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012784 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012785 oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012786
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012787 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012788 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000012789
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012790 sub = particle->children->children;
12791 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012792 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012793 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012794 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012795 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012796 tmp = pctxt->state;
12797 xmlAutomataNewCountedTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012798 oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012799 pctxt->state =
12800 xmlAutomataNewCounterTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012801 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000012802
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012803 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012804 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Daniel Veillardafc05b62005-07-17 06:11:19 +000012805 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012806 oldstate = pctxt->state;
Daniel Veillardafc05b62005-07-17 06:11:19 +000012807
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012808 sub = particle->children->children;
12809 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012810 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012811 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012812 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012813 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012814 xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012815 oldstate);
Daniel Veillardafc05b62005-07-17 06:11:19 +000012816 /*
12817 * epsilon needed to block previous trans from
12818 * being allowed to enter back from another
12819 * construct
12820 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012821 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12822 pctxt->state, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012823 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012824 xmlAutomataNewEpsilon(pctxt->am,
12825 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012826 }
12827 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012828 } else if ((particle->maxOccurs > 1)
12829 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012830 xmlAutomataStatePtr tmp;
12831 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012832
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012833 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012834 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012835 oldstate = pctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000012836
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012837 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012838 particle->minOccurs - 1,
12839 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012840
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012841 sub = particle->children->children;
12842 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012843 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012844 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012845 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012846 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012847 tmp = pctxt->state;
12848 xmlAutomataNewCountedTrans(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012849 tmp, oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012850 pctxt->state =
12851 xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012852 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012853 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012854 xmlAutomataNewEpsilon(pctxt->am,
12855 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012856 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012857 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012858 sub = particle->children->children;
12859 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012860 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012861 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012862 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012863 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012864 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012865 xmlAutomataNewEpsilon(pctxt->am, oldstate,
12866 pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012867 }
12868 }
12869 }
12870 break;
12871 }
12872 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012873 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012874 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000012875
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012876 start = pctxt->state;
12877 end = xmlAutomataNewState(pctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000012878
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012879 /*
12880 * iterate over the subtypes and remerge the end with an
12881 * epsilon transition
12882 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012883 if (particle->maxOccurs == 1) {
12884 sub = particle->children->children;
12885 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012886 pctxt->state = start;
12887 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012888 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012889 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012890 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012891 }
12892 } else {
12893 int counter;
Daniel Veillardafc05b62005-07-17 06:11:19 +000012894 xmlAutomataStatePtr hop, base;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012895 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12896 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012897 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012898 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000012899
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012900 /*
12901 * use a counter to keep track of the number of transtions
12902 * which went through the choice.
12903 */
12904 counter =
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012905 xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12906 hop = xmlAutomataNewState(pctxt->am);
12907 base = xmlAutomataNewState(pctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000012908
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012909 sub = particle->children->children;
12910 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012911 pctxt->state = base;
12912 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012913 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012914 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012915 sub = sub->next;
Daniel Veillarda980bef2005-07-18 21:34:03 +000012916 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012917 xmlAutomataNewEpsilon(pctxt->am, start, base);
12918 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
12919 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012920 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012921 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012922 xmlAutomataNewEpsilon(pctxt->am, start, end);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012923 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012924 pctxt->state = end;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012925 break;
12926 }
12927 case XML_SCHEMA_TYPE_ALL:{
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +000012928 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012929 xmlSchemaParticlePtr sub;
12930 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012931 int lax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012932
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012933 sub = (xmlSchemaParticlePtr) particle->children->children;
12934 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012935 break;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012936 start = pctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012937 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012938 pctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012939
12940 elemDecl = (xmlSchemaElementPtr) sub->children;
12941 if (elemDecl == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012942 PERROR_INT("xmlSchemaBuildAContentModel",
12943 "<element> particle has no term");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012944 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012945 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012946 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012947 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000012948 * {particles} of the group must be 0 or 1; this is
12949 * already ensured during the parse of the content of
12950 * <all>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012951 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000012952 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12953 int counter;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012954
Daniel Veillarda980bef2005-07-18 21:34:03 +000012955 /*
12956 * This is an abstract group, we need to share
12957 * the same counter for all the element transitions
12958 * derived from the group
12959 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012960 counter = xmlAutomataNewCounter(pctxt->am,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012961 sub->minOccurs, sub->maxOccurs);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012962 xmlSchemaBuildContentModelForSubstGroup(pctxt,
12963 sub, counter, pctxt->state);
Daniel Veillarda980bef2005-07-18 21:34:03 +000012964 } else {
12965 if ((sub->minOccurs == 1) &&
12966 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012967 xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
12968 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012969 elemDecl->name,
12970 elemDecl->targetNamespace,
12971 1, 1, elemDecl);
12972 } else if ((sub->minOccurs == 0) &&
12973 (sub->maxOccurs == 1)) {
12974
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012975 xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
12976 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012977 elemDecl->name,
12978 elemDecl->targetNamespace,
12979 0,
12980 1,
12981 elemDecl);
12982 }
12983 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012984 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012985 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012986 lax = particle->minOccurs == 0;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012987 pctxt->state =
12988 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012989 break;
12990 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012991 case XML_SCHEMA_TYPE_GROUP:
12992 /*
12993 * If we hit a model group definition, then this means that
12994 * it was empty, thus was not substituted for the containing
12995 * model group. Just do nothing in this case.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012996 * TODO: But the group should be substituted and not occur at
12997 * all in the content model at this point. Fix this.
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012998 */
12999 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013000 default:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013001 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13002 "xmlSchemaBuildAContentModel",
13003 "found unexpected term of type '%s' in content model",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013004 WXS_ITEM_TYPE_NAME(particle->children), NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013005 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000013006 }
13007}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013008
Daniel Veillard4255d502002-04-16 15:50:10 +000013009/**
13010 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000013011 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013012 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000013013 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000013014 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013015 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000013016 */
13017static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013018xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013019 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013020{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013021 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13022 (type->contModel != NULL) ||
13023 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13024 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013025 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013026
13027#ifdef DEBUG_CONTENT
13028 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013029 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013030#endif
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013031 ctxt->am = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013032 ctxt->am = xmlNewAutomata();
13033 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013034 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013035 "Cannot create automata for complex type %s\n", type->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013036 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000013037 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000013038 ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013039 /*
13040 * Build the automaton.
13041 */
13042 xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
Daniel Veillard4255d502002-04-16 15:50:10 +000013043 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013044 type->contModel = xmlAutomataCompile(ctxt->am);
13045 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013046 xmlSchemaPCustomErr(ctxt,
13047 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013048 WXS_BASIC_CAST type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013049 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013050 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013051 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013052 XML_SCHEMAP_NOT_DETERMINISTIC,
13053 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013054 WXS_BASIC_CAST type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013055 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000013056 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000013057#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013058 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013059 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013060 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000013061#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000013062 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000013063 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013064 xmlFreeAutomata(ctxt->am);
13065 ctxt->am = NULL;
13066}
13067
13068/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013069 * xmlSchemaResolveElementReferences:
Daniel Veillard4255d502002-04-16 15:50:10 +000013070 * @elem: the schema element context
13071 * @ctxt: the schema parser context
13072 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000013073 * Resolves the references of an element declaration
13074 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013075 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000013076 */
13077static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013078xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13079 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000013080{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013081 if ((ctxt == NULL) || (elemDecl == NULL) ||
13082 ((elemDecl != NULL) &&
13083 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013084 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013085 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013086
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013087 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013088 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013089
13090 /* (type definition) ... otherwise the type definition ·resolved·
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013091 * to by the ·actual value· of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013092 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013093 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013094 elemDecl->namedTypeNs);
13095 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013096 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013097 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013098 WXS_BASIC_CAST elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013099 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013100 XML_SCHEMA_TYPE_BASIC, "type definition");
13101 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013102 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013103 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013104 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013105 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013106
Daniel Veillardc0826a72004-08-10 14:17:33 +000013107 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013108 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013109 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000013110 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013111 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13112 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013113 if (substHead == NULL) {
13114 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013115 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013116 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013117 "substitutionGroup", elemDecl->substGroup,
13118 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013119 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013120 xmlSchemaResolveElementReferences(substHead, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013121 /*
13122 * Set the "substitution group affiliation".
13123 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013124 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013125 WXS_SUBST_HEAD(elemDecl) = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013126 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013127 * The type definitions is set to:
13128 * SPEC "...the {type definition} of the element
13129 * declaration ·resolved· to by the ·actual value·
13130 * of the substitutionGroup [attribute], if present"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013131 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013132 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013133 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013134 }
13135 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013136 /*
13137 * SPEC "The definition of anyType serves as the default type definition
13138 * for element declarations whose XML representation does not specify one."
13139 */
13140 if ((elemDecl->subtypes == NULL) &&
13141 (elemDecl->namedType == NULL) &&
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013142 (elemDecl->substGroup == NULL))
13143 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000013144}
13145
13146/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013147 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000013148 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013149 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000013150 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013151 * Checks and builds the "member type definitions" property of the union
13152 * simple type. This handles part (1), part (2) is done in
13153 * xmlSchemaFinishMemberTypeDefinitionsProperty()
13154 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000013155 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000013156 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013157static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013158xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13159 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000013160{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013161
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013162 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013163 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000013164
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013165 /*
13166 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13167 * define the explicit members as the type definitions ·resolved·
13168 * to by the items in the ·actual value· of the memberTypes [attribute],
13169 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013170 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000013171 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013172 /*
13173 * Resolve references.
13174 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013175 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013176 lastLink = NULL;
13177 while (link != NULL) {
13178 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013179
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013180 name = ((xmlSchemaQNameRefPtr) link->type)->name;
13181 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13182
13183 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013184 if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013185 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013186 WXS_BASIC_CAST type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013187 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13188 /*
13189 * Remove the member type link.
13190 */
13191 if (lastLink == NULL)
13192 type->memberTypes = link->next;
13193 else
13194 lastLink->next = link->next;
13195 newLink = link;
13196 link = link->next;
13197 xmlFree(newLink);
13198 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013199 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013200 lastLink = link;
13201 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013202 }
13203 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013204 /*
13205 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013206 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013207 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013208 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013209 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13210 if (link == NULL) {
13211 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13212 return (-1);
13213 }
13214 link->type = memberType;
13215 link->next = NULL;
13216 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013217 type->memberTypes = link;
13218 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000013219 lastLink->next = link;
13220 lastLink = link;
13221 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013222 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013223 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000013224}
13225
Daniel Veillard4255d502002-04-16 15:50:10 +000013226/**
Daniel Veillard3646d642004-06-02 19:19:14 +000013227 * xmlSchemaIsDerivedFromBuiltInType:
13228 * @ctxt: the schema parser context
13229 * @type: the type definition
13230 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013231 *
Daniel Veillard3646d642004-06-02 19:19:14 +000013232 *
13233 * Returns 1 if the type has the given value type, or
13234 * is derived from such a type.
13235 */
William M. Brack803812b2004-06-03 02:11:24 +000013236static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013237xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000013238{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013239 if (type == NULL)
13240 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013241 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013242 return (0);
13243 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13244 if (type->builtInType == valType)
13245 return(1);
13246 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13247 (type->builtInType == XML_SCHEMAS_ANYTYPE))
13248 return (0);
13249 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard6a0baa02005-12-10 11:11:12 +000013250 }
13251 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000013252}
13253
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013254#if 0
13255/**
13256 * xmlSchemaIsDerivedFromBuiltInType:
13257 * @ctxt: the schema parser context
13258 * @type: the type definition
13259 * @valType: the value type
13260 *
13261 *
13262 * Returns 1 if the type has the given value type, or
13263 * is derived from such a type.
13264 */
13265static int
13266xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13267{
13268 if (type == NULL)
13269 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013270 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013271 return (0);
13272 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13273 if (type->builtInType == valType)
13274 return(1);
13275 return (0);
13276 } else
13277 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13278
13279 return (0);
13280}
13281#endif
13282
13283static xmlSchemaTypePtr
13284xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13285{
13286 if (type == NULL)
13287 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013288 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013289 return (NULL);
13290 if (type->type == XML_SCHEMA_TYPE_BASIC)
Daniel Veillard6a0baa02005-12-10 11:11:12 +000013291 return(type);
13292 return(xmlSchemaQueryBuiltInType(type->subtypes));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013293}
13294
Daniel Veillard3646d642004-06-02 19:19:14 +000013295/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013296 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013297 * @type: the simpleType definition
13298 *
13299 * Returns the primitive type of the given type or
13300 * NULL in case of error.
13301 */
13302static xmlSchemaTypePtr
13303xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13304{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013305
Daniel Veillard01fa6152004-06-29 17:04:39 +000013306 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013307 /*
13308 * Note that anySimpleType is actually not a primitive type
13309 * but we need that here.
13310 */
13311 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13312 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013313 return (type);
13314 type = type->baseType;
13315 }
13316
13317 return (NULL);
13318}
13319
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013320#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013321/**
13322 * xmlSchemaGetBuiltInTypeAncestor:
13323 * @type: the simpleType definition
13324 *
13325 * Returns the primitive type of the given type or
13326 * NULL in case of error.
13327 */
13328static xmlSchemaTypePtr
13329xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13330{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013331 if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013332 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013333 while (type != NULL) {
13334 if (type->type == XML_SCHEMA_TYPE_BASIC)
13335 return (type);
13336 type = type->baseType;
13337 }
13338
13339 return (NULL);
13340}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013341#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013342
Daniel Veillard01fa6152004-06-29 17:04:39 +000013343/**
Daniel Veillard50355f02004-06-08 17:52:16 +000013344 * xmlSchemaCloneWildcardNsConstraints:
13345 * @ctxt: the schema parser context
13346 * @dest: the destination wildcard
13347 * @source: the source wildcard
13348 *
13349 * Clones the namespace constraints of source
13350 * and assignes them to dest.
13351 * Returns -1 on internal error, 0 otherwise.
13352 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013353static int
13354xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013355 xmlSchemaWildcardPtr dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013356 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000013357{
13358 xmlSchemaWildcardNsPtr cur, tmp, last;
13359
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013360 if ((source == NULL) || (dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013361 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013362 dest->any = source->any;
Daniel Veillard3646d642004-06-02 19:19:14 +000013363 cur = source->nsSet;
13364 last = NULL;
13365 while (cur != NULL) {
13366 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13367 if (tmp == NULL)
13368 return(-1);
13369 tmp->value = cur->value;
13370 if (last == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013371 dest->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013372 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013373 last->next = tmp;
13374 last = tmp;
13375 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013376 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013377 if (dest->negNsSet != NULL)
13378 xmlSchemaFreeWildcardNsSet(dest->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000013379 if (source->negNsSet != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013380 dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13381 if (dest->negNsSet == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013382 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013383 dest->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000013384 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013385 dest->negNsSet = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000013386 return(0);
13387}
13388
Daniel Veillard50355f02004-06-08 17:52:16 +000013389/**
13390 * xmlSchemaUnionWildcards:
13391 * @ctxt: the schema parser context
13392 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013393 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013394 *
13395 * Unions the namespace constraints of the given wildcards.
13396 * @completeWild will hold the resulting union.
13397 * Returns a positive error code on failure, -1 in case of an
13398 * internal error, 0 otherwise.
13399 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013400static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013401xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000013402 xmlSchemaWildcardPtr completeWild,
13403 xmlSchemaWildcardPtr curWild)
13404{
13405 xmlSchemaWildcardNsPtr cur, curB, tmp;
13406
13407 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013408 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013409 * value.
13410 */
13411 if ((completeWild->any == curWild->any) &&
13412 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13413 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013414
Daniel Veillard3646d642004-06-02 19:19:14 +000013415 if ((completeWild->negNsSet == NULL) ||
13416 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013417
Daniel Veillard3646d642004-06-02 19:19:14 +000013418 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000013419 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013420
13421 /*
13422 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000013423 */
13424 cur = completeWild->nsSet;
13425 while (cur != NULL) {
13426 found = 0;
13427 curB = curWild->nsSet;
13428 while (curB != NULL) {
13429 if (cur->value == curB->value) {
13430 found = 1;
13431 break;
13432 }
13433 curB = curB->next;
13434 }
13435 if (!found)
13436 break;
13437 cur = cur->next;
13438 }
13439 if (found)
13440 return(0);
13441 } else
13442 return(0);
13443 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013444 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013445 /*
13446 * 2 If either O1 or O2 is any, then any must be the value
13447 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013448 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013449 if (completeWild->any == 0) {
13450 completeWild->any = 1;
13451 if (completeWild->nsSet != NULL) {
13452 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13453 completeWild->nsSet = NULL;
13454 }
13455 if (completeWild->negNsSet != NULL) {
13456 xmlFree(completeWild->negNsSet);
13457 completeWild->negNsSet = NULL;
13458 }
13459 }
Daniel Veillard50355f02004-06-08 17:52:16 +000013460 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013461 }
13462 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013463 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000013464 * then the union of those sets must be the value.
13465 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013466 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013467 int found;
13468 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013469
Daniel Veillard3646d642004-06-02 19:19:14 +000013470 cur = curWild->nsSet;
13471 start = completeWild->nsSet;
13472 while (cur != NULL) {
13473 found = 0;
13474 curB = start;
13475 while (curB != NULL) {
13476 if (cur->value == curB->value) {
13477 found = 1;
13478 break;
13479 }
13480 curB = curB->next;
13481 }
13482 if (!found) {
13483 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013484 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013485 return (-1);
13486 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013487 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000013488 completeWild->nsSet = tmp;
13489 }
13490 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013491 }
13492
Daniel Veillard3646d642004-06-02 19:19:14 +000013493 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013494 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013495 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013496 * 4 If the two are negations of different values (namespace names
Daniel Veillard3646d642004-06-02 19:19:14 +000013497 * or ·absent·), then a pair of not and ·absent· must be the value.
13498 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013499 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013500 (curWild->negNsSet != NULL) &&
13501 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
13502 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000013503
13504 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013505 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013506 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013507 * 5.
13508 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013509 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013510 (completeWild->negNsSet->value != NULL) &&
13511 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013512 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013513 (curWild->negNsSet->value != NULL) &&
13514 (completeWild->nsSet != NULL))) {
13515
13516 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013517
Daniel Veillard3646d642004-06-02 19:19:14 +000013518 if (completeWild->nsSet != NULL) {
13519 cur = completeWild->nsSet;
13520 curB = curWild->negNsSet;
13521 } else {
13522 cur = curWild->nsSet;
13523 curB = completeWild->negNsSet;
13524 }
13525 nsFound = 0;
13526 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013527 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013528 absentFound = 1;
13529 else if (cur->value == curB->value)
13530 nsFound = 1;
13531 if (nsFound && absentFound)
13532 break;
13533 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013534 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013535
13536 if (nsFound && absentFound) {
13537 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013538 * 5.1 If the set S includes both the negated namespace
Daniel Veillard3646d642004-06-02 19:19:14 +000013539 * name and ·absent·, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013540 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013541 completeWild->any = 1;
13542 if (completeWild->nsSet != NULL) {
13543 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13544 completeWild->nsSet = NULL;
13545 }
13546 if (completeWild->negNsSet != NULL) {
13547 xmlFree(completeWild->negNsSet);
13548 completeWild->negNsSet = NULL;
13549 }
13550 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013551 /*
13552 * 5.2 If the set S includes the negated namespace name
13553 * but not ·absent·, then a pair of not and ·absent· must
Daniel Veillard3646d642004-06-02 19:19:14 +000013554 * be the value.
13555 */
13556 if (completeWild->nsSet != NULL) {
13557 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13558 completeWild->nsSet = NULL;
13559 }
13560 if (completeWild->negNsSet == NULL) {
13561 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13562 if (completeWild->negNsSet == NULL)
13563 return (-1);
13564 }
13565 completeWild->negNsSet->value = NULL;
13566 } else if ((!nsFound) && absentFound) {
13567 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013568 * 5.3 If the set S includes ·absent· but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000013569 * namespace name, then the union is not expressible.
13570 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013571 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000013572 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013573 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013574 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000013575 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000013576 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013577 /*
13578 * 5.4 If the set S does not include either the negated namespace
13579 * name or ·absent·, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000013580 * and a namespace name must be the value.
13581 */
13582 if (completeWild->negNsSet == NULL) {
13583 if (completeWild->nsSet != NULL) {
13584 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13585 completeWild->nsSet = NULL;
13586 }
13587 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13588 if (completeWild->negNsSet == NULL)
13589 return (-1);
13590 completeWild->negNsSet->value = curWild->negNsSet->value;
13591 }
13592 }
13593 return (0);
13594 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013595 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013596 * 6.
13597 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013598 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013599 (completeWild->negNsSet->value == NULL) &&
13600 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013601 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013602 (curWild->negNsSet->value == NULL) &&
13603 (completeWild->nsSet != NULL))) {
13604
13605 if (completeWild->nsSet != NULL) {
13606 cur = completeWild->nsSet;
13607 } else {
13608 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013609 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013610 while (cur != NULL) {
13611 if (cur->value == NULL) {
13612 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013613 * 6.1 If the set S includes ·absent·, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013614 * value.
13615 */
13616 completeWild->any = 1;
13617 if (completeWild->nsSet != NULL) {
13618 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13619 completeWild->nsSet = NULL;
13620 }
13621 if (completeWild->negNsSet != NULL) {
13622 xmlFree(completeWild->negNsSet);
13623 completeWild->negNsSet = NULL;
13624 }
13625 return (0);
13626 }
13627 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013628 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013629 if (completeWild->negNsSet == NULL) {
13630 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013631 * 6.2 If the set S does not include ·absent·, then a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000013632 * and ·absent· must be the value.
13633 */
13634 if (completeWild->nsSet != NULL) {
13635 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13636 completeWild->nsSet = NULL;
13637 }
13638 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13639 if (completeWild->negNsSet == NULL)
13640 return (-1);
13641 completeWild->negNsSet->value = NULL;
13642 }
13643 return (0);
13644 }
13645 return (0);
13646
13647}
13648
Daniel Veillard50355f02004-06-08 17:52:16 +000013649/**
13650 * xmlSchemaIntersectWildcards:
13651 * @ctxt: the schema parser context
13652 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013653 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013654 *
13655 * Intersects the namespace constraints of the given wildcards.
13656 * @completeWild will hold the resulting intersection.
13657 * Returns a positive error code on failure, -1 in case of an
13658 * internal error, 0 otherwise.
13659 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013660static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013661xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000013662 xmlSchemaWildcardPtr completeWild,
13663 xmlSchemaWildcardPtr curWild)
13664{
William M. Brack803812b2004-06-03 02:11:24 +000013665 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013666
13667 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013668 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013669 * value.
13670 */
13671 if ((completeWild->any == curWild->any) &&
13672 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13673 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013674
Daniel Veillard3646d642004-06-02 19:19:14 +000013675 if ((completeWild->negNsSet == NULL) ||
13676 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013677
Daniel Veillard3646d642004-06-02 19:19:14 +000013678 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000013679 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013680
13681 /*
13682 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000013683 */
13684 cur = completeWild->nsSet;
13685 while (cur != NULL) {
13686 found = 0;
13687 curB = curWild->nsSet;
13688 while (curB != NULL) {
13689 if (cur->value == curB->value) {
13690 found = 1;
13691 break;
13692 }
13693 curB = curB->next;
13694 }
13695 if (!found)
13696 break;
13697 cur = cur->next;
13698 }
13699 if (found)
13700 return(0);
13701 } else
13702 return(0);
13703 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013704 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013705 /*
13706 * 2 If either O1 or O2 is any, then the other must be the value.
13707 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013708 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013709 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013710 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000013711 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013712 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013713 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013714 * 3 If either O1 or O2 is a pair of not and a value (a namespace
13715 * name or ·absent·) and the other is a set of (namespace names or
13716 * ·absent·), then that set, minus the negated value if it was in
Daniel Veillard3646d642004-06-02 19:19:14 +000013717 * the set, minus ·absent· if it was in the set, must be the value.
13718 */
13719 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13720 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13721 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013722
Daniel Veillard3646d642004-06-02 19:19:14 +000013723 if (completeWild->nsSet == NULL) {
13724 neg = completeWild->negNsSet->value;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013725 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
Daniel Veillard3646d642004-06-02 19:19:14 +000013726 return(-1);
13727 } else
13728 neg = curWild->negNsSet->value;
13729 /*
13730 * Remove absent and negated.
13731 */
13732 prev = NULL;
13733 cur = completeWild->nsSet;
13734 while (cur != NULL) {
13735 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013736 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013737 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013738 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013739 prev->next = cur->next;
13740 xmlFree(cur);
13741 break;
13742 }
13743 prev = cur;
13744 cur = cur->next;
13745 }
13746 if (neg != NULL) {
13747 prev = NULL;
13748 cur = completeWild->nsSet;
13749 while (cur != NULL) {
13750 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013751 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013752 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013753 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013754 prev->next = cur->next;
13755 xmlFree(cur);
13756 break;
13757 }
13758 prev = cur;
13759 cur = cur->next;
13760 }
13761 }
13762
13763 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013764 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013765 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013766 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000013767 * then the intersection of those sets must be the value.
13768 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013769 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013770 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013771
Daniel Veillard3646d642004-06-02 19:19:14 +000013772 cur = completeWild->nsSet;
13773 prev = NULL;
13774 while (cur != NULL) {
13775 found = 0;
13776 curB = curWild->nsSet;
13777 while (curB != NULL) {
13778 if (cur->value == curB->value) {
13779 found = 1;
13780 break;
13781 }
13782 curB = curB->next;
13783 }
13784 if (!found) {
13785 if (prev == NULL)
13786 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013787 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013788 prev->next = cur->next;
13789 tmp = cur->next;
13790 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013791 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013792 continue;
13793 }
13794 prev = cur;
13795 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013796 }
13797
Daniel Veillard3646d642004-06-02 19:19:14 +000013798 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013799 }
13800 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000013801 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013802 */
13803 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013804 (curWild->negNsSet != NULL) &&
13805 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013806 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013807 (curWild->negNsSet->value != NULL)) {
13808
13809 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013810 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013811 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000013812 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013813 }
13814 /*
13815 * 6 If the one is a negation of a namespace name and the other
13816 * is a negation of ·absent·, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000013817 * of a namespace name must be the value.
13818 */
13819 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13820 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013821 (completeWild->negNsSet->value == NULL)) {
13822 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000013823 }
13824 return(0);
13825}
13826
Daniel Veillard50355f02004-06-08 17:52:16 +000013827/**
13828 * xmlSchemaIsWildcardNsConstraintSubset:
13829 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013830 * @sub: the first wildcard
13831 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013832 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013833 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13834 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013835 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013836 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000013837 */
13838static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013839xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13840 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013841{
Daniel Veillard50355f02004-06-08 17:52:16 +000013842 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013843 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000013844 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013845 if (super->any)
13846 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000013847 /*
13848 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
13849 * 2.2 super must be a pair of not and the same value.
13850 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013851 if ((sub->negNsSet != NULL) &&
13852 (super->negNsSet != NULL) &&
13853 (sub->negNsSet->value == sub->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013854 return (0);
13855 /*
13856 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
Daniel Veillard50355f02004-06-08 17:52:16 +000013857 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013858 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013859 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013860 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000013861 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013862 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013863 xmlSchemaWildcardNsPtr cur, curB;
13864 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013865
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013866 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000013867 while (cur != NULL) {
13868 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013869 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000013870 while (curB != NULL) {
13871 if (cur->value == curB->value) {
13872 found = 1;
13873 break;
13874 }
13875 curB = curB->next;
13876 }
13877 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013878 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013879 cur = cur->next;
13880 }
13881 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013882 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013883 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013884 xmlSchemaWildcardNsPtr cur;
13885 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013886 * 3.2.2 super must be a pair of not and a namespace name or
13887 * ·absent· and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000013888 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013889 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013890 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013891 if (cur->value == super->negNsSet->value)
13892 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013893 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013894 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013895 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000013896 }
13897 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013898 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013899}
13900
Daniel Veillard50355f02004-06-08 17:52:16 +000013901static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013902xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013903 int *fixed,
13904 const xmlChar **value,
13905 xmlSchemaValPtr *val)
13906{
13907 *fixed = 0;
13908 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013909 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013910 *val = NULL;
13911
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013912 if (attruse->defValue != NULL) {
13913 *value = attruse->defValue;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000013914 if (val != NULL)
13915 *val = attruse->defVal;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013916 if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013917 *fixed = 1;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013918 return(1);
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000013919 } else if ((attruse->attrDecl != NULL) &&
13920 (attruse->attrDecl->defValue != NULL)) {
13921 *value = attruse->attrDecl->defValue;
13922 if (val != NULL)
13923 *val = attruse->attrDecl->defVal;
13924 if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013925 *fixed = 1;
13926 return(1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013927 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013928 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013929}
Daniel Veillard3646d642004-06-02 19:19:14 +000013930/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013931 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000013932 * @wild: the wildcard
13933 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013934 *
13935 * Validation Rule: Wildcard allows Namespace Name
13936 * (cvc-wildcard-namespace)
13937 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013938 * Returns 0 if the given namespace matches the wildcard,
13939 * 1 otherwise and -1 on API errors.
Daniel Veillard3646d642004-06-02 19:19:14 +000013940 */
13941static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013942xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
13943 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000013944{
13945 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013946 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000013947
13948 if (wild->any)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013949 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013950 else if (wild->nsSet != NULL) {
13951 xmlSchemaWildcardNsPtr cur;
13952
13953 cur = wild->nsSet;
13954 while (cur != NULL) {
13955 if (xmlStrEqual(cur->value, ns))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013956 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013957 cur = cur->next;
13958 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013959 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013960 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013961 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013962
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013963 return(1);
13964}
13965
13966#define XML_SCHEMA_ACTION_DERIVE 0
13967#define XML_SCHEMA_ACTION_REDEFINE 1
13968
13969#define WXS_ACTION_STR(a) \
13970((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
13971
13972/*
13973* Schema Component Constraint:
13974* Derivation Valid (Restriction, Complex)
13975* derivation-ok-restriction (2) - (4)
13976*
13977* ATTENTION:
13978* In XML Schema 1.1 this will be:
13979* Validation Rule:
13980* Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
13981*
13982*/
13983static int
13984xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
13985 int action,
13986 xmlSchemaBasicItemPtr item,
13987 xmlSchemaBasicItemPtr baseItem,
13988 xmlSchemaItemListPtr uses,
13989 xmlSchemaItemListPtr baseUses,
13990 xmlSchemaWildcardPtr wild,
13991 xmlSchemaWildcardPtr baseWild)
13992{
13993 xmlSchemaAttributeUsePtr cur = NULL, bcur;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000013994 int i, j, found; /* err = 0; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013995 const xmlChar *bEffValue;
13996 int effFixed;
13997
13998 if (uses != NULL) {
13999 for (i = 0; i < uses->nbItems; i++) {
14000 cur = uses->items[i];
14001 found = 0;
14002 if (baseUses == NULL)
14003 goto not_found;
14004 for (j = 0; j < baseUses->nbItems; j++) {
14005 bcur = baseUses->items[j];
14006 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14007 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14008 (WXS_ATTRUSE_DECL_TNS(cur) ==
14009 WXS_ATTRUSE_DECL_TNS(bcur)))
14010 {
14011 /*
14012 * (2.1) "If there is an attribute use in the {attribute
14013 * uses} of the {base type definition} (call this B) whose
14014 * {attribute declaration} has the same {name} and {target
14015 * namespace}, then all of the following must be true:"
14016 */
14017 found = 1;
14018
14019 if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14020 (bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14021 {
14022 xmlChar *str = NULL;
14023 /*
14024 * (2.1.1) "one of the following must be true:"
14025 * (2.1.1.1) "B's {required} is false."
14026 * (2.1.1.2) "R's {required} is true."
14027 */
14028 xmlSchemaPAttrUseErr4(pctxt,
14029 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14030 WXS_ITEM_NODE(item), item, cur,
14031 "The 'optional' attribute use is inconsistent "
14032 "with the corresponding 'required' attribute use of "
14033 "the %s %s",
14034 WXS_ACTION_STR(action),
14035 xmlSchemaGetComponentDesignation(&str, baseItem),
14036 NULL, NULL);
14037 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014038 /* err = pctxt->err; */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014039 } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014040 WXS_ATTRUSE_TYPEDEF(cur),
14041 WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14042 {
14043 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14044
14045 /*
14046 * SPEC (2.1.2) "R's {attribute declaration}'s
14047 * {type definition} must be validly derived from
14048 * B's {type definition} given the empty set as
14049 * defined in Type Derivation OK (Simple) (§3.14.6)."
14050 */
14051 xmlSchemaPAttrUseErr4(pctxt,
14052 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14053 WXS_ITEM_NODE(item), item, cur,
14054 "The attribute declaration's %s "
14055 "is not validly derived from "
14056 "the corresponding %s of the "
14057 "attribute declaration in the %s %s",
14058 xmlSchemaGetComponentDesignation(&strA,
14059 WXS_ATTRUSE_TYPEDEF(cur)),
14060 xmlSchemaGetComponentDesignation(&strB,
14061 WXS_ATTRUSE_TYPEDEF(bcur)),
14062 WXS_ACTION_STR(action),
14063 xmlSchemaGetComponentDesignation(&strC, baseItem));
14064 /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14065 FREE_AND_NULL(strA);
14066 FREE_AND_NULL(strB);
14067 FREE_AND_NULL(strC);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014068 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014069 } else {
14070 /*
14071 * 2.1.3 [Definition:] Let the effective value
14072 * constraint of an attribute use be its {value
14073 * constraint}, if present, otherwise its {attribute
14074 * declaration}'s {value constraint} .
14075 */
14076 xmlSchemaGetEffectiveValueConstraint(bcur,
14077 &effFixed, &bEffValue, NULL);
14078 /*
14079 * 2.1.3 ... one of the following must be true
14080 *
14081 * 2.1.3.1 B's ·effective value constraint· is
14082 * ·absent· or default.
14083 */
14084 if ((bEffValue != NULL) &&
14085 (effFixed == 1)) {
14086 const xmlChar *rEffValue = NULL;
14087
14088 xmlSchemaGetEffectiveValueConstraint(bcur,
14089 &effFixed, &rEffValue, NULL);
14090 /*
14091 * 2.1.3.2 R's ·effective value constraint· is
14092 * fixed with the same string as B's.
14093 * MAYBE TODO: Compare the computed values.
14094 * Hmm, it says "same string" so
14095 * string-equality might really be sufficient.
14096 */
14097 if ((effFixed == 0) ||
14098 (! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14099 {
14100 xmlChar *str = NULL;
14101
14102 xmlSchemaPAttrUseErr4(pctxt,
14103 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14104 WXS_ITEM_NODE(item), item, cur,
14105 "The effective value constraint of the "
14106 "attribute use is inconsistent with "
14107 "its correspondent in the %s %s",
14108 WXS_ACTION_STR(action),
14109 xmlSchemaGetComponentDesignation(&str,
14110 baseItem),
14111 NULL, NULL);
14112 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014113 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014114 }
14115 }
14116 }
14117 break;
14118 }
14119 }
14120not_found:
14121 if (!found) {
14122 /*
14123 * (2.2) "otherwise the {base type definition} must have an
14124 * {attribute wildcard} and the {target namespace} of the
14125 * R's {attribute declaration} must be ·valid· with respect
14126 * to that wildcard, as defined in Wildcard allows Namespace
14127 * Name (§3.10.4)."
14128 */
14129 if ((baseWild == NULL) ||
14130 (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14131 (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14132 {
14133 xmlChar *str = NULL;
14134
14135 xmlSchemaPAttrUseErr4(pctxt,
14136 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14137 WXS_ITEM_NODE(item), item, cur,
14138 "Neither a matching attribute use, "
14139 "nor a matching wildcard exists in the %s %s",
14140 WXS_ACTION_STR(action),
14141 xmlSchemaGetComponentDesignation(&str, baseItem),
14142 NULL, NULL);
14143 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014144 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014145 }
14146 }
14147 }
14148 }
14149 /*
14150 * SPEC derivation-ok-restriction (3):
14151 * (3) "For each attribute use in the {attribute uses} of the {base type
14152 * definition} whose {required} is true, there must be an attribute
14153 * use with an {attribute declaration} with the same {name} and
14154 * {target namespace} as its {attribute declaration} in the {attribute
14155 * uses} of the complex type definition itself whose {required} is true.
14156 */
14157 if (baseUses != NULL) {
14158 for (j = 0; j < baseUses->nbItems; j++) {
14159 bcur = baseUses->items[j];
14160 if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14161 continue;
14162 found = 0;
14163 if (uses != NULL) {
14164 for (i = 0; i < uses->nbItems; i++) {
14165 cur = uses->items[i];
14166 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14167 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14168 (WXS_ATTRUSE_DECL_TNS(cur) ==
14169 WXS_ATTRUSE_DECL_TNS(bcur))) {
14170 found = 1;
14171 break;
14172 }
14173 }
14174 }
14175 if (!found) {
14176 xmlChar *strA = NULL, *strB = NULL;
14177
14178 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14179 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14180 NULL, item,
14181 "A matching attribute use for the "
14182 "'required' %s of the %s %s is missing",
14183 xmlSchemaGetComponentDesignation(&strA, bcur),
14184 WXS_ACTION_STR(action),
14185 xmlSchemaGetComponentDesignation(&strB, baseItem),
14186 NULL);
14187 FREE_AND_NULL(strA);
14188 FREE_AND_NULL(strB);
14189 }
14190 }
14191 }
14192 /*
14193 * derivation-ok-restriction (4)
14194 */
14195 if (wild != NULL) {
14196 /*
14197 * (4) "If there is an {attribute wildcard}, all of the
14198 * following must be true:"
14199 */
14200 if (baseWild == NULL) {
14201 xmlChar *str = NULL;
14202
14203 /*
14204 * (4.1) "The {base type definition} must also have one."
14205 */
14206 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14207 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14208 NULL, item,
14209 "The %s has an attribute wildcard, "
14210 "but the %s %s '%s' does not have one",
14211 WXS_ITEM_TYPE_NAME(item),
14212 WXS_ACTION_STR(action),
14213 WXS_ITEM_TYPE_NAME(baseItem),
14214 xmlSchemaGetComponentQName(&str, baseItem));
14215 FREE_AND_NULL(str);
14216 return(pctxt->err);
14217 } else if ((baseWild->any == 0) &&
14218 xmlSchemaCheckCOSNSSubset(wild, baseWild))
14219 {
14220 xmlChar *str = NULL;
14221 /*
14222 * (4.2) "The complex type definition's {attribute wildcard}'s
14223 * {namespace constraint} must be a subset of the {base type
14224 * definition}'s {attribute wildcard}'s {namespace constraint},
14225 * as defined by Wildcard Subset (§3.10.6)."
14226 */
14227 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14228 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14229 NULL, item,
14230 "The attribute wildcard is not a valid "
14231 "subset of the wildcard in the %s %s '%s'",
14232 WXS_ACTION_STR(action),
14233 WXS_ITEM_TYPE_NAME(baseItem),
14234 xmlSchemaGetComponentQName(&str, baseItem),
14235 NULL);
14236 FREE_AND_NULL(str);
14237 return(pctxt->err);
14238 }
14239 /* 4.3 Unless the {base type definition} is the ·ur-type
14240 * definition·, the complex type definition's {attribute
14241 * wildcard}'s {process contents} must be identical to or
14242 * stronger than the {base type definition}'s {attribute
14243 * wildcard}'s {process contents}, where strict is stronger
14244 * than lax is stronger than skip.
14245 */
14246 if ((! WXS_IS_ANYTYPE(baseItem)) &&
14247 (wild->processContents < baseWild->processContents)) {
14248 xmlChar *str = NULL;
14249 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14250 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14251 NULL, baseItem,
14252 "The {process contents} of the attribute wildcard is "
14253 "weaker than the one in the %s %s '%s'",
14254 WXS_ACTION_STR(action),
14255 WXS_ITEM_TYPE_NAME(baseItem),
14256 xmlSchemaGetComponentQName(&str, baseItem),
14257 NULL);
14258 FREE_AND_NULL(str)
14259 return(pctxt->err);
14260 }
14261 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014262 return(0);
14263}
14264
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014265
14266static int
14267xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14268 xmlSchemaBasicItemPtr item,
14269 xmlSchemaWildcardPtr *completeWild,
14270 xmlSchemaItemListPtr list,
14271 xmlSchemaItemListPtr prohibs);
Daniel Veillard3646d642004-06-02 19:19:14 +000014272/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014273 * xmlSchemaFixupTypeAttributeUses:
Daniel Veillard3646d642004-06-02 19:19:14 +000014274 * @ctxt: the schema parser context
14275 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014276 *
Daniel Veillard3646d642004-06-02 19:19:14 +000014277 *
14278 * Builds the wildcard and the attribute uses on the given complex type.
14279 * Returns -1 if an internal error occurs, 0 otherwise.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014280 *
14281 * ATTENTION TODO: Experimantally this uses pointer comparisons for
14282 * strings, so recheck this if we start to hardcode some schemata, since
14283 * they might not be in the same dict.
14284 * NOTE: It is allowed to "extend" the xs:anyType type.
Daniel Veillard3646d642004-06-02 19:19:14 +000014285 */
14286static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014287xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014288 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000014289{
14290 xmlSchemaTypePtr baseType = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014291 xmlSchemaAttributeUsePtr use;
14292 xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000014293
Daniel Veillard01fa6152004-06-29 17:04:39 +000014294 if (type->baseType == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014295 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014296 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014297 return (-1);
14298 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014299 baseType = type->baseType;
14300 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014301 if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014302 return(-1);
14303
14304 uses = type->attrUses;
14305 baseUses = baseType->attrUses;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014306 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014307 * Expand attribute group references. And build the 'complete'
14308 * wildcard, i.e. intersect multiple wildcards.
14309 * Move attribute prohibitions into a separate list.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014310 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014311 if (uses != NULL) {
14312 if (WXS_IS_RESTRICTION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014313 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014314 * This one will transfer all attr. prohibitions
14315 * into pctxt->attrProhibs.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014316 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014317 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14318 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14319 pctxt->attrProhibs) == -1)
14320 {
14321 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14322 "failed to expand attributes");
14323 }
14324 if (pctxt->attrProhibs->nbItems != 0)
14325 prohibs = pctxt->attrProhibs;
14326 } else {
14327 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14328 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14329 NULL) == -1)
14330 {
14331 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14332 "failed to expand attributes");
14333 }
14334 }
14335 }
14336 /*
14337 * Inherit the attribute uses of the base type.
14338 */
14339 if (baseUses != NULL) {
14340 int i, j;
14341 xmlSchemaAttributeUseProhibPtr pro;
14342
14343 if (WXS_IS_RESTRICTION(type)) {
14344 int usesCount;
14345 xmlSchemaAttributeUsePtr tmp;
14346
14347 if (uses != NULL)
14348 usesCount = uses->nbItems;
14349 else
14350 usesCount = 0;
14351
14352 /* Restriction. */
14353 for (i = 0; i < baseUses->nbItems; i++) {
14354 use = baseUses->items[i];
14355 if (prohibs) {
14356 /*
14357 * Filter out prohibited uses.
14358 */
14359 for (j = 0; j < prohibs->nbItems; j++) {
14360 pro = prohibs->items[j];
14361 if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14362 (WXS_ATTRUSE_DECL_TNS(use) ==
14363 pro->targetNamespace))
14364 {
14365 goto inherit_next;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014366 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014367 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014368 }
14369 if (usesCount) {
14370 /*
14371 * Filter out existing uses.
14372 */
14373 for (j = 0; j < usesCount; j++) {
14374 tmp = uses->items[j];
14375 if ((WXS_ATTRUSE_DECL_NAME(use) ==
14376 WXS_ATTRUSE_DECL_NAME(tmp)) &&
14377 (WXS_ATTRUSE_DECL_TNS(use) ==
14378 WXS_ATTRUSE_DECL_TNS(tmp)))
14379 {
14380 goto inherit_next;
14381 }
14382 }
14383 }
14384 if (uses == NULL) {
14385 type->attrUses = xmlSchemaItemListCreate();
14386 if (type->attrUses == NULL)
14387 goto exit_failure;
14388 uses = type->attrUses;
14389 }
14390 xmlSchemaItemListAddSize(uses, 2, use);
14391inherit_next: {}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014392 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014393 } else {
14394 /* Extension. */
14395 for (i = 0; i < baseUses->nbItems; i++) {
14396 use = baseUses->items[i];
14397 if (uses == NULL) {
14398 type->attrUses = xmlSchemaItemListCreate();
14399 if (type->attrUses == NULL)
14400 goto exit_failure;
14401 uses = type->attrUses;
14402 }
14403 xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14404 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014405 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014406 }
14407 /*
14408 * Shrink attr. uses.
14409 */
14410 if (uses) {
14411 if (uses->nbItems == 0) {
14412 xmlSchemaItemListFree(uses);
14413 type->attrUses = NULL;
14414 }
14415 /*
14416 * TODO: We could shrink the size of the array
14417 * to fit the actual number of items.
14418 */
14419 }
14420 /*
14421 * Compute the complete wildcard.
14422 */
14423 if (WXS_IS_EXTENSION(type)) {
14424 if (baseType->attributeWildcard != NULL) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014425 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014426 * (3.2.2.1) "If the ·base wildcard· is non-·absent·, then
14427 * the appropriate case among the following:"
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014428 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014429 if (type->attributeWildcard != NULL) {
14430 /*
14431 * Union the complete wildcard with the base wildcard.
14432 * SPEC {attribute wildcard}
14433 * (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14434 * and {annotation} are those of the ·complete wildcard·,
14435 * and whose {namespace constraint} is the intensional union
14436 * of the {namespace constraint} of the ·complete wildcard·
14437 * and of the ·base wildcard·, as defined in Attribute
14438 * Wildcard Union (§3.10.6)."
14439 */
14440 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14441 baseType->attributeWildcard) == -1)
14442 goto exit_failure;
14443 } else {
14444 /*
14445 * (3.2.2.1.1) "If the ·complete wildcard· is ·absent·,
14446 * then the ·base wildcard·."
14447 */
14448 type->attributeWildcard = baseType->attributeWildcard;
14449 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014450 } else {
14451 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014452 * (3.2.2.2) "otherwise (the ·base wildcard· is ·absent·) the
14453 * ·complete wildcard"
14454 * NOOP
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014455 */
Daniel Veillard50355f02004-06-08 17:52:16 +000014456 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014457 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014458 /*
14459 * SPEC {attribute wildcard}
14460 * (3.1) "If the <restriction> alternative is chosen, then the
14461 * ·complete wildcard·;"
14462 * NOOP
14463 */
Daniel Veillard50355f02004-06-08 17:52:16 +000014464 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014465
Daniel Veillard3646d642004-06-02 19:19:14 +000014466 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014467
14468exit_failure:
14469 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000014470}
14471
14472/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000014473 * xmlSchemaTypeFinalContains:
14474 * @schema: the schema
14475 * @type: the type definition
14476 * @final: the final
14477 *
14478 * Evaluates if a type definition contains the given "final".
14479 * This does take "finalDefault" into account as well.
14480 *
14481 * Returns 1 if the type does containt the given "final",
14482 * 0 otherwise.
14483 */
14484static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014485xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014486{
Daniel Veillard01fa6152004-06-29 17:04:39 +000014487 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014488 return (0);
14489 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014490 return (1);
14491 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014492 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014493}
14494
14495/**
14496 * xmlSchemaGetUnionSimpleTypeMemberTypes:
14497 * @type: the Union Simple Type
14498 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014499 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014500 * returns NULL otherwise.
14501 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014502static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000014503xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14504{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014505 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014506 if (type->memberTypes != NULL)
14507 return (type->memberTypes);
14508 else
14509 type = type->baseType;
14510 }
14511 return (NULL);
14512}
14513
14514/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014515 * xmlSchemaGetParticleTotalRangeMin:
14516 * @particle: the particle
14517 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014518 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014519 * (all and sequence) + (choice)
14520 *
14521 * Returns the minimun Effective Total Range.
14522 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014523static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014524xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014525{
14526 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014527 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014528 return (0);
14529 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014530 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014531 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014532 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014533
14534 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014535 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014536 while (part != NULL) {
14537 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14538 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014539 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014540 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014541 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014542 if (cur == 0)
14543 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014544 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014545 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014546 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014547 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014548 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014549 } else {
14550 /* <all> and <sequence> */
14551 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014552 xmlSchemaParticlePtr part =
14553 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014554
14555 if (part == NULL)
14556 return (0);
14557 do {
14558 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14559 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014560 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014561 else
14562 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014563 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014564 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014565 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014566 }
14567}
14568
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014569/**
14570 * xmlSchemaGetParticleTotalRangeMax:
14571 * @particle: the particle
14572 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014573 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014574 * (all and sequence) + (choice)
14575 *
14576 * Returns the maximum Effective Total Range.
14577 */
14578static int
14579xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14580{
14581 if ((particle->children == NULL) ||
14582 (particle->children->children == NULL))
14583 return (0);
14584 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14585 int max = -1, cur;
14586 xmlSchemaParticlePtr part =
14587 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014588
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014589 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14590 if (part->children == NULL)
14591 continue;
14592 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14593 (part->children->type == XML_SCHEMA_TYPE_ANY))
14594 cur = part->maxOccurs;
14595 else
14596 cur = xmlSchemaGetParticleTotalRangeMax(part);
14597 if (cur == UNBOUNDED)
14598 return (UNBOUNDED);
14599 if ((max < cur) || (max == -1))
14600 max = cur;
14601 }
14602 /* TODO: Handle overflows? */
14603 return (particle->maxOccurs * max);
14604 } else {
14605 /* <all> and <sequence> */
14606 int sum = 0, cur;
14607 xmlSchemaParticlePtr part =
14608 (xmlSchemaParticlePtr) particle->children->children;
14609
14610 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14611 if (part->children == NULL)
14612 continue;
14613 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14614 (part->children->type == XML_SCHEMA_TYPE_ANY))
14615 cur = part->maxOccurs;
14616 else
14617 cur = xmlSchemaGetParticleTotalRangeMax(part);
14618 if (cur == UNBOUNDED)
14619 return (UNBOUNDED);
14620 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14621 return (UNBOUNDED);
14622 sum += cur;
14623 }
14624 /* TODO: Handle overflows? */
14625 return (particle->maxOccurs * sum);
14626 }
14627}
14628
14629/**
14630 * xmlSchemaIsParticleEmptiable:
14631 * @particle: the particle
14632 *
14633 * Schema Component Constraint: Particle Emptiable
14634 * Checks whether the given particle is emptiable.
14635 *
14636 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014637 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014638static int
14639xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14640{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014641 /*
14642 * SPEC (1) "Its {min occurs} is 0."
14643 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014644 if ((particle == NULL) || (particle->minOccurs == 0) ||
14645 (particle->children == NULL))
14646 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014647 /*
14648 * SPEC (2) "Its {term} is a group and the minimum part of the
14649 * effective total range of that group, [...] is 0."
14650 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014651 if (WXS_IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014652 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014653 return (1);
14654 }
14655 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014656}
14657
14658/**
14659 * xmlSchemaCheckCOSSTDerivedOK:
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014660 * @actxt: a context
Daniel Veillard01fa6152004-06-29 17:04:39 +000014661 * @type: the derived simple type definition
14662 * @baseType: the base type definition
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014663 * @subset: the subset of ('restriction', ect.)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014664 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014665 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014666 * Type Derivation OK (Simple) (cos-st-derived-OK)
14667 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014668 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000014669 * derived from @baseType.
14670 *
14671 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014672 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014673static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014674xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014675 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014676 xmlSchemaTypePtr baseType,
14677 int subset)
14678{
Daniel Veillard01fa6152004-06-29 17:04:39 +000014679 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014680 * 1 They are the same type definition.
14681 * TODO: The identy check might have to be more complex than this.
14682 */
14683 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014684 return (0);
14685 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014686 * 2.1 restriction is not in the subset, or in the {final}
14687 * of its own {base type definition};
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014688 *
14689 * NOTE that this will be used also via "xsi:type".
14690 *
14691 * TODO: Revise this, it looks strange. How can the "type"
14692 * not be fixed or *in* fixing?
Daniel Veillard01fa6152004-06-29 17:04:39 +000014693 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014694 if (WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014695 if (xmlSchemaTypeFixup(type, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014696 return(-1);
14697 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014698 if (xmlSchemaTypeFixup(baseType, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014699 return(-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014700 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014701 (xmlSchemaTypeFinalContains(type->baseType,
14702 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14703 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014704 }
14705 /* 2.2 */
14706 if (type->baseType == baseType) {
14707 /*
14708 * 2.2.1 D's ·base type definition· is B.
14709 */
14710 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014711 }
14712 /*
14713 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
14714 * and is validly derived from B given the subset, as defined by this
14715 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014716 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014717 if ((! WXS_IS_ANYTYPE(type->baseType)) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014718 (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014719 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014720 return (0);
14721 }
14722 /*
14723 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
Daniel Veillard01fa6152004-06-29 17:04:39 +000014724 * definition·.
14725 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014726 if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14727 (WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014728 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014729 }
14730 /*
14731 * 2.2.4 B's {variety} is union and D is validly derived from a type
14732 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000014733 * defined by this constraint.
14734 *
14735 * NOTE: This seems not to involve built-in types, since there is no
14736 * built-in Union Simple Type.
14737 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014738 if (WXS_IS_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014739 xmlSchemaTypeLinkPtr cur;
14740
14741 cur = baseType->memberTypes;
14742 while (cur != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014743 if (WXS_IS_TYPE_NOT_FIXED(cur->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014744 if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014745 return(-1);
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014746 if (xmlSchemaCheckCOSSTDerivedOK(actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014747 type, cur->type, subset) == 0)
14748 {
14749 /*
14750 * It just has to be validly derived from at least one
14751 * member-type.
14752 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014753 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014754 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014755 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014756 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014757 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014758 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14759}
14760
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014761/**
14762 * xmlSchemaCheckTypeDefCircularInternal:
14763 * @pctxt: the schema parser context
14764 * @ctxtType: the type definition
14765 * @ancestor: an ancestor of @ctxtType
14766 *
14767 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014768 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014769 *
14770 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14771 * circular, 0 otherwise.
14772 */
14773static int
14774xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14775 xmlSchemaTypePtr ctxtType,
14776 xmlSchemaTypePtr ancestor)
14777{
14778 int ret;
14779
14780 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14781 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014782
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014783 if (ctxtType == ancestor) {
14784 xmlSchemaPCustomErr(pctxt,
14785 XML_SCHEMAP_ST_PROPS_CORRECT_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014786 WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014787 "The definition is circular", NULL);
14788 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14789 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014790 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14791 /*
14792 * Avoid inifinite recursion on circular types not yet checked.
14793 */
14794 return (0);
14795 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014796 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14797 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14798 ancestor->baseType);
14799 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14800 return (ret);
14801}
14802
14803/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014804 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014805 * @item: the complex/simple type definition
14806 * @ctxt: the parser context
14807 * @name: the name
14808 *
14809 * Checks for circular type definitions.
14810 */
14811static void
14812xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014813 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014814{
14815 if ((item == NULL) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014816 (item->type == XML_SCHEMA_TYPE_BASIC) ||
14817 (item->baseType == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014818 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014819 xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14820 item->baseType);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014821}
Daniel Veillard01fa6152004-06-29 17:04:39 +000014822
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014823/*
14824* Simple Type Definition Representation OK (src-simple-type) 4
14825*
14826* "4 Circular union type definition is disallowed. That is, if the
14827* <union> alternative is chosen, there must not be any entries in the
14828* memberTypes [attribute] at any depth which resolve to the component
14829* corresponding to the <simpleType>."
14830*
14831* Note that this should work on the *representation* of a component,
14832* thus assumes any union types in the member types not being yet
14833* substituted. At this stage we need the variety of the types
14834* to be already computed.
14835*/
14836static int
14837xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14838 xmlSchemaTypePtr ctxType,
14839 xmlSchemaTypeLinkPtr members)
14840{
14841 xmlSchemaTypeLinkPtr member;
14842 xmlSchemaTypePtr memberType;
14843
14844 member = members;
14845 while (member != NULL) {
14846 memberType = member->type;
14847 while ((memberType != NULL) &&
14848 (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14849 if (memberType == ctxType) {
14850 xmlSchemaPCustomErr(pctxt,
14851 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014852 WXS_BASIC_CAST ctxType, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014853 "The union type definition is circular", NULL);
14854 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14855 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014856 if ((WXS_IS_UNION(memberType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014857 ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14858 {
14859 int res;
14860 memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14861 res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
14862 ctxType,
14863 xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
14864 memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
14865 if (res != 0)
14866 return(res);
14867 }
14868 memberType = memberType->baseType;
14869 }
14870 member = member->next;
14871 }
14872 return(0);
14873}
14874
14875static int
14876xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
14877 xmlSchemaTypePtr type)
14878{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014879 if (! WXS_IS_UNION(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014880 return(0);
14881 return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
14882 type->memberTypes));
14883}
14884
Daniel Veillard01fa6152004-06-29 17:04:39 +000014885/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014886 * xmlSchemaResolveTypeReferences:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014887 * @item: the complex/simple type definition
14888 * @ctxt: the parser context
14889 * @name: the name
14890 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014891 * Resolvese type definition references
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014892 */
14893static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014894xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014895 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014896{
14897 if (typeDef == NULL)
14898 return;
14899
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014900 /*
14901 * Resolve the base type.
14902 */
14903 if (typeDef->baseType == NULL) {
14904 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
14905 typeDef->base, typeDef->baseNs);
14906 if (typeDef->baseType == NULL) {
14907 xmlSchemaPResCompAttrErr(ctxt,
14908 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014909 WXS_BASIC_CAST typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014910 "base", typeDef->base, typeDef->baseNs,
14911 XML_SCHEMA_TYPE_SIMPLE, NULL);
14912 return;
14913 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014914 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014915 if (WXS_IS_SIMPLE(typeDef)) {
14916 if (WXS_IS_UNION(typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014917 /*
14918 * Resolve the memberTypes.
14919 */
14920 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
14921 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014922 } else if (WXS_IS_LIST(typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014923 /*
14924 * Resolve the itemType.
14925 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014926 if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
14927
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014928 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014929 typeDef->base, typeDef->baseNs);
14930
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014931 if ((typeDef->subtypes == NULL) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014932 (! WXS_IS_SIMPLE(typeDef->subtypes)))
14933 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014934 typeDef->subtypes = NULL;
14935 xmlSchemaPResCompAttrErr(ctxt,
14936 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014937 WXS_BASIC_CAST typeDef, typeDef->node,
14938 "itemType", typeDef->base, typeDef->baseNs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014939 XML_SCHEMA_TYPE_SIMPLE, NULL);
14940 }
14941 }
14942 return;
14943 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014944 }
14945 /*
14946 * The ball of letters below means, that if we have a particle
14947 * which has a QName-helper component as its {term}, we want
14948 * to resolve it...
14949 */
14950 else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
14951 ((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
14952 XML_SCHEMA_TYPE_PARTICLE) &&
14953 (WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
14954 ((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
14955 XML_SCHEMA_EXTRA_QNAMEREF))
14956 {
14957 xmlSchemaQNameRefPtr ref =
14958 WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
14959 xmlSchemaModelGroupDefPtr groupDef;
14960
14961 /*
14962 * URGENT TODO: Test this.
14963 */
14964 WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
14965 /*
14966 * Resolve the MG definition reference.
14967 */
14968 groupDef =
14969 WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
14970 ref->itemType, ref->name, ref->targetNamespace);
14971 if (groupDef == NULL) {
14972 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
14973 NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
14974 "ref", ref->name, ref->targetNamespace, ref->itemType,
14975 NULL);
14976 /* Remove the particle. */
14977 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
14978 } else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
14979 /* Remove the particle. */
14980 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
14981 else {
14982 /*
14983 * Assign the MG definition's {model group} to the
14984 * particle's {term}.
14985 */
14986 WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
14987
14988 if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
14989 /*
14990 * SPEC cos-all-limited (1.2)
14991 * "1.2 the {term} property of a particle with
14992 * {max occurs}=1 which is part of a pair which constitutes
14993 * the {content type} of a complex type definition."
14994 */
14995 if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
14996 xmlSchemaCustomErr(ACTXT_CAST ctxt,
14997 /* TODO: error code */
14998 XML_SCHEMAP_COS_ALL_LIMITED,
14999 WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15000 "The particle's {max occurs} must be 1, since the "
15001 "reference resolves to an 'all' model group",
15002 NULL, NULL);
15003 }
15004 }
15005 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015006 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015007}
15008
15009
15010
15011/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000015012 * xmlSchemaCheckSTPropsCorrect:
15013 * @ctxt: the schema parser context
15014 * @type: the simple type definition
15015 *
15016 * Checks st-props-correct.
15017 *
15018 * Returns 0 if the properties are correct,
15019 * if not, a positive error code and -1 on internal
15020 * errors.
15021 */
15022static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015023xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015024 xmlSchemaTypePtr type)
15025{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015026 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015027 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015028
Daniel Veillardc0826a72004-08-10 14:17:33 +000015029 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015030 /*
15031 * Schema Component Constraint: Simple Type Definition Properties Correct
15032 *
15033 * NOTE: This is somehow redundant, since we actually built a simple type
15034 * to have all the needed information; this acts as an self test.
15035 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015036 /* Base type: If the datatype has been ·derived· by ·restriction·
15037 * then the Simple Type Definition component from which it is ·derived·,
15038 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000015039 */
15040 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015041 /*
15042 * TODO: Think about: "modulo the impact of Missing
15043 * Sub-components (§5.3)."
15044 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015045 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015046 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015047 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015048 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015049 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015050
Daniel Veillard01fa6152004-06-29 17:04:39 +000015051 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015052 if (! WXS_IS_SIMPLE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015053 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015054 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015055 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015056 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015057 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015058 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015059 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15060 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015061 if ( (WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015062 (WXS_IS_RESTRICTION(type) == 0) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015063 (! WXS_IS_ANY_SIMPLE_TYPE(baseType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015064 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015065 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015066 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015067 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015068 "the simple ur-type definition as base type, not '%s'",
15069 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015070 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015071 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15072 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015073 /*
15074 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015075 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015076 if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15077 (! WXS_IS_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015078 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015079 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015080 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015081 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015082 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15083 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015084 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015085
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015086 /*
15087 * 3 The {final} of the {base type definition} must not contain restriction.
15088 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015089 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015090 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15091 xmlSchemaPCustomErr(ctxt,
15092 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015093 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015094 "The 'final' of its base type '%s' must not contain "
15095 "'restriction'",
15096 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015097 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015098 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015099 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015100
15101 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015102 * 2 All simple type definitions must be derived ultimately from the ·simple
15103 * ur-type definition (so· circular definitions are disallowed). That is, it
15104 * must be possible to reach a built-in primitive datatype or the ·simple
15105 * ur-type definition· by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015106 *
15107 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000015108 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015109 return (0);
15110}
15111
15112/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015113 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000015114 * @ctxt: the schema parser context
15115 * @type: the simple type definition
15116 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015117 * Schema Component Constraint:
15118 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15119
15120 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015121 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000015122 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015123 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015124 * a positive error code otherwise.
15125 */
15126static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015127xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015128 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015129{
Daniel Veillardc0826a72004-08-10 14:17:33 +000015130 xmlChar *str = NULL;
15131
Daniel Veillard01fa6152004-06-29 17:04:39 +000015132 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015133 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15134 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015135 return (-1);
15136 }
15137
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015138 if (WXS_IS_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015139 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015140 /*
15141 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000015142 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015143 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015144 if (! WXS_IS_ATOMIC(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015145 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015146 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015147 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015148 "The base type '%s' is not an atomic simple type",
15149 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015150 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015151 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15152 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015153 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000015154 * restriction.
15155 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015156 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015157 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015158 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015159 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015160 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015161 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015162 "The final of its base type '%s' must not contain 'restriction'",
15163 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015164 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015165 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15166 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015167
15168 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000015169 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015170 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000015171 * Primitive datatypes.
15172 */
15173 if (type->facets != NULL) {
15174 xmlSchemaFacetPtr facet;
15175 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015176
Daniel Veillard01fa6152004-06-29 17:04:39 +000015177 primitive = xmlSchemaGetPrimitiveType(type);
15178 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015179 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15180 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015181 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015182 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015183 facet = type->facets;
15184 do {
15185 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015186 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015187 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015188 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015189 type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015190 }
15191 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015192 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015193 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015194 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015195 }
15196 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015197 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15198 * of the {base type definition} (call this BF),then the DF's {value}
15199 * must be a valid restriction of BF's {value} as defined in
15200 * [XML Schemas: Datatypes]."
15201 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015202 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015203 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015204 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015205 } else if (WXS_IS_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015206 xmlSchemaTypePtr itemType = NULL;
15207
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015208 itemType = type->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015209 if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015210 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15211 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015212 return (-1);
15213 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015214 if (WXS_IS_TYPE_NOT_FIXED(itemType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015215 xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015216 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015217 * 2.1 The {item type definition} must have a {variety} of atomic or
15218 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000015219 * must be atomic).
15220 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015221 if ((! WXS_IS_ATOMIC(itemType)) &&
15222 (! WXS_IS_UNION(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015223 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015224 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015225 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015226 "The item type '%s' does not have a variety of atomic or union",
15227 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015228 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015229 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015230 } else if (WXS_IS_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015231 xmlSchemaTypeLinkPtr member;
15232
15233 member = itemType->memberTypes;
15234 while (member != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015235 if (! WXS_IS_ATOMIC(member->type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015236 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015237 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015238 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015239 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015240 "member type '%s' of this item type is not atomic",
15241 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015242 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015243 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15244 }
15245 member = member->next;
15246 }
15247 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015248
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015249 if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015250 xmlSchemaFacetPtr facet;
15251 /*
15252 * This is the case if we have: <simpleType><list ..
15253 */
15254 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015255 * 2.3.1
15256 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000015257 * contain list.
15258 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015259 if (xmlSchemaTypeFinalContains(itemType,
15260 XML_SCHEMAS_TYPE_FINAL_LIST)) {
15261 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015262 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015263 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015264 "The final of its item type '%s' must not contain 'list'",
15265 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015266 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015267 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15268 }
15269 /*
15270 * 2.3.1.2 The {facets} must only contain the whiteSpace
15271 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015272 * OPTIMIZE TODO: the S4S already disallows any facet
15273 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015274 */
15275 if (type->facets != NULL) {
15276 facet = type->facets;
15277 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015278 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015279 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015280 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015281 type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015282 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15283 }
15284 facet = facet->next;
15285 } while (facet != NULL);
15286 }
15287 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015288 * MAYBE TODO: (Hmm, not really) Datatypes states:
15289 * A ·list· datatype can be ·derived· from an ·atomic· datatype
15290 * whose ·lexical space· allows space (such as string or anyURI)or
15291 * a ·union· datatype any of whose {member type definitions}'s
Daniel Veillard01fa6152004-06-29 17:04:39 +000015292 * ·lexical space· allows space.
15293 */
15294 } else {
15295 /*
15296 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015297 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015298 */
15299 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015300 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000015301 * 2.3.2.1 The {base type definition} must have a {variety} of list.
15302 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015303 if (! WXS_IS_LIST(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015304 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015305 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015306 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015307 "The base type '%s' must be a list type",
15308 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015309 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015310 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15311 }
15312 /*
15313 * 2.3.2.2 The {final} of the {base type definition} must not
15314 * contain restriction.
15315 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015316 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015317 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015318 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015319 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015320 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015321 "The 'final' of the base type '%s' must not contain 'restriction'",
15322 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015323 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015324 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15325 }
15326 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015327 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000015328 * from the {base type definition}'s {item type definition} given
15329 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
15330 */
15331 {
15332 xmlSchemaTypePtr baseItemType;
15333
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015334 baseItemType = type->baseType->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015335 if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015336 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15337 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015338 return (-1);
15339 }
15340 if ((itemType != baseItemType) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015341 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015342 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015343 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015344 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015345 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015346 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015347 "The item type '%s' is not validly derived from "
15348 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015349 xmlSchemaGetComponentQName(&str, itemType),
15350 xmlSchemaGetComponentQName(&strBIT, baseItemType),
15351 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015352
15353 FREE_AND_NULL(str)
15354 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015355 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015356 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15357 }
15358 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015359
Daniel Veillard01fa6152004-06-29 17:04:39 +000015360 if (type->facets != NULL) {
15361 xmlSchemaFacetPtr facet;
15362 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015363 /*
15364 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000015365 * and enumeration facet components are allowed among the {facets}.
15366 */
15367 facet = type->facets;
15368 do {
15369 switch (facet->type) {
15370 case XML_SCHEMA_FACET_LENGTH:
15371 case XML_SCHEMA_FACET_MINLENGTH:
15372 case XML_SCHEMA_FACET_MAXLENGTH:
15373 case XML_SCHEMA_FACET_WHITESPACE:
15374 /*
15375 * TODO: 2.5.1.2 List datatypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015376 * The value of ·whiteSpace· is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015377 */
15378 case XML_SCHEMA_FACET_PATTERN:
15379 case XML_SCHEMA_FACET_ENUMERATION:
15380 break;
15381 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015382 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015383 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015384 type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015385 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015386 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000015387 * invalid facets.
15388 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015389 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015390 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015391 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015392 facet = facet->next;
15393 } while (facet != NULL);
15394 if (ok == 0)
15395 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15396 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015397 * SPEC (2.3.2.5) (same as 1.3.2)
15398 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015399 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015400 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015401 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015402 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015403 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015404 } else if (WXS_IS_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015405 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015406 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000015407 * atomic or list.
15408 */
15409 xmlSchemaTypeLinkPtr member;
15410
15411 member = type->memberTypes;
15412 while (member != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015413 if (WXS_IS_TYPE_NOT_FIXED(member->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015414 xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015415
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015416 if ((! WXS_IS_ATOMIC(member->type)) &&
15417 (! WXS_IS_LIST(member->type))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015418 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015419 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015420 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015421 "The member type '%s' is neither an atomic, nor a list type",
15422 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015423 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015424 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15425 }
15426 member = member->next;
15427 }
15428 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015429 * 3.3.1 If the {base type definition} is the ·simple ur-type
15430 * definition·
Daniel Veillard01fa6152004-06-29 17:04:39 +000015431 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015432 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015433 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015434 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000015435 * {final} which does not contain union.
15436 */
15437 member = type->memberTypes;
15438 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015439 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015440 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015441 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015442 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015443 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015444 "The 'final' of member type '%s' contains 'union'",
15445 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015446 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015447 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15448 }
15449 member = member->next;
15450 }
15451 /*
15452 * 3.3.1.2 The {facets} must be empty.
15453 */
15454 if (type->facetSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015455 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015456 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015457 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015458 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015459 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15460 }
15461 } else {
15462 /*
15463 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015464 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015465 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015466 if (! WXS_IS_UNION(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015467 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015468 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015469 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015470 "The base type '%s' is not a union type",
15471 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015472 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015473 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15474 }
15475 /*
15476 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15477 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015478 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015479 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015480 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015481 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015482 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015483 "The 'final' of its base type '%s' must not contain 'restriction'",
15484 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015485 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015486 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15487 }
15488 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015489 * 3.3.2.3 The {member type definitions}, in order, must be validly
15490 * derived from the corresponding type definitions in the {base
15491 * type definition}'s {member type definitions} given the empty set,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015492 * as defined in Type Derivation OK (Simple) (§3.14.6).
15493 */
15494 {
15495 xmlSchemaTypeLinkPtr baseMember;
15496
15497 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015498 * OPTIMIZE: if the type is restricting, it has no local defined
15499 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015500 * thus a check for equality can be skipped.
15501 */
15502 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015503 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015504 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000015505 * types of it's base type. This check seems not necessary with
15506 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015507 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015508 */
15509 if (type->memberTypes != NULL) {
15510 member = type->memberTypes;
15511 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015512 if ((member == NULL) && (baseMember != NULL)) {
15513 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15514 "different number of member types in base");
15515 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015516 while (member != NULL) {
15517 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015518 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15519 "different number of member types in base");
Daniel Veillard14b56432006-03-09 18:41:40 +000015520 } else if ((member->type != baseMember->type) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015521 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015522 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015523 xmlChar *strBMT = NULL, *strBT = NULL;
15524
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015525 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015526 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015527 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015528 "The member type %s is not validly "
15529 "derived from its corresponding member "
15530 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015531 xmlSchemaGetComponentQName(&str, member->type),
15532 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15533 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015534 FREE_AND_NULL(str)
15535 FREE_AND_NULL(strBMT)
15536 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015537 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015538 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015539 member = member->next;
15540 baseMember = baseMember->next;
15541 }
15542 }
15543 }
15544 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015545 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000015546 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015547 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015548 if (type->facets != NULL) {
15549 xmlSchemaFacetPtr facet;
15550 int ok = 1;
15551
15552 facet = type->facets;
15553 do {
15554 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15555 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015556 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015557 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015558 type, facet);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015559 ok = 0;
15560 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015561 facet = facet->next;
15562 } while (facet != NULL);
15563 if (ok == 0)
15564 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015565
Daniel Veillard01fa6152004-06-29 17:04:39 +000015566 }
15567 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015568 * SPEC (3.3.2.5) (same as 1.3.2)
15569 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015570 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015571 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015572 */
15573 }
15574 }
15575
15576 return (0);
15577}
15578
15579/**
15580 * xmlSchemaCheckSRCSimpleType:
15581 * @ctxt: the schema parser context
15582 * @type: the simple type definition
15583 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015584 * Checks crc-simple-type constraints.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015585 *
15586 * Returns 0 if the constraints are satisfied,
15587 * if not a positive error code and -1 on internal
15588 * errors.
15589 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015590#if 0
Daniel Veillard01fa6152004-06-29 17:04:39 +000015591static int
15592xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15593 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015594{
15595 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000015596 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015597 * must satisfy the conditions set out in Constraints on Simple Type
15598 * Definition Schema Components (§3.14.6).
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015599 */
15600 if (WXS_IS_RESTRICTION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015601 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015602 * src-simple-type.2 "If the <restriction> alternative is chosen,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015603 * either it must have a base [attribute] or a <simpleType> among its
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015604 * [children], but not both."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015605 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015606 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015607 /*
15608 *
15609 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015610 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015611 /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015612 * an itemType [attribute] or a <simpleType> among its [children],
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015613 * but not both."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015614 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015615 * NOTE: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015616 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015617 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015618 /*
15619 * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015620 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015621 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015622 return (0);
15623}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015624#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000015625
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015626static int
15627xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15628{
15629 if (ctxt->vctxt == NULL) {
15630 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15631 if (ctxt->vctxt == NULL) {
15632 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015633 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015634 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015635 "failed to create a temp. validation context.\n",
15636 NULL, NULL);
15637 return (-1);
15638 }
15639 /* TODO: Pass user data. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015640 xmlSchemaSetValidErrors(ctxt->vctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000015641 ctxt->error, ctxt->warning, ctxt->errCtxt);
15642 xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15643 ctxt->serror, ctxt->errCtxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015644 }
15645 return (0);
15646}
15647
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015648static int
15649xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15650 xmlNodePtr node,
15651 xmlSchemaTypePtr type,
15652 const xmlChar *value,
15653 xmlSchemaValPtr *retVal,
15654 int fireErrors,
15655 int normalize,
15656 int isNormalized);
15657
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015658/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015659 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015660 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015661 * @type: the simple type definition
15662 * @value: the default value
15663 * @node: an optional node (the holder of the value)
15664 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015665 * Schema Component Constraint: Element Default Valid (Immediate)
15666 * (cos-valid-default)
15667 * This will be used by the parser only. For the validator there's
15668 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015669 *
15670 * Returns 0 if the constraints are satisfied,
15671 * if not, a positive error code and -1 on internal
15672 * errors.
15673 */
15674static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015675xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15676 xmlNodePtr node,
15677 xmlSchemaTypePtr type,
15678 const xmlChar *value,
15679 xmlSchemaValPtr *val)
15680{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015681 int ret = 0;
15682
15683 /*
15684 * cos-valid-default:
15685 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015686 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015687 * definition the appropriate case among the following must be true:
15688 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015689 if WXS_IS_COMPLEX(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015690 /*
15691 * Complex type.
15692 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015693 * SPEC (2.1) "its {content type} must be a simple type definition
15694 * or mixed."
15695 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015696 * type}'s particle must be ·emptiable· as defined by
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015697 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000015698 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015699 if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15700 ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015701 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015702 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015703 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015704 WXS_BASIC_CAST type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015705 "For a string to be a valid default, the type definition "
15706 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015707 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015708 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15709 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015710 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015711 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015712 * 1 If the type definition is a simple type definition, then the string
15713 * must be ·valid· with respect to that definition as defined by String
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015714 * Valid (§3.14.4).
15715 *
15716 * AND
15717 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015718 * 2.2.1 If the {content type} is a simple type definition, then the
15719 * string must be ·valid· with respect to that simple type definition
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015720 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015721 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015722 if (WXS_IS_SIMPLE(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015723 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015724 type, value, val, 1, 1, 0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015725 else if (WXS_HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015726 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015727 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015728 else
15729 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015730
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015731 if (ret < 0) {
15732 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15733 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015734 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015735
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015736 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000015737}
15738
15739/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015740 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000015741 * @ctxt: the schema parser context
15742 * @type: the complex type definition
15743 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015744 *.(4.6) Constraints on Complex Type Definition Schema Components
15745 * Schema Component Constraint:
15746 * Complex Type Definition Properties Correct (ct-props-correct)
15747 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000015748 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015749 * Returns 0 if the constraints are satisfied, a positive
15750 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000015751 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015752static int
15753xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15754 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000015755{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015756 /*
15757 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15758 *
15759 * SPEC (1) "The values of the properties of a complex type definition must
15760 * be as described in the property tableau in The Complex Type Definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015761 * Schema Component (§3.4.1), modulo the impact of Missing
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015762 * Sub-components (§5.3)."
15763 */
15764 if ((type->baseType != NULL) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015765 (WXS_IS_SIMPLE(type->baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015766 (WXS_IS_EXTENSION(type) == 0)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015767 /*
15768 * SPEC (2) "If the {base type definition} is a simple type definition,
15769 * the {derivation method} must be extension."
15770 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015771 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015772 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015773 NULL, WXS_BASIC_CAST type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015774 "If the base type is a simple type, the derivation method must be "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015775 "'extension'", NULL, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015776 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015777 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015778 /*
15779 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
15780 * definition·. That is, it must be possible to reach the ·ur-type
15781 * definition by repeatedly following the {base type definition}."
15782 *
15783 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015784 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015785 /*
15786 * NOTE that (4) and (5) need the following:
15787 * - attribute uses need to be already inherited (apply attr. prohibitions)
15788 * - attribute group references need to be expanded already
15789 * - simple types need to be typefixed already
15790 */
15791 if (type->attrUses &&
15792 (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15793 {
15794 xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15795 xmlSchemaAttributeUsePtr use, tmp;
15796 int i, j, hasId = 0;
15797
15798 for (i = uses->nbItems -1; i >= 0; i--) {
15799 use = uses->items[i];
15800
15801 /*
15802 * SPEC ct-props-correct
15803 * (4) "Two distinct attribute declarations in the
15804 * {attribute uses} must not have identical {name}s and
15805 * {target namespace}s."
15806 */
15807 if (i > 0) {
15808 for (j = i -1; j >= 0; j--) {
15809 tmp = uses->items[j];
15810 if ((WXS_ATTRUSE_DECL_NAME(use) ==
15811 WXS_ATTRUSE_DECL_NAME(tmp)) &&
15812 (WXS_ATTRUSE_DECL_TNS(use) ==
15813 WXS_ATTRUSE_DECL_TNS(tmp)))
15814 {
15815 xmlChar *str = NULL;
15816
15817 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15818 XML_SCHEMAP_AG_PROPS_CORRECT,
15819 NULL, WXS_BASIC_CAST type,
15820 "Duplicate %s",
15821 xmlSchemaGetComponentDesignation(&str, use),
15822 NULL);
15823 FREE_AND_NULL(str);
15824 /*
15825 * Remove the duplicate.
15826 */
15827 if (xmlSchemaItemListRemove(uses, i) == -1)
15828 goto exit_failure;
15829 goto next_use;
15830 }
15831 }
15832 }
15833 /*
15834 * SPEC ct-props-correct
15835 * (5) "Two distinct attribute declarations in the
15836 * {attribute uses} must not have {type definition}s which
15837 * are or are derived from ID."
15838 */
15839 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15840 if (xmlSchemaIsDerivedFromBuiltInType(
15841 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15842 {
15843 if (hasId) {
15844 xmlChar *str = NULL;
15845
15846 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15847 XML_SCHEMAP_AG_PROPS_CORRECT,
15848 NULL, WXS_BASIC_CAST type,
15849 "There must not exist more than one attribute "
15850 "declaration of type 'xs:ID' "
15851 "(or derived from 'xs:ID'). The %s violates this "
15852 "constraint",
15853 xmlSchemaGetComponentDesignation(&str, use),
15854 NULL);
15855 FREE_AND_NULL(str);
15856 if (xmlSchemaItemListRemove(uses, i) == -1)
15857 goto exit_failure;
15858 }
15859
15860 hasId = 1;
15861 }
15862 }
15863next_use: {}
15864 }
15865 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015866 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015867exit_failure:
15868 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +000015869}
15870
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015871static int
15872xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
15873 xmlSchemaTypePtr typeB)
15874{
15875 /*
15876 * TODO: This should implement component-identity
15877 * in the future.
15878 */
15879 if ((typeA == NULL) || (typeB == NULL))
15880 return (0);
15881 return (typeA == typeB);
15882}
15883
15884/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015885 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015886 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015887 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015888 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015889 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015890 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015891 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015892 * Type Derivation OK (Complex) (cos-ct-derived-ok)
15893 *
15894 * STATUS: completed
15895 *
15896 * Returns 0 if the constraints are satisfied, or 1
15897 * if not.
15898 */
15899static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015900xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015901 xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015902 xmlSchemaTypePtr baseType,
15903 int set)
15904{
15905 int equal = xmlSchemaAreEqualTypes(type, baseType);
15906 /* TODO: Error codes. */
15907 /*
15908 * SPEC "For a complex type definition (call it D, for derived)
15909 * to be validly derived from a type definition (call this
15910 * B, for base) given a subset of {extension, restriction}
15911 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015912 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015913 if (! equal) {
15914 /*
15915 * SPEC (1) "If B and D are not the same type definition, then the
15916 * {derivation method} of D must not be in the subset."
15917 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015918 if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
15919 ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015920 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015921 } else {
15922 /*
15923 * SPEC (2.1) "B and D must be the same type definition."
15924 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015925 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015926 }
15927 /*
15928 * SPEC (2.2) "B must be D's {base type definition}."
15929 */
15930 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015931 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015932 /*
15933 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
15934 * definition·."
15935 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015936 if (WXS_IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015937 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015938
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015939 if (WXS_IS_COMPLEX(type->baseType)) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015940 /*
15941 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
15942 * must be validly derived from B given the subset as defined by this
15943 * constraint."
15944 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015945 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015946 baseType, set));
15947 } else {
15948 /*
15949 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
15950 * must be validly derived from B given the subset as defined in Type
15951 * Derivation OK (Simple) (§3.14.6).
15952 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015953 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015954 baseType, set));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015955 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015956}
15957
15958/**
15959 * xmlSchemaCheckCOSDerivedOK:
15960 * @type: the derived simple type definition
15961 * @baseType: the base type definition
15962 *
15963 * Calls:
15964 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015965 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015966 * Checks wheter @type can be validly derived from @baseType.
15967 *
15968 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015969 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015970static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015971xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015972 xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015973 xmlSchemaTypePtr baseType,
15974 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015975{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015976 if (WXS_IS_SIMPLE(type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015977 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015978 else
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015979 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015980}
15981
William M. Brack2f2a6632004-08-20 23:09:47 +000015982/**
15983 * xmlSchemaCheckCOSCTExtends:
15984 * @ctxt: the schema parser context
15985 * @type: the complex type definition
15986 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015987 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015988 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015989 * Derivation Valid (Extension) (cos-ct-extends)
15990 *
15991 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015992 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015993 * (1.5)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015994 * (1.4.3.2.2.2) "Particle Valid (Extension)"
William M. Brack2f2a6632004-08-20 23:09:47 +000015995 *
15996 * Returns 0 if the constraints are satisfied, a positive
15997 * error code if not and -1 if an internal error occured.
15998 */
15999static int
16000xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16001 xmlSchemaTypePtr type)
16002{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016003 xmlSchemaTypePtr base = type->baseType;
16004 /*
16005 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16006 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000016007 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016008 /*
16009 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016010 * then all of the following must be true:"
16011 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016012 if (WXS_IS_COMPLEX(base)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000016013 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016014 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016015 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000016016 */
16017 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16018 xmlSchemaPCustomErr(ctxt,
16019 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016020 WXS_BASIC_CAST type, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000016021 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016022 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000016023 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16024 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016025
16026 /*
16027 * ATTENTION: The constrains (1.2) and (1.3) are not applied,
16028 * since they are automatically satisfied through the
16029 * inheriting mechanism.
16030 * Note that even if redefining components, the inheriting mechanism
16031 * is used.
16032 */
16033#if 0
William M. Brack2f2a6632004-08-20 23:09:47 +000016034 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016035 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016036 * uses}
16037 * of the complex type definition itself, that is, for every attribute
16038 * use in the {attribute uses} of the {base type definition}, there
16039 * must be an attribute use in the {attribute uses} of the complex
16040 * type definition itself whose {attribute declaration} has the same
16041 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016042 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000016043 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016044 if (base->attrUses != NULL) {
16045 int i, j, found;
16046 xmlSchemaAttributeUsePtr use, buse;
William M. Brack2f2a6632004-08-20 23:09:47 +000016047
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016048 for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16049 buse = (WXS_LIST_CAST base->attrUses)->items[i];
16050 found = 0;
16051 if (type->attrUses != NULL) {
16052 use = (WXS_LIST_CAST type->attrUses)->items[j];
16053 for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16054 {
16055 if ((WXS_ATTRUSE_DECL_NAME(use) ==
16056 WXS_ATTRUSE_DECL_NAME(buse)) &&
16057 (WXS_ATTRUSE_DECL_TNS(use) ==
16058 WXS_ATTRUSE_DECL_TNS(buse)) &&
16059 (WXS_ATTRUSE_TYPEDEF(use) ==
16060 WXS_ATTRUSE_TYPEDEF(buse))
16061 {
16062 found = 1;
16063 break;
16064 }
16065 }
16066 }
16067 if (! found) {
16068 xmlChar *str = NULL;
16069
16070 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16071 XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16072 NULL, WXS_BASIC_CAST type,
16073 /*
16074 * TODO: The report does not indicate that also the
16075 * type needs to be the same.
16076 */
16077 "This type is missing a matching correspondent "
16078 "for its {base type}'s %s in its {attribute uses}",
16079 xmlSchemaGetComponentDesignation(&str,
16080 buse->children),
16081 NULL);
16082 FREE_AND_NULL(str)
16083 }
16084 }
16085 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016086 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016087 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16088 * definition must also have one, and the base type definition's
16089 * {attribute wildcard}'s {namespace constraint} must be a subset
16090 * of the complex type definition's {attribute wildcard}'s {namespace
16091 * constraint}, as defined by Wildcard Subset (§3.10.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016092 */
16093
16094 /*
16095 * MAYBE TODO: Enable if ever needed. But this will be needed only
16096 * if created the type via a schema construction API.
16097 */
16098 if (base->attributeWildcard != NULL) {
16099 if (type->attributeWilcard == NULL) {
16100 xmlChar *str = NULL;
16101
16102 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16103 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16104 NULL, type,
16105 "The base %s has an attribute wildcard, "
16106 "but this type is missing an attribute wildcard",
16107 xmlSchemaGetComponentDesignation(&str, base));
16108 FREE_AND_NULL(str)
16109
16110 } else if (xmlSchemaCheckCOSNSSubset(
16111 base->attributeWildcard, type->attributeWildcard))
16112 {
16113 xmlChar *str = NULL;
16114
16115 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16116 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16117 NULL, type,
16118 "The attribute wildcard is not a valid "
16119 "superset of the one in the base %s",
16120 xmlSchemaGetComponentDesignation(&str, base));
16121 FREE_AND_NULL(str)
16122 }
16123 }
16124#endif
16125 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016126 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000016127 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016128 if ((type->contentTypeDef != NULL) &&
16129 (type->contentTypeDef == base->contentTypeDef)) {
16130 /*
16131 * SPEC (1.4.1) "The {content type} of the {base type definition}
16132 * and the {content type} of the complex type definition itself
16133 * must be the same simple type definition"
16134 * PASS
16135 */
16136 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16137 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16138 /*
16139 * SPEC (1.4.2) "The {content type} of both the {base type
16140 * definition} and the complex type definition itself must
16141 * be empty."
16142 * PASS
16143 */
16144 } else {
16145 /*
16146 * SPEC (1.4.3) "All of the following must be true:"
16147 */
16148 if (type->subtypes == NULL) {
16149 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016150 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016151 * definition itself must specify a particle.
16152 */
16153 xmlSchemaPCustomErr(ctxt,
16154 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016155 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016156 "The content type must specify a particle", NULL);
16157 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16158 }
16159 /*
16160 * SPEC (1.4.3.2) "One of the following must be true:"
16161 */
16162 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16163 /*
16164 * SPEC (1.4.3.2.1) "The {content type} of the {base type
16165 * definition} must be empty.
16166 * PASS
16167 */
16168 } else {
16169 /*
16170 * SPEC (1.4.3.2.2) "All of the following must be true:"
16171 */
16172 if ((type->contentType != base->contentType) ||
16173 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16174 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16175 /*
16176 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16177 * or both must be element-only."
16178 */
16179 xmlSchemaPCustomErr(ctxt,
16180 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016181 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016182 "The content type of both, the type and its base "
16183 "type, must either 'mixed' or 'element-only'", NULL);
16184 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016185 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016186 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016187 * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016188 * complex type definition must be a ·valid extension·
16189 * of the {base type definition}'s particle, as defined
16190 * in Particle Valid (Extension) (§3.9.6)."
16191 *
16192 * NOTE that we won't check "Particle Valid (Extension)",
16193 * since it is ensured by the derivation process in
16194 * xmlSchemaTypeFixup(). We need to implement this when heading
16195 * for a construction API
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016196 * TODO: !! This is needed to be checked if redefining a type !!
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016197 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016198 }
16199 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016200 * URGENT TODO (1.5)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016201 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016202 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016203 } else {
16204 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016205 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016206 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000016207 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016208 if (type->contentTypeDef != base) {
16209 /*
16210 * SPEC (2.1) "The {content type} must be the same simple type
16211 * definition."
16212 */
16213 xmlSchemaPCustomErr(ctxt,
16214 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016215 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016216 "The content type must be the simple base type", NULL);
16217 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16218 }
16219 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16220 /*
16221 * SPEC (2.2) "The {final} of the {base type definition} must not
16222 * contain extension"
16223 * NOTE that this is the same as (1.1).
16224 */
16225 xmlSchemaPCustomErr(ctxt,
16226 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016227 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016228 "The 'final' of the base type definition "
16229 "contains 'extension'", NULL);
16230 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016231 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016232 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016233 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016234}
16235
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016236/**
16237 * xmlSchemaCheckDerivationOKRestriction:
16238 * @ctxt: the schema parser context
16239 * @type: the complex type definition
16240 *
16241 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016242 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016243 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16244 *
16245 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016246 * missing:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016247 * (5.4.2) ???
16248 *
16249 * ATTENTION:
16250 * In XML Schema 1.1 this will be:
16251 * Validation Rule: Checking complex type subsumption
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016252 *
16253 * Returns 0 if the constraints are satisfied, a positive
16254 * error code if not and -1 if an internal error occured.
16255 */
16256static int
16257xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16258 xmlSchemaTypePtr type)
16259{
16260 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016261
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016262 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016263 * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016264 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016265 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016266 base = type->baseType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016267 if (! WXS_IS_COMPLEX(base)) {
16268 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16269 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16270 type->node, WXS_BASIC_CAST type,
16271 "The base type must be a complex type", NULL, NULL);
16272 return(ctxt->err);
16273 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016274 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16275 /*
16276 * SPEC (1) "The {base type definition} must be a complex type
16277 * definition whose {final} does not contain restriction."
16278 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016279 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16280 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16281 type->node, WXS_BASIC_CAST type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016282 "The 'final' of the base type definition "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016283 "contains 'restriction'", NULL, NULL);
16284 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016285 }
16286 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016287 * SPEC (2), (3) and (4)
16288 * Those are handled in a separate function, since the
16289 * same constraints are needed for redefinition of
16290 * attribute groups as well.
16291 */
16292 if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16293 XML_SCHEMA_ACTION_DERIVE,
16294 WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16295 type->attrUses, base->attrUses,
16296 type->attributeWildcard,
16297 base->attributeWildcard) == -1)
16298 {
16299 return(-1);
16300 }
16301 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016302 * SPEC (5) "One of the following must be true:"
16303 */
16304 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16305 /*
16306 * SPEC (5.1) "The {base type definition} must be the
16307 * ·ur-type definition·."
16308 * PASS
16309 */
16310 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16311 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16312 /*
16313 * SPEC (5.2.1) "The {content type} of the complex type definition
16314 * must be a simple type definition"
16315 *
16316 * SPEC (5.2.2) "One of the following must be true:"
16317 */
16318 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016319 (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16320 {
16321 int err;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016322 /*
16323 * SPEC (5.2.2.1) "The {content type} of the {base type
16324 * definition} must be a simple type definition from which
16325 * the {content type} is validly derived given the empty
16326 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016327 *
16328 * ATTENTION TODO: This seems not needed if the type implicitely
16329 * derived from the base type.
16330 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016331 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016332 err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16333 type->contentTypeDef, base->contentTypeDef, 0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016334 if (err != 0) {
16335 xmlChar *strA = NULL, *strB = NULL;
16336
16337 if (err == -1)
16338 return(-1);
16339 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16340 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16341 NULL, WXS_BASIC_CAST type,
16342 "The {content type} %s is not validly derived from the "
16343 "base type's {content type} %s",
16344 xmlSchemaGetComponentDesignation(&strA,
16345 type->contentTypeDef),
16346 xmlSchemaGetComponentDesignation(&strB,
16347 base->contentTypeDef));
16348 FREE_AND_NULL(strA);
16349 FREE_AND_NULL(strB);
16350 return(ctxt->err);
16351 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016352 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16353 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016354 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016355 /*
16356 * SPEC (5.2.2.2) "The {base type definition} must be mixed
16357 * and have a particle which is ·emptiable· as defined in
16358 * Particle Emptiable (§3.9.6)."
16359 * PASS
16360 */
16361 } else {
16362 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016363 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16364 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016365 "The content type of the base type must be either "
16366 "a simple type or 'mixed' and an emptiable particle", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016367 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016368 }
16369 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16370 /*
16371 * SPEC (5.3.1) "The {content type} of the complex type itself must
16372 * be empty"
16373 */
16374 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16375 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016376 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016377 * definition} must also be empty."
16378 * PASS
16379 */
16380 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16381 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16382 xmlSchemaIsParticleEmptiable(
16383 (xmlSchemaParticlePtr) base->subtypes)) {
16384 /*
16385 * SPEC (5.3.2.2) "The {content type} of the {base type
16386 * definition} must be elementOnly or mixed and have a particle
16387 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
16388 * PASS
16389 */
16390 } else {
16391 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016392 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16393 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016394 "The content type of the base type must be either "
16395 "empty or 'mixed' (or 'elements-only') and an emptiable "
16396 "particle", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016397 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016398 }
16399 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016400 WXS_HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016401 /*
16402 * SPEC (5.4.1.1) "The {content type} of the complex type definition
16403 * itself must be element-only"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016404 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016405 if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016406 /*
16407 * SPEC (5.4.1.2) "The {content type} of the complex type
16408 * definition itself and of the {base type definition} must be
16409 * mixed"
16410 */
16411 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016412 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16413 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016414 "If the content type is 'mixed', then the content type of the "
16415 "base type must also be 'mixed'", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016416 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016417 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016418 /*
16419 * SPEC (5.4.2) "The particle of the complex type definition itself
16420 * must be a ·valid restriction· of the particle of the {content
16421 * type} of the {base type definition} as defined in Particle Valid
16422 * (Restriction) (§3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016423 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016424 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016425 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016426 } else {
16427 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016428 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16429 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016430 "The type is not a valid restriction of its base type", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016431 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016432 }
16433 return (0);
16434}
16435
16436/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016437 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016438 * @ctxt: the schema parser context
16439 * @type: the complex type definition
16440 *
16441 * (3.4.6) Constraints on Complex Type Definition Schema Components
16442 *
16443 * Returns 0 if the constraints are satisfied, a positive
16444 * error code if not and -1 if an internal error occured.
16445 */
16446static int
16447xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16448 xmlSchemaTypePtr type)
16449{
16450 int ret;
16451 /*
16452 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016453 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016454 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16455 if (ret != 0)
16456 return (ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016457 if (WXS_IS_EXTENSION(type))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016458 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16459 else
16460 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16461 return (ret);
16462}
16463
16464/**
16465 * xmlSchemaCheckSRCCT:
16466 * @ctxt: the schema parser context
16467 * @type: the complex type definition
16468 *
16469 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016470 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016471 * Complex Type Definition Representation OK (src-ct)
16472 *
16473 * Returns 0 if the constraints are satisfied, a positive
16474 * error code if not and -1 if an internal error occured.
16475 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016476static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016477xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016478 xmlSchemaTypePtr type)
16479{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016480 xmlSchemaTypePtr base;
16481 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016482
16483 /*
16484 * TODO: Adjust the error codes here, as I used
16485 * XML_SCHEMAP_SRC_CT_1 only yet.
16486 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016487 base = type->baseType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016488 if (! WXS_HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016489 /*
16490 * 1 If the <complexContent> alternative is chosen, the type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016491 * ·resolved· to by the ·actual value· of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016492 * must be a complex type definition;
16493 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016494 if (! WXS_IS_COMPLEX(base)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016495 xmlChar *str = NULL;
16496 xmlSchemaPCustomErr(ctxt,
16497 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016498 WXS_BASIC_CAST type, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016499 "If using <complexContent>, the base type is expected to be "
16500 "a complex type. The base type '%s' is a simple type",
16501 xmlSchemaFormatQName(&str, base->targetNamespace,
16502 base->name));
16503 FREE_AND_NULL(str)
16504 return (XML_SCHEMAP_SRC_CT_1);
16505 }
16506 } else {
16507 /*
16508 * SPEC
16509 * 2 If the <simpleContent> alternative is chosen, all of the
16510 * following must be true:
16511 * 2.1 The type definition ·resolved· to by the ·actual value· of the
16512 * base [attribute] must be one of the following:
16513 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016514 if (WXS_IS_SIMPLE(base)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016515 if (WXS_IS_EXTENSION(type) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016516 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016517 /*
16518 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016519 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016520 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016521 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016522 xmlSchemaPCustomErr(ctxt,
16523 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016524 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016525 "If using <simpleContent> and <restriction>, the base "
16526 "type must be a complex type. The base type '%s' is "
16527 "a simple type",
16528 xmlSchemaFormatQName(&str, base->targetNamespace,
16529 base->name));
16530 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016531 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016532 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016533 } else {
16534 /* Base type is a complex type. */
16535 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16536 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16537 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016538 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016539 * simple type definition;
16540 * PASS
16541 */
16542 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016543 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016544 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016545 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016546 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016547 type->name);
16548 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016549 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016550 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016551 (WXS_IS_RESTRICTION(type))) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016552
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016553 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016554 * 2.1.2 only if the <restriction> alternative is also
16555 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016556 * is mixed and a particle emptiable.
16557 */
16558 if (! xmlSchemaIsParticleEmptiable(
16559 (xmlSchemaParticlePtr) base->subtypes)) {
16560 ret = XML_SCHEMAP_SRC_CT_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016561 } else
16562 /*
16563 * Attention: at this point the <simpleType> child is in
16564 * ->contentTypeDef (put there during parsing).
16565 */
16566 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016567 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016568 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016569 * 2.2 If clause 2.1.2 above is satisfied, then there
16570 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016571 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016572 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016573 /* TODO: Change error code to ..._SRC_CT_2_2. */
16574 xmlSchemaPCustomErr(ctxt,
16575 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016576 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016577 "A <simpleType> is expected among the children "
16578 "of <restriction>, if <simpleContent> is used and "
16579 "the base type '%s' is a complex type",
16580 xmlSchemaFormatQName(&str, base->targetNamespace,
16581 base->name));
16582 FREE_AND_NULL(str)
16583 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016584 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016585 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016586 ret = XML_SCHEMAP_SRC_CT_1;
16587 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016588 }
16589 if (ret > 0) {
16590 xmlChar *str = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016591 if (WXS_IS_RESTRICTION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016592 xmlSchemaPCustomErr(ctxt,
16593 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016594 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016595 "If <simpleContent> and <restriction> is used, the "
16596 "base type must be a simple type or a complex type with "
16597 "mixed content and particle emptiable. The base type "
16598 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016599 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016600 base->name));
16601 } else {
16602 xmlSchemaPCustomErr(ctxt,
16603 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016604 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016605 "If <simpleContent> and <extension> is used, the "
16606 "base type must be a simple type. The base type '%s' "
16607 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016608 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016609 base->name));
16610 }
16611 FREE_AND_NULL(str)
16612 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016613 }
16614 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016615 * SPEC (3) "The corresponding complex type definition component must
16616 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016617 * Definition Schema Components (§3.4.6);"
16618 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016619 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016620 /*
16621 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016622 * above for {attribute wildcard} is satisfied, the intensional
16623 * intersection must be expressible, as defined in Attribute Wildcard
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016624 * Intersection (§3.10.6).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016625 * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016626 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016627 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016628}
William M. Brack2f2a6632004-08-20 23:09:47 +000016629
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016630#ifdef ENABLE_PARTICLE_RESTRICTION
16631/**
16632 * xmlSchemaCheckParticleRangeOK:
16633 * @ctxt: the schema parser context
16634 * @type: the complex type definition
16635 *
16636 * (3.9.6) Constraints on Particle Schema Components
16637 * Schema Component Constraint:
16638 * Occurrence Range OK (range-ok)
16639 *
16640 * STATUS: complete
16641 *
16642 * Returns 0 if the constraints are satisfied, a positive
16643 * error code if not and -1 if an internal error occured.
16644 */
16645static int
16646xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16647 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016648{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016649 if (rmin < bmin)
16650 return (1);
16651 if ((bmax != UNBOUNDED) &&
16652 (rmax > bmax))
16653 return (1);
16654 return (0);
16655}
16656
16657/**
16658 * xmlSchemaCheckRCaseNameAndTypeOK:
16659 * @ctxt: the schema parser context
16660 * @r: the restricting element declaration particle
16661 * @b: the base element declaration particle
16662 *
16663 * (3.9.6) Constraints on Particle Schema Components
16664 * Schema Component Constraint:
16665 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16666 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016667 *
16668 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016669 * MISSING (3.2.3)
16670 * CLARIFY: (3.2.2)
16671 *
16672 * Returns 0 if the constraints are satisfied, a positive
16673 * error code if not and -1 if an internal error occured.
16674 */
16675static int
16676xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16677 xmlSchemaParticlePtr r,
16678 xmlSchemaParticlePtr b)
16679{
16680 xmlSchemaElementPtr elemR, elemB;
16681
16682 /* TODO: Error codes (rcase-NameAndTypeOK). */
16683 elemR = (xmlSchemaElementPtr) r->children;
16684 elemB = (xmlSchemaElementPtr) b->children;
16685 /*
16686 * SPEC (1) "The declarations' {name}s and {target namespace}s are
16687 * the same."
16688 */
16689 if ((elemR != elemB) &&
16690 ((! xmlStrEqual(elemR->name, elemB->name)) ||
16691 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16692 return (1);
16693 /*
16694 * SPEC (2) "R's occurrence range is a valid restriction of B's
16695 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16696 */
16697 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16698 b->minOccurs, b->maxOccurs) != 0)
16699 return (1);
16700 /*
16701 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16702 * {scope} are global."
16703 */
16704 if (elemR == elemB)
16705 return (0);
16706 /*
16707 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16708 */
16709 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16710 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16711 return (1);
16712 /*
16713 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16714 * or is not fixed, or R's declaration's {value constraint} is fixed
16715 * with the same value."
16716 */
16717 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16718 ((elemR->value == NULL) ||
16719 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16720 /* TODO: Equality of the initial value or normalized or canonical? */
16721 (! xmlStrEqual(elemR->value, elemB->value))))
16722 return (1);
16723 /*
16724 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16725 * definitions} is a subset of B's declaration's {identity-constraint
16726 * definitions}, if any."
16727 */
16728 if (elemB->idcs != NULL) {
16729 /* TODO */
16730 }
16731 /*
16732 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16733 * superset of B's declaration's {disallowed substitutions}."
16734 */
16735 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16736 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16737 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16738 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16739 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16740 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16741 return (1);
16742 /*
16743 * SPEC (3.2.5) "R's {type definition} is validly derived given
16744 * {extension, list, union} from B's {type definition}"
16745 *
16746 * BADSPEC TODO: What's the point of adding "list" and "union" to the
16747 * set, if the corresponding constraints handle "restriction" and
16748 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016749 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016750 */
16751 {
16752 int set = 0;
16753
16754 set |= SUBSET_EXTENSION;
16755 set |= SUBSET_LIST;
16756 set |= SUBSET_UNION;
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016757 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016758 elemB->subtypes, set) != 0)
16759 return (1);
16760 }
16761 return (0);
16762}
16763
16764/**
16765 * xmlSchemaCheckRCaseNSCompat:
16766 * @ctxt: the schema parser context
16767 * @r: the restricting element declaration particle
16768 * @b: the base wildcard particle
16769 *
16770 * (3.9.6) Constraints on Particle Schema Components
16771 * Schema Component Constraint:
16772 * Particle Derivation OK (Elt:Any -- NSCompat)
16773 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016774 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016775 * STATUS: complete
16776 *
16777 * Returns 0 if the constraints are satisfied, a positive
16778 * error code if not and -1 if an internal error occured.
16779 */
16780static int
16781xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16782 xmlSchemaParticlePtr r,
16783 xmlSchemaParticlePtr b)
16784{
16785 /* TODO:Error codes (rcase-NSCompat). */
16786 /*
16787 * SPEC "For an element declaration particle to be a ·valid restriction·
16788 * of a wildcard particle all of the following must be true:"
16789 *
16790 * SPEC (1) "The element declaration's {target namespace} is ·valid·
16791 * with respect to the wildcard's {namespace constraint} as defined by
16792 * Wildcard allows Namespace Name (§3.10.4)."
16793 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016794 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016795 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16796 return (1);
16797 /*
16798 * SPEC (2) "R's occurrence range is a valid restriction of B's
16799 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16800 */
16801 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16802 b->minOccurs, b->maxOccurs) != 0)
16803 return (1);
16804
16805 return (0);
16806}
16807
16808/**
16809 * xmlSchemaCheckRCaseRecurseAsIfGroup:
16810 * @ctxt: the schema parser context
16811 * @r: the restricting element declaration particle
16812 * @b: the base model group particle
16813 *
16814 * (3.9.6) Constraints on Particle Schema Components
16815 * Schema Component Constraint:
16816 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16817 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016818 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016819 * STATUS: TODO
16820 *
16821 * Returns 0 if the constraints are satisfied, a positive
16822 * error code if not and -1 if an internal error occured.
16823 */
16824static int
16825xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16826 xmlSchemaParticlePtr r,
16827 xmlSchemaParticlePtr b)
16828{
16829 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16830 TODO
16831 return (0);
16832}
16833
16834/**
16835 * xmlSchemaCheckRCaseNSSubset:
16836 * @ctxt: the schema parser context
16837 * @r: the restricting wildcard particle
16838 * @b: the base wildcard particle
16839 *
16840 * (3.9.6) Constraints on Particle Schema Components
16841 * Schema Component Constraint:
16842 * Particle Derivation OK (Any:Any -- NSSubset)
16843 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016844 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016845 * STATUS: complete
16846 *
16847 * Returns 0 if the constraints are satisfied, a positive
16848 * error code if not and -1 if an internal error occured.
16849 */
16850static int
16851xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16852 xmlSchemaParticlePtr r,
16853 xmlSchemaParticlePtr b,
16854 int isAnyTypeBase)
16855{
16856 /* TODO: Error codes (rcase-NSSubset). */
16857 /*
16858 * SPEC (1) "R's occurrence range is a valid restriction of B's
16859 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16860 */
16861 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16862 b->minOccurs, b->maxOccurs))
16863 return (1);
16864 /*
16865 * SPEC (2) "R's {namespace constraint} must be an intensional subset
16866 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
16867 */
16868 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
16869 (xmlSchemaWildcardPtr) b->children))
16870 return (1);
16871 /*
16872 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
16873 * definition·, R's {process contents} must be identical to or stronger
16874 * than B's {process contents}, where strict is stronger than lax is
16875 * stronger than skip."
16876 */
16877 if (! isAnyTypeBase) {
16878 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
16879 ((xmlSchemaWildcardPtr) b->children)->processContents)
16880 return (1);
16881 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016882
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016883 return (0);
16884}
16885
16886/**
16887 * xmlSchemaCheckCOSParticleRestrict:
16888 * @ctxt: the schema parser context
16889 * @type: the complex type definition
16890 *
16891 * (3.9.6) Constraints on Particle Schema Components
16892 * Schema Component Constraint:
16893 * Particle Valid (Restriction) (cos-particle-restrict)
16894 *
16895 * STATUS: TODO
16896 *
16897 * Returns 0 if the constraints are satisfied, a positive
16898 * error code if not and -1 if an internal error occured.
16899 */
16900static int
16901xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
16902 xmlSchemaParticlePtr r,
16903 xmlSchemaParticlePtr b)
16904{
16905 int ret = 0;
16906
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016907 /*part = WXS_TYPE_PARTICLE(type);
16908 basePart = WXS_TYPE_PARTICLE(base);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016909 */
16910
16911 TODO
16912
16913 /*
16914 * SPEC (1) "They are the same particle."
16915 */
16916 if (r == b)
16917 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016918
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016919
16920 return (0);
16921}
16922
16923/**
16924 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
16925 * @ctxt: the schema parser context
16926 * @r: the model group particle
16927 * @b: the base wildcard particle
16928 *
16929 * (3.9.6) Constraints on Particle Schema Components
16930 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016931 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016932 * NSRecurseCheckCardinality)
16933 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016934 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016935 * STATUS: TODO: subst-groups
16936 *
16937 * Returns 0 if the constraints are satisfied, a positive
16938 * error code if not and -1 if an internal error occured.
16939 */
16940static int
16941xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
16942 xmlSchemaParticlePtr r,
16943 xmlSchemaParticlePtr b)
16944{
16945 xmlSchemaParticlePtr part;
16946 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
16947 if ((r->children == NULL) || (r->children->children == NULL))
16948 return (-1);
16949 /*
16950 * SPEC "For a group particle to be a ·valid restriction· of a
16951 * wildcard particle..."
16952 *
16953 * SPEC (1) "Every member of the {particles} of the group is a ·valid
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016954 * restriction· of the wildcard as defined by
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016955 * Particle Valid (Restriction) (§3.9.6)."
16956 */
16957 part = (xmlSchemaParticlePtr) r->children->children;
16958 do {
16959 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
16960 return (1);
16961 part = (xmlSchemaParticlePtr) part->next;
16962 } while (part != NULL);
16963 /*
16964 * SPEC (2) "The effective total range of the group [...] is a
16965 * valid restriction of B's occurrence range as defined by
16966 * Occurrence Range OK (§3.9.6)."
16967 */
16968 if (xmlSchemaCheckParticleRangeOK(
16969 xmlSchemaGetParticleTotalRangeMin(r),
16970 xmlSchemaGetParticleTotalRangeMax(r),
16971 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016972 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016973 return (0);
16974}
16975
16976/**
16977 * xmlSchemaCheckRCaseRecurse:
16978 * @ctxt: the schema parser context
16979 * @r: the <all> or <sequence> model group particle
16980 * @b: the base <all> or <sequence> model group particle
16981 *
16982 * (3.9.6) Constraints on Particle Schema Components
16983 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016984 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016985 Recurse)
16986 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016987 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016988 * STATUS: ?
16989 * TODO: subst-groups
16990 *
16991 * Returns 0 if the constraints are satisfied, a positive
16992 * error code if not and -1 if an internal error occured.
16993 */
16994static int
16995xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
16996 xmlSchemaParticlePtr r,
16997 xmlSchemaParticlePtr b)
16998{
16999 /* xmlSchemaParticlePtr part; */
17000 /* TODO: Error codes (rcase-Recurse). */
17001 if ((r->children == NULL) || (b->children == NULL) ||
17002 (r->children->type != b->children->type))
17003 return (-1);
17004 /*
17005 * SPEC "For an all or sequence group particle to be a ·valid
17006 * restriction· of another group particle with the same {compositor}..."
17007 *
17008 * SPEC (1) "R's occurrence range is a valid restriction of B's
17009 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
17010 */
17011 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17012 b->minOccurs, b->maxOccurs))
17013 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017014
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017015
17016 return (0);
17017}
17018
17019#endif
17020
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017021#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17022 xmlSchemaPCustomErrExt(pctxt, \
17023 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017024 WXS_BASIC_CAST fac1, fac1->node, \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017025 "It is an error for both '%s' and '%s' to be specified on the "\
17026 "same type definition", \
17027 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17028 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17029
17030#define FACET_RESTR_ERR(fac1, msg) \
17031 xmlSchemaPCustomErr(pctxt, \
17032 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017033 WXS_BASIC_CAST fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017034 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017035
17036#define FACET_RESTR_FIXED_ERR(fac) \
17037 xmlSchemaPCustomErr(pctxt, \
17038 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017039 WXS_BASIC_CAST fac, fac->node, \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017040 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017041 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017042
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017043static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017044xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17045 xmlSchemaFacetPtr facet1,
17046 xmlSchemaFacetPtr facet2,
17047 int lessGreater,
17048 int orEqual,
17049 int ofBase)
17050{
17051 xmlChar *msg = NULL;
17052
17053 msg = xmlStrdup(BAD_CAST "'");
17054 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17055 msg = xmlStrcat(msg, BAD_CAST "' has to be");
17056 if (lessGreater == 0)
17057 msg = xmlStrcat(msg, BAD_CAST " equal to");
17058 if (lessGreater == 1)
17059 msg = xmlStrcat(msg, BAD_CAST " greater than");
17060 else
17061 msg = xmlStrcat(msg, BAD_CAST " less than");
17062
17063 if (orEqual)
17064 msg = xmlStrcat(msg, BAD_CAST " or equal to");
17065 msg = xmlStrcat(msg, BAD_CAST " '");
17066 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17067 if (ofBase)
17068 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17069 else
17070 msg = xmlStrcat(msg, BAD_CAST "'");
17071
17072 xmlSchemaPCustomErr(pctxt,
17073 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017074 WXS_BASIC_CAST facet1, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017075 (const char *) msg, NULL);
17076
17077 if (msg != NULL)
17078 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017079}
17080
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017081/*
17082* xmlSchemaDeriveAndValidateFacets:
17083*
17084* Schema Component Constraint: Simple Type Restriction (Facets)
17085* (st-restrict-facets)
17086*/
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017087static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017088xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17089 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017090{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017091 xmlSchemaTypePtr base = type->baseType;
17092 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017093 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017094 flength = NULL, ftotdig = NULL, ffracdig = NULL,
17095 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17096 fmininc = NULL, fmaxinc = NULL,
17097 fminexc = NULL, fmaxexc = NULL,
17098 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17099 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17100 bfmininc = NULL, bfmaxinc = NULL,
17101 bfminexc = NULL, bfmaxexc = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000017102 int res; /* err = 0, fixedErr; */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017103
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017104 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017105 * SPEC st-restrict-facets 1:
17106 * "The {variety} of R is the same as that of B."
17107 */
17108 /*
17109 * SPEC st-restrict-facets 2:
17110 * "If {variety} is atomic, the {primitive type definition}
17111 * of R is the same as that of B."
17112 *
17113 * NOTE: we leave 1 & 2 out for now, since this will be
17114 * satisfied by the derivation process.
17115 * CONSTRUCTION TODO: Maybe needed if using a construction API.
17116 */
17117 /*
17118 * SPEC st-restrict-facets 3:
17119 * "The {facets} of R are the union of S and the {facets}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017120 * of B, eliminating duplicates. To eliminate duplicates,
17121 * when a facet of the same kind occurs in both S and the
17122 * {facets} of B, the one in the {facets} of B is not
17123 * included, with the exception of enumeration and pattern
17124 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017125 * are allowed."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017126 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017127
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017128 if ((type->facetSet == NULL) && (base->facetSet == NULL))
17129 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017130
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017131 last = type->facetSet;
17132 if (last != NULL)
17133 while (last->next != NULL)
17134 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017135
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017136 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17137 facet = cur->facet;
17138 switch (facet->type) {
17139 case XML_SCHEMA_FACET_LENGTH:
17140 flength = facet; break;
17141 case XML_SCHEMA_FACET_MINLENGTH:
17142 fminlen = facet; break;
17143 case XML_SCHEMA_FACET_MININCLUSIVE:
17144 fmininc = facet; break;
17145 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17146 fminexc = facet; break;
17147 case XML_SCHEMA_FACET_MAXLENGTH:
17148 fmaxlen = facet; break;
17149 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17150 fmaxinc = facet; break;
17151 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17152 fmaxexc = facet; break;
17153 case XML_SCHEMA_FACET_TOTALDIGITS:
17154 ftotdig = facet; break;
17155 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17156 ffracdig = facet; break;
17157 default:
17158 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017159 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017160 }
17161 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17162 facet = cur->facet;
17163 switch (facet->type) {
17164 case XML_SCHEMA_FACET_LENGTH:
17165 bflength = facet; break;
17166 case XML_SCHEMA_FACET_MINLENGTH:
17167 bfminlen = facet; break;
17168 case XML_SCHEMA_FACET_MININCLUSIVE:
17169 bfmininc = facet; break;
17170 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17171 bfminexc = facet; break;
17172 case XML_SCHEMA_FACET_MAXLENGTH:
17173 bfmaxlen = facet; break;
17174 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17175 bfmaxinc = facet; break;
17176 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17177 bfmaxexc = facet; break;
17178 case XML_SCHEMA_FACET_TOTALDIGITS:
17179 bftotdig = facet; break;
17180 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17181 bffracdig = facet; break;
17182 default:
17183 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017184 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017185 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017186 /*
17187 * length and minLength or maxLength (2.2) + (3.2)
17188 */
17189 if (flength && (fminlen || fmaxlen)) {
17190 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17191 "either of 'minLength' or 'maxLength' to be specified on "
17192 "the same type definition")
17193 }
17194 /*
17195 * Mutual exclusions in the same derivation step.
17196 */
17197 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017198 /*
17199 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017200 */
17201 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17202 }
17203 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017204 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017205 * SCC "minInclusive and minExclusive"
17206 */
17207 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017208 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017209
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017210 if (flength && bflength) {
17211 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017212 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017213 * The values have to be equal.
17214 */
17215 res = xmlSchemaCompareValues(flength->val, bflength->val);
17216 if (res == -2)
17217 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017218 if (res != 0)
17219 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17220 if ((res != 0) && (bflength->fixed)) {
17221 FACET_RESTR_FIXED_ERR(flength)
17222 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017223
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017224 }
17225 if (fminlen && bfminlen) {
17226 /*
17227 * SCC "minLength valid restriction"
17228 * minLength >= BASE minLength
17229 */
17230 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17231 if (res == -2)
17232 goto internal_error;
17233 if (res == -1)
17234 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17235 if ((res != 0) && (bfminlen->fixed)) {
17236 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017237 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017238 }
17239 if (fmaxlen && bfmaxlen) {
17240 /*
17241 * SCC "maxLength valid restriction"
17242 * maxLength <= BASE minLength
17243 */
17244 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17245 if (res == -2)
17246 goto internal_error;
17247 if (res == 1)
17248 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17249 if ((res != 0) && (bfmaxlen->fixed)) {
17250 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017251 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017252 }
17253 /*
17254 * SCC "length and minLength or maxLength"
17255 */
17256 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017257 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017258 if (flength) {
17259 if (! fminlen)
17260 flength = bflength;
17261 if (fminlen) {
17262 /* (1.1) length >= minLength */
17263 res = xmlSchemaCompareValues(flength->val, fminlen->val);
17264 if (res == -2)
17265 goto internal_error;
17266 if (res == -1)
17267 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17268 }
17269 if (! fmaxlen)
17270 fmaxlen = bfmaxlen;
17271 if (fmaxlen) {
17272 /* (2.1) length <= maxLength */
17273 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17274 if (res == -2)
17275 goto internal_error;
17276 if (res == 1)
17277 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17278 }
17279 }
17280 if (fmaxinc) {
17281 /*
17282 * "maxInclusive"
17283 */
17284 if (fmininc) {
17285 /* SCC "maxInclusive >= minInclusive" */
17286 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17287 if (res == -2)
17288 goto internal_error;
17289 if (res == -1) {
17290 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17291 }
17292 }
17293 /*
17294 * SCC "maxInclusive valid restriction"
17295 */
17296 if (bfmaxinc) {
17297 /* maxInclusive <= BASE maxInclusive */
17298 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17299 if (res == -2)
17300 goto internal_error;
17301 if (res == 1)
17302 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17303 if ((res != 0) && (bfmaxinc->fixed)) {
17304 FACET_RESTR_FIXED_ERR(fmaxinc)
17305 }
17306 }
17307 if (bfmaxexc) {
17308 /* maxInclusive < BASE maxExclusive */
17309 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17310 if (res == -2)
17311 goto internal_error;
17312 if (res != -1) {
17313 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17314 }
17315 }
17316 if (bfmininc) {
17317 /* maxInclusive >= BASE minInclusive */
17318 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17319 if (res == -2)
17320 goto internal_error;
17321 if (res == -1) {
17322 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17323 }
17324 }
17325 if (bfminexc) {
17326 /* maxInclusive > BASE minExclusive */
17327 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17328 if (res == -2)
17329 goto internal_error;
17330 if (res != 1) {
17331 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17332 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017333 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017334 }
17335 if (fmaxexc) {
17336 /*
17337 * "maxExclusive >= minExclusive"
17338 */
17339 if (fminexc) {
17340 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17341 if (res == -2)
17342 goto internal_error;
17343 if (res == -1) {
17344 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17345 }
17346 }
17347 /*
17348 * "maxExclusive valid restriction"
17349 */
17350 if (bfmaxexc) {
17351 /* maxExclusive <= BASE maxExclusive */
17352 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17353 if (res == -2)
17354 goto internal_error;
17355 if (res == 1) {
17356 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17357 }
17358 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017359 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017360 }
17361 }
17362 if (bfmaxinc) {
17363 /* maxExclusive <= BASE maxInclusive */
17364 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17365 if (res == -2)
17366 goto internal_error;
17367 if (res == 1) {
17368 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17369 }
17370 }
17371 if (bfmininc) {
17372 /* maxExclusive > BASE minInclusive */
17373 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17374 if (res == -2)
17375 goto internal_error;
17376 if (res != 1) {
17377 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17378 }
17379 }
17380 if (bfminexc) {
17381 /* maxExclusive > BASE minExclusive */
17382 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17383 if (res == -2)
17384 goto internal_error;
17385 if (res != 1) {
17386 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17387 }
17388 }
17389 }
17390 if (fminexc) {
17391 /*
17392 * "minExclusive < maxInclusive"
17393 */
17394 if (fmaxinc) {
17395 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17396 if (res == -2)
17397 goto internal_error;
17398 if (res != -1) {
17399 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17400 }
17401 }
17402 /*
17403 * "minExclusive valid restriction"
17404 */
17405 if (bfminexc) {
17406 /* minExclusive >= BASE minExclusive */
17407 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17408 if (res == -2)
17409 goto internal_error;
17410 if (res == -1) {
17411 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17412 }
17413 if ((res != 0) && (bfminexc->fixed)) {
17414 FACET_RESTR_FIXED_ERR(fminexc)
17415 }
17416 }
17417 if (bfmaxinc) {
17418 /* minExclusive <= BASE maxInclusive */
17419 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17420 if (res == -2)
17421 goto internal_error;
17422 if (res == 1) {
17423 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17424 }
17425 }
17426 if (bfmininc) {
17427 /* minExclusive >= BASE minInclusive */
17428 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17429 if (res == -2)
17430 goto internal_error;
17431 if (res == -1) {
17432 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17433 }
17434 }
17435 if (bfmaxexc) {
17436 /* minExclusive < BASE maxExclusive */
17437 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17438 if (res == -2)
17439 goto internal_error;
17440 if (res != -1) {
17441 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17442 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017443 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017444 }
17445 if (fmininc) {
17446 /*
17447 * "minInclusive < maxExclusive"
17448 */
17449 if (fmaxexc) {
17450 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17451 if (res == -2)
17452 goto internal_error;
17453 if (res != -1) {
17454 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17455 }
17456 }
17457 /*
17458 * "minExclusive valid restriction"
17459 */
17460 if (bfmininc) {
17461 /* minInclusive >= BASE minInclusive */
17462 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17463 if (res == -2)
17464 goto internal_error;
17465 if (res == -1) {
17466 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17467 }
17468 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017469 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017470 }
17471 }
17472 if (bfmaxinc) {
17473 /* minInclusive <= BASE maxInclusive */
17474 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17475 if (res == -2)
17476 goto internal_error;
Daniel Veillard0a119eb2005-07-20 13:46:00 +000017477 if (res == 1) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017478 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17479 }
17480 }
17481 if (bfminexc) {
17482 /* minInclusive > BASE minExclusive */
17483 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17484 if (res == -2)
17485 goto internal_error;
17486 if (res != 1)
17487 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17488 }
17489 if (bfmaxexc) {
17490 /* minInclusive < BASE maxExclusive */
17491 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17492 if (res == -2)
17493 goto internal_error;
17494 if (res != -1)
17495 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17496 }
17497 }
17498 if (ftotdig && bftotdig) {
17499 /*
17500 * SCC " totalDigits valid restriction"
17501 * totalDigits <= BASE totalDigits
17502 */
17503 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17504 if (res == -2)
17505 goto internal_error;
17506 if (res == 1)
17507 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17508 -1, 1, 1);
17509 if ((res != 0) && (bftotdig->fixed)) {
17510 FACET_RESTR_FIXED_ERR(ftotdig)
17511 }
17512 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017513 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017514 /*
17515 * SCC "fractionDigits valid restriction"
17516 * fractionDigits <= BASE fractionDigits
17517 */
17518 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17519 if (res == -2)
17520 goto internal_error;
17521 if (res == 1)
17522 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17523 -1, 1, 1);
17524 if ((res != 0) && (bffracdig->fixed)) {
17525 FACET_RESTR_FIXED_ERR(ffracdig)
17526 }
17527 }
17528 /*
17529 * SCC "fractionDigits less than or equal to totalDigits"
17530 */
17531 if (! ftotdig)
17532 ftotdig = bftotdig;
17533 if (! ffracdig)
17534 ffracdig = bffracdig;
17535 if (ftotdig && ffracdig) {
17536 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17537 if (res == -2)
17538 goto internal_error;
17539 if (res == 1)
17540 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17541 -1, 1, 0);
17542 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017543 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017544 * *Enumerations* won' be added here, since only the first set
17545 * of enumerations in the ancestor-or-self axis is used
17546 * for validation, plus we need to use the base type of those
17547 * enumerations for whitespace.
17548 *
17549 * *Patterns*: won't be add here, since they are ORed at
17550 * type level and ANDed at ancestor level. This will
17551 * happed during validation by walking the base axis
17552 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017553 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017554 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17555 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017556 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017557 * Special handling of enumerations and patterns.
17558 * TODO: hmm, they should not appear in the set, so remove this.
17559 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017560 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017561 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017562 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017563 /*
17564 * Search for a duplicate facet in the current type.
17565 */
17566 link = type->facetSet;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000017567 /* err = 0; */
17568 /* fixedErr = 0; */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017569 while (link != NULL) {
17570 facet = link->facet;
17571 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017572 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017573 case XML_SCHEMA_FACET_WHITESPACE:
17574 /*
17575 * The whitespace must be stronger.
17576 */
17577 if (facet->whitespace < bfacet->whitespace) {
17578 FACET_RESTR_ERR(flength,
17579 "The 'whitespace' value has to be equal to "
17580 "or stronger than the 'whitespace' value of "
17581 "the base type")
17582 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017583 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017584 (facet->whitespace != bfacet->whitespace)) {
17585 FACET_RESTR_FIXED_ERR(facet)
17586 }
17587 break;
17588 default:
17589 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017590 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017591 /* Duplicate found. */
17592 break;
17593 }
17594 link = link->next;
17595 }
17596 /*
17597 * If no duplicate was found: add the base types's facet
17598 * to the set.
17599 */
17600 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017601 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017602 xmlMalloc(sizeof(xmlSchemaFacetLink));
17603 if (link == NULL) {
17604 xmlSchemaPErrMemory(pctxt,
17605 "deriving facets, creating a facet link", NULL);
17606 return (-1);
17607 }
17608 link->facet = cur->facet;
17609 link->next = NULL;
17610 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017611 type->facetSet = link;
17612 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017613 last->next = link;
17614 last = link;
17615 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017616
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017617 }
17618
17619 return (0);
17620internal_error:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017621 PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17622 "an error occured");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017623 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017624}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017625
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017626static int
17627xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17628 xmlSchemaTypePtr type)
17629{
17630 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17631 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017632 * The actual value is then formed by replacing any union type
17633 * definition in the ·explicit members· with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017634 * {member type definitions}, in order.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017635 *
17636 * TODO: There's a bug entry at
17637 * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17638 * which indicates that we'll keep the union types the future.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017639 */
17640 link = type->memberTypes;
17641 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017642
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017643 if (WXS_IS_TYPE_NOT_FIXED(link->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000017644 xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017645
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017646 if (WXS_IS_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017647 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017648 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017649 link->type = subLink->type;
17650 if (subLink->next != NULL) {
17651 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017652 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017653 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017654 while (subLink != NULL) {
17655 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017656 xmlMalloc(sizeof(xmlSchemaTypeLink));
17657 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017658 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017659 NULL);
17660 return (-1);
17661 }
17662 newLink->type = subLink->type;
17663 prevLink->next = newLink;
17664 prevLink = newLink;
17665 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017666
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017667 subLink = subLink->next;
17668 }
17669 }
17670 }
17671 }
17672 link = link->next;
17673 }
17674 return (0);
17675}
17676
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017677static void
17678xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17679{
17680 int has = 0, needVal = 0, normVal = 0;
17681
17682 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17683 if (has) {
17684 needVal = (type->baseType->flags &
17685 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17686 normVal = (type->baseType->flags &
17687 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17688 }
17689 if (type->facets != NULL) {
17690 xmlSchemaFacetPtr fac;
17691
17692 for (fac = type->facets; fac != NULL; fac = fac->next) {
17693 switch (fac->type) {
17694 case XML_SCHEMA_FACET_WHITESPACE:
17695 break;
17696 case XML_SCHEMA_FACET_PATTERN:
17697 normVal = 1;
17698 has = 1;
17699 break;
17700 case XML_SCHEMA_FACET_ENUMERATION:
17701 needVal = 1;
17702 normVal = 1;
17703 has = 1;
17704 break;
17705 default:
17706 has = 1;
17707 break;
17708 }
17709 }
17710 }
17711 if (normVal)
17712 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17713 if (needVal)
17714 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17715 if (has)
17716 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17717
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017718 if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017719 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17720 /*
17721 * OPTIMIZE VAL TODO: Some facets need a computed value.
17722 */
17723 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17724 (prim->builtInType != XML_SCHEMAS_STRING)) {
17725 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17726 }
17727 }
17728}
17729
17730static int
17731xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17732{
17733
17734
17735 /*
17736 * Evaluate the whitespace-facet value.
17737 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017738 if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017739 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17740 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017741 } else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017742 return (0);
17743
17744 if (type->facetSet != NULL) {
17745 xmlSchemaFacetLinkPtr lin;
17746
17747 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17748 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17749 switch (lin->facet->whitespace) {
17750 case XML_SCHEMAS_FACET_PRESERVE:
17751 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17752 break;
17753 case XML_SCHEMAS_FACET_REPLACE:
17754 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17755 break;
17756 case XML_SCHEMAS_FACET_COLLAPSE:
17757 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17758 break;
17759 default:
17760 return (-1);
17761 }
17762 return (0);
17763 }
17764 }
17765 }
17766 /*
17767 * For all ·atomic· datatypes other than string (and types ·derived·
17768 * by ·restriction· from it) the value of whiteSpace is fixed to
17769 * collapse
17770 */
17771 {
17772 xmlSchemaTypePtr anc;
17773
17774 for (anc = type->baseType; anc != NULL &&
17775 anc->builtInType != XML_SCHEMAS_ANYTYPE;
17776 anc = anc->baseType) {
17777
17778 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17779 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17780 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17781
17782 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17783 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17784 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17785
17786 } else
17787 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17788 break;
17789 }
17790 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017791 }
17792 return (0);
17793}
17794
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017795static int
17796xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17797 xmlSchemaTypePtr type)
Daniel Veillard4255d502002-04-16 15:50:10 +000017798{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017799 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17800 return(0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017801 if (! WXS_IS_TYPE_NOT_FIXED_1(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017802 return(0);
17803 type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017804
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017805 if (WXS_IS_LIST(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017806 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017807 * Corresponds to <simpleType><list>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017808 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017809 if (type->subtypes == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017810 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017811 * This one is really needed, so get out.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017812 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017813 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017814 "list type has no item-type assigned");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017815 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017816 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017817 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017818 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017819 * Corresponds to <simpleType><union>...
17820 */
17821 if (type->memberTypes == NULL) {
17822 /*
17823 * This one is really needed, so get out.
17824 */
17825 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17826 "union type has no member-types assigned");
17827 return(-1);
17828 }
17829 } else {
17830 /*
17831 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017832 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017833 if (type->baseType == NULL) {
17834 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17835 "type has no base-type assigned");
17836 return(-1);
17837 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017838 if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017839 if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17840 return(-1);
17841 /*
17842 * Variety
17843 * If the <restriction> alternative is chosen, then the
17844 * {variety} of the {base type definition}.
17845 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017846 if (WXS_IS_ATOMIC(type->baseType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017847 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017848 else if (WXS_IS_LIST(type->baseType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017849 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017850 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017851 * Inherit the itemType.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017852 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017853 type->subtypes = type->baseType->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017854 } else if (WXS_IS_UNION(type->baseType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017855 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017856 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017857 * NOTE that we won't assign the memberTypes of the base,
17858 * since this will make trouble when freeing them; we will
17859 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017860 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017861 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017862 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017863 return(0);
17864}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017865
Daniel Veillard8651f532002-04-17 09:06:27 +000017866#ifdef DEBUG_TYPE
Daniel Veillard67952602006-01-05 15:29:44 +000017867static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017868xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
17869 xmlSchemaTypePtr type)
17870{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017871 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017872 xmlGenericError(xmlGenericErrorContext,
17873 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017874 type->node->doc->URL,
17875 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000017876 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017877 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000017878 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017879 if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017880 switch (type->contentType) {
17881 case XML_SCHEMA_CONTENT_SIMPLE:
17882 xmlGenericError(xmlGenericErrorContext, "simple\n");
17883 break;
17884 case XML_SCHEMA_CONTENT_ELEMENTS:
17885 xmlGenericError(xmlGenericErrorContext, "elements\n");
17886 break;
17887 case XML_SCHEMA_CONTENT_UNKNOWN:
17888 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
17889 break;
17890 case XML_SCHEMA_CONTENT_EMPTY:
17891 xmlGenericError(xmlGenericErrorContext, "empty\n");
17892 break;
17893 case XML_SCHEMA_CONTENT_MIXED:
17894 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017895 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017896 xmlGenericError(xmlGenericErrorContext,
17897 "mixed as emptiable particle\n");
17898 else
17899 xmlGenericError(xmlGenericErrorContext, "mixed\n");
17900 break;
17901 /* Removed, since not used. */
17902 /*
17903 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
17904 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
17905 break;
17906 */
17907 case XML_SCHEMA_CONTENT_BASIC:
17908 xmlGenericError(xmlGenericErrorContext, "basic\n");
17909 break;
17910 default:
17911 xmlGenericError(xmlGenericErrorContext,
17912 "not registered !!!\n");
17913 break;
17914 }
Daniel Veillard8651f532002-04-17 09:06:27 +000017915 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017916}
Daniel Veillard8651f532002-04-17 09:06:27 +000017917#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017918
17919/*
17920* 3.14.6 Constraints on Simple Type Definition Schema Components
17921*/
17922static int
17923xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
17924 xmlSchemaTypePtr type)
17925{
17926 int res, olderrs = pctxt->nberrors;
17927
17928 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17929 return(-1);
17930
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017931 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017932 return(0);
17933
17934 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
17935 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
17936
17937 if (type->baseType == NULL) {
17938 PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
17939 "missing baseType");
17940 goto exit_failure;
17941 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017942 if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000017943 xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017944 /*
17945 * If a member type of a union is a union itself, we need to substitute
17946 * that member type for its member types.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017947 * NOTE that this might change in WXS 1.1; i.e. we will keep the union
17948 * types in WXS 1.1.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017949 */
17950 if ((type->memberTypes != NULL) &&
17951 (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
17952 return(-1);
17953 /*
17954 * SPEC src-simple-type 1
17955 * "The corresponding simple type definition, if any, must satisfy
17956 * the conditions set out in Constraints on Simple Type Definition
17957 * Schema Components (§3.14.6)."
17958 */
17959 /*
17960 * Schema Component Constraint: Simple Type Definition Properties Correct
17961 * (st-props-correct)
17962 */
17963 res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
17964 HFAILURE HERROR
17965 /*
17966 * Schema Component Constraint: Derivation Valid (Restriction, Simple)
17967 * (cos-st-restricts)
17968 */
17969 res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
17970 HFAILURE HERROR
17971 /*
17972 * TODO: Removed the error report, since it got annoying to get an
17973 * extra error report, if anything failed until now.
17974 * Enable this if needed.
17975 *
17976 * xmlSchemaPErr(ctxt, type->node,
17977 * XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
17978 * "Simple type '%s' does not satisfy the constraints "
17979 * "on simple type definitions.\n",
17980 * type->name, NULL);
17981 */
17982 /*
17983 * Schema Component Constraint: Simple Type Restriction (Facets)
17984 * (st-restrict-facets)
17985 */
17986 res = xmlSchemaCheckFacetValues(type, pctxt);
17987 HFAILURE HERROR
17988 if ((type->facetSet != NULL) ||
17989 (type->baseType->facetSet != NULL)) {
17990 res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
17991 HFAILURE HERROR
17992 }
17993 /*
17994 * Whitespace value.
17995 */
17996 res = xmlSchemaTypeFixupWhitespace(type);
17997 HFAILURE HERROR
17998 xmlSchemaTypeFixupOptimFacets(type);
17999
18000exit_error:
18001#ifdef DEBUG_TYPE
18002 xmlSchemaDebugFixedType(pctxt, type);
18003#endif
18004 if (olderrs != pctxt->nberrors)
18005 return(pctxt->err);
18006 return(0);
18007
18008exit_failure:
18009#ifdef DEBUG_TYPE
18010 xmlSchemaDebugFixedType(pctxt, type);
18011#endif
18012 return(-1);
18013}
18014
18015static int
18016xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18017 xmlSchemaTypePtr type)
18018{
18019 int res = 0, olderrs = pctxt->nberrors;
18020 xmlSchemaTypePtr baseType = type->baseType;
18021
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018022 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018023 return(0);
18024 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18025 if (baseType == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018026 PERROR_INT("xmlSchemaFixupComplexType",
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018027 "missing baseType");
18028 goto exit_failure;
18029 }
18030 /*
18031 * Fixup the base type.
18032 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018033 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018034 xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018035 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18036 /*
18037 * Skip fixup if the base type is invalid.
18038 * TODO: Generate a warning!
18039 */
18040 return(0);
18041 }
18042 /*
18043 * This basically checks if the base type can be derived.
18044 */
18045 res = xmlSchemaCheckSRCCT(pctxt, type);
18046 HFAILURE HERROR
18047 /*
18048 * Fixup the content type.
18049 */
18050 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18051 /*
18052 * Corresponds to <complexType><simpleContent>...
18053 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018054 if ((WXS_IS_COMPLEX(baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018055 (baseType->contentTypeDef != NULL) &&
18056 (WXS_IS_RESTRICTION(type))) {
18057 xmlSchemaTypePtr contentBase, content;
18058#ifdef ENABLE_NAMED_LOCALS
18059 char buf[30];
18060 const xmlChar *tmpname;
18061#endif
18062 /*
18063 * SPEC (1) If <restriction> + base type is <complexType>,
18064 * "whose own {content type} is a simple type..."
18065 */
18066 if (type->contentTypeDef != NULL) {
18067 /*
18068 * SPEC (1.1) "the simple type definition corresponding to the
18069 * <simpleType> among the [children] of <restriction> if there
18070 * is one;"
18071 * Note that this "<simpleType> among the [children]" was put
18072 * into ->contentTypeDef during parsing.
18073 */
18074 contentBase = type->contentTypeDef;
18075 type->contentTypeDef = NULL;
18076 } else {
18077 /*
18078 * (1.2) "...otherwise (<restriction> has no <simpleType>
18079 * among its [children]), the simple type definition which
18080 * is the {content type} of the ... base type."
18081 */
18082 contentBase = baseType->contentTypeDef;
18083 }
18084 /*
18085 * SPEC
18086 * "... a simple type definition which restricts the simple
18087 * type definition identified in clause 1.1 or clause 1.2
18088 * with a set of facet components"
18089 *
18090 * Create the anonymous simple type, which will be the content
18091 * type of the complex type.
18092 */
18093#ifdef ENABLE_NAMED_LOCALS
18094 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18095 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018096 content = xmlSchemaAddType(pctxt, pctxt->schema,
18097 XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018098 type->node, 0);
18099#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018100 content = xmlSchemaAddType(pctxt, pctxt->schema,
18101 XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018102 type->node, 0);
18103#endif
18104 if (content == NULL)
18105 goto exit_failure;
18106 /*
18107 * We will use the same node as for the <complexType>
18108 * to have it somehow anchored in the schema doc.
18109 */
18110 content->type = XML_SCHEMA_TYPE_SIMPLE;
18111 content->baseType = contentBase;
18112 /*
18113 * Move the facets, previously anchored on the
18114 * complexType during parsing.
18115 */
18116 content->facets = type->facets;
18117 type->facets = NULL;
18118 content->facetSet = type->facetSet;
18119 type->facetSet = NULL;
18120
18121 type->contentTypeDef = content;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018122 if (WXS_IS_TYPE_NOT_FIXED(contentBase))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018123 xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018124 /*
18125 * Fixup the newly created type. We don't need to check
18126 * for circularity here.
18127 */
18128 res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18129 HFAILURE HERROR
18130 res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18131 HFAILURE HERROR
18132
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018133 } else if ((WXS_IS_COMPLEX(baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018134 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18135 (WXS_IS_RESTRICTION(type))) {
18136 /*
18137 * SPEC (2) If <restriction> + base is a mixed <complexType> with
18138 * an emptiable particle, then a simple type definition which
18139 * restricts the <restriction>'s <simpleType> child.
18140 */
18141 if ((type->contentTypeDef == NULL) ||
18142 (type->contentTypeDef->baseType == NULL)) {
18143 /*
18144 * TODO: Check if this ever happens.
18145 */
18146 xmlSchemaPCustomErr(pctxt,
18147 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018148 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018149 "Internal error: xmlSchemaTypeFixup, "
18150 "complex type '%s': the <simpleContent><restriction> "
18151 "is missing a <simpleType> child, but was not catched "
18152 "by xmlSchemaCheckSRCCT()", type->name);
18153 goto exit_failure;
18154 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018155 } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018156 /*
18157 * SPEC (3) If <extension> + base is <complexType> with
18158 * <simpleType> content, "...then the {content type} of that
18159 * complex type definition"
18160 */
18161 if (baseType->contentTypeDef == NULL) {
18162 /*
18163 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18164 * should have catched this already.
18165 */
18166 xmlSchemaPCustomErr(pctxt,
18167 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018168 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018169 "Internal error: xmlSchemaTypeFixup, "
18170 "complex type '%s': the <extension>ed base type is "
18171 "a complex type with no simple content type",
18172 type->name);
18173 goto exit_failure;
18174 }
18175 type->contentTypeDef = baseType->contentTypeDef;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018176 } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018177 /*
18178 * SPEC (4) <extension> + base is <simpleType>
18179 * "... then that simple type definition"
18180 */
18181 type->contentTypeDef = baseType;
18182 } else {
18183 /*
18184 * TODO: Check if this ever happens.
18185 */
18186 xmlSchemaPCustomErr(pctxt,
18187 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018188 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018189 "Internal error: xmlSchemaTypeFixup, "
18190 "complex type '%s' with <simpleContent>: unhandled "
18191 "derivation case", type->name);
18192 goto exit_failure;
18193 }
18194 } else {
18195 int dummySequence = 0;
18196 xmlSchemaParticlePtr particle =
18197 (xmlSchemaParticlePtr) type->subtypes;
18198 /*
18199 * Corresponds to <complexType><complexContent>...
18200 *
18201 * NOTE that the effective mixed was already set during parsing of
18202 * <complexType> and <complexContent>; its flag value is
18203 * XML_SCHEMAS_TYPE_MIXED.
18204 *
18205 * Compute the "effective content":
18206 * (2.1.1) + (2.1.2) + (2.1.3)
18207 */
18208 if ((particle == NULL) ||
18209 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18210 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18211 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18212 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18213 (particle->minOccurs == 0))) &&
18214 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18215 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18216 /*
18217 * SPEC (2.1.4) "If the ·effective mixed· is true, then
18218 * a particle whose properties are as follows:..."
18219 *
18220 * Empty sequence model group with
18221 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18222 * NOTE that we sill assign it the <complexType> node to
18223 * somehow anchor it in the doc.
18224 */
18225 if ((particle == NULL) ||
18226 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18227 /*
18228 * Create the particle.
18229 */
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000018230 particle = xmlSchemaAddParticle(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018231 type->node, 1, 1);
18232 if (particle == NULL)
18233 goto exit_failure;
18234 /*
18235 * Create the model group.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018236 */ /* URGENT TODO: avoid adding to pending items. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018237 particle->children = (xmlSchemaTreeItemPtr)
18238 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18239 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18240 if (particle->children == NULL)
18241 goto exit_failure;
18242
18243 type->subtypes = (xmlSchemaTypePtr) particle;
18244 }
18245 dummySequence = 1;
18246 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18247 } else {
18248 /*
18249 * SPEC (2.1.5) "otherwise empty"
18250 */
18251 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18252 }
18253 } else {
18254 /*
18255 * SPEC (2.2) "otherwise the particle corresponding to the
18256 * <all>, <choice>, <group> or <sequence> among the
18257 * [children]."
18258 */
18259 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18260 }
18261 /*
18262 * Compute the "content type".
18263 */
18264 if (WXS_IS_RESTRICTION(type)) {
18265 /*
18266 * SPEC (3.1) "If <restriction>..."
18267 * (3.1.1) + (3.1.2) */
18268 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18269 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18270 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18271 }
18272 } else {
18273 /*
18274 * SPEC (3.2) "If <extension>..."
18275 */
18276 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18277 /*
18278 * SPEC (3.2.1)
18279 */
18280 type->contentType = baseType->contentType;
18281 type->subtypes = baseType->subtypes;
18282 /*
18283 * NOTE that the effective mixed is ignored here.
18284 */
18285 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18286 /*
18287 * SPEC (3.2.2)
18288 */
18289 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18290 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18291 } else {
18292 /*
18293 * SPEC (3.2.3)
18294 */
18295 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18296 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18297 /*
18298 * "A model group whose {compositor} is sequence and whose
18299 * {particles} are..."
18300 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018301 if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18302 (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18303 ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18304 XML_SCHEMA_TYPE_ALL))
18305 {
18306 /*
18307 * SPEC cos-all-limited (1)
18308 */
18309 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18310 /* TODO: error code */
18311 XML_SCHEMAP_COS_ALL_LIMITED,
18312 WXS_ITEM_NODE(type), NULL,
18313 "The type has an 'all' model group in its "
18314 "{content type} and thus cannot be derived from "
18315 "a non-empty type, since this would produce a "
18316 "'sequence' model group containing the 'all' "
18317 "model group; 'all' model groups are not "
18318 "allowed to appear inside other model groups",
18319 NULL, NULL);
18320
18321 } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18322 (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18323 ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18324 XML_SCHEMA_TYPE_ALL))
18325 {
18326 /*
18327 * SPEC cos-all-limited (1)
18328 */
18329 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18330 /* TODO: error code */
18331 XML_SCHEMAP_COS_ALL_LIMITED,
18332 WXS_ITEM_NODE(type), NULL,
18333 "A type cannot be derived by extension from a type "
18334 "which has an 'all' model group in its "
18335 "{content type}, since this would produce a "
18336 "'sequence' model group containing the 'all' "
18337 "model group; 'all' model groups are not "
18338 "allowed to appear inside other model groups",
18339 NULL, NULL);
18340
18341 } else if (! dummySequence) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018342 xmlSchemaTreeItemPtr effectiveContent =
18343 (xmlSchemaTreeItemPtr) type->subtypes;
18344 /*
18345 * Create the particle.
18346 */
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000018347 particle = xmlSchemaAddParticle(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018348 type->node, 1, 1);
18349 if (particle == NULL)
18350 goto exit_failure;
18351 /*
18352 * Create the "sequence" model group.
18353 */
18354 particle->children = (xmlSchemaTreeItemPtr)
18355 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18356 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18357 if (particle->children == NULL)
18358 goto exit_failure;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018359 WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018360 /*
18361 * SPEC "the particle of the {content type} of
18362 * the ... base ..."
18363 * Create a duplicate of the base type's particle
18364 * and assign its "term" to it.
18365 */
18366 particle->children->children =
18367 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000018368 type->node,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018369 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
18370 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
18371 if (particle->children->children == NULL)
18372 goto exit_failure;
18373 particle = (xmlSchemaParticlePtr)
18374 particle->children->children;
18375 particle->children =
18376 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
18377 /*
18378 * SPEC "followed by the ·effective content·."
18379 */
18380 particle->next = effectiveContent;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018381 /*
18382 * This all will result in:
18383 * new-particle
18384 * --> new-sequence(
18385 * new-particle
18386 * --> base-model,
18387 * this-particle
18388 * --> this-model
18389 * )
18390 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018391 } else {
18392 /*
18393 * This is the case when there is already an empty
18394 * <sequence> with minOccurs==maxOccurs==1.
18395 * Just add the base types's content type.
18396 * NOTE that, although we miss to add an intermediate
18397 * <sequence>, this should produce no difference to
18398 * neither the regex compilation of the content model,
18399 * nor to the complex type contraints.
18400 */
18401 particle->children->children =
18402 (xmlSchemaTreeItemPtr) baseType->subtypes;
18403 }
18404 }
18405 }
18406 }
18407 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018408 * Now fixup attribute uses:
18409 * - expand attr. group references
18410 * - intersect attribute wildcards
18411 * - inherit attribute uses of the base type
18412 * - inherit or union attr. wildcards if extending
18413 * - apply attr. use prohibitions if restricting
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018414 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018415 res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018416 HFAILURE HERROR
18417 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018418 * Apply the complex type component constraints; this will not
18419 * check attributes, since this is done in
18420 * xmlSchemaFixupTypeAttributeUses().
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018421 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018422 res = xmlSchemaCheckCTComponent(pctxt, type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018423 HFAILURE HERROR
18424
18425#ifdef DEBUG_TYPE
18426 xmlSchemaDebugFixedType(pctxt, type);
18427#endif
18428 if (olderrs != pctxt->nberrors)
18429 return(pctxt->err);
18430 else
18431 return(0);
18432
18433exit_error:
18434 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18435#ifdef DEBUG_TYPE
18436 xmlSchemaDebugFixedType(pctxt, type);
18437#endif
18438 return(pctxt->err);
18439
18440exit_failure:
18441 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18442#ifdef DEBUG_TYPE
18443 xmlSchemaDebugFixedType(pctxt, type);
18444#endif
18445 return(-1);
18446}
18447
18448
18449/**
18450 * xmlSchemaTypeFixup:
18451 * @typeDecl: the schema type definition
18452 * @ctxt: the schema parser context
18453 *
18454 * Fixes the content model of the type.
18455 * URGENT TODO: We need an int result!
18456 */
18457static int
18458xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018459 xmlSchemaAbstractCtxtPtr actxt)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018460{
18461 if (type == NULL)
18462 return(0);
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018463 if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18464 AERROR_INT("xmlSchemaTypeFixup",
18465 "this function needs a parser context");
18466 return(-1);
18467 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018468 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018469 return(0);
18470 if (type->type == XML_SCHEMA_TYPE_COMPLEX)
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018471 return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018472 else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018473 return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018474 return(0);
Daniel Veillard4255d502002-04-16 15:50:10 +000018475}
18476
18477/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018478 * xmlSchemaCheckFacet:
18479 * @facet: the facet
18480 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000018481 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018482 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018483 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018484 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018485 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018486 * Returns 0 if valid, a positive error code if not valid and
18487 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018488 */
18489int
18490xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018491 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018492 xmlSchemaParserCtxtPtr pctxt,
18493 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018494{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018495 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018496
Daniel Veillardce682bc2004-11-05 17:22:25 +000018497 if ((facet == NULL) || (typeDecl == NULL))
18498 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018499 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018500 * TODO: will the parser context be given if used from
18501 * the relaxNG module?
18502 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018503 if (pctxt == NULL)
18504 ctxtGiven = 0;
18505 else
18506 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018507
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018508 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018509 case XML_SCHEMA_FACET_MININCLUSIVE:
18510 case XML_SCHEMA_FACET_MINEXCLUSIVE:
18511 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018512 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18513 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018514 /*
18515 * Okay we need to validate the value
18516 * at that point.
18517 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018518 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018519
18520 /* 4.3.5.5 Constraints on enumeration Schema Components
18521 * Schema Component Constraint: enumeration valid restriction
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018522 * It is an ·error· if any member of {value} is not in the
18523 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018524 *
18525 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018526 * The value ·must· be in the
18527 * ·value space· of the ·base type·.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018528 */
18529 /*
18530 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018531 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018532 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018533 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018534 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018535 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018536 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018537 */
18538 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18539 base = typeDecl->baseType;
18540 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018541 PERROR_INT("xmlSchemaCheckFacet",
18542 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018543 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018544 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018545 } else
18546 base = typeDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018547
18548 if (! ctxtGiven) {
18549 /*
18550 * A context is needed if called from RelaxNG.
18551 */
18552 pctxt = xmlSchemaNewParserCtxt("*");
18553 if (pctxt == NULL)
18554 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018555 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018556 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018557 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018558 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018559 * facet->node is just the node holding the facet
18560 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018561 * of the facet.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018562 */
18563 ret = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018564 ACTXT_CAST pctxt, facet->node, base,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018565 facet->value, &(facet->val), 1, 1, 0);
18566 if (ret != 0) {
18567 if (ret < 0) {
18568 /* No error message for RelaxNG. */
18569 if (ctxtGiven) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018570 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018571 XML_SCHEMAP_INTERNAL, facet->node, NULL,
18572 "Internal error: xmlSchemaCheckFacet, "
18573 "failed to validate the value '%s' of the "
18574 "facet '%s' against the base type",
18575 facet->value, xmlSchemaFacetTypeToString(facet->type));
18576 }
18577 goto internal_error;
18578 }
18579 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18580 /* No error message for RelaxNG. */
18581 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018582 xmlChar *str = NULL;
18583
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018584 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018585 ret, facet->node, WXS_BASIC_CAST facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018586 "The value '%s' of the facet does not validate "
18587 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018588 facet->value,
18589 xmlSchemaFormatQName(&str,
18590 base->targetNamespace, base->name));
18591 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018592 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018593 goto exit;
18594 } else if (facet->val == NULL) {
18595 if (ctxtGiven) {
18596 PERROR_INT("xmlSchemaCheckFacet",
18597 "value was not computed");
18598 }
18599 TODO
18600 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018601 break;
18602 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018603 case XML_SCHEMA_FACET_PATTERN:
18604 facet->regexp = xmlRegexpCompile(facet->value);
18605 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018606 ret = XML_SCHEMAP_REGEXP_INVALID;
18607 /* No error message for RelaxNG. */
18608 if (ctxtGiven) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018609 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018610 ret, facet->node, WXS_BASIC_CAST typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018611 "The value '%s' of the facet 'pattern' is not a "
18612 "valid regular expression",
18613 facet->value, NULL);
18614 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018615 }
18616 break;
18617 case XML_SCHEMA_FACET_TOTALDIGITS:
18618 case XML_SCHEMA_FACET_FRACTIONDIGITS:
18619 case XML_SCHEMA_FACET_LENGTH:
18620 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018621 case XML_SCHEMA_FACET_MINLENGTH:
18622
18623 if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18624 ret = xmlSchemaValidatePredefinedType(
18625 xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18626 facet->value, &(facet->val));
18627 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018628 ret = xmlSchemaValidatePredefinedType(
18629 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18630 facet->value, &(facet->val));
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018631 }
18632 if (ret != 0) {
18633 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018634 /* No error message for RelaxNG. */
18635 if (ctxtGiven) {
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018636 PERROR_INT("xmlSchemaCheckFacet",
18637 "validating facet value");
18638 }
18639 goto internal_error;
18640 }
18641 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18642 /* No error message for RelaxNG. */
18643 if (ctxtGiven) {
18644 /* error code */
18645 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18646 ret, facet->node, WXS_BASIC_CAST typeDecl,
18647 "The value '%s' of the facet '%s' is not a valid '%s'",
18648 facet->value,
18649 xmlSchemaFacetTypeToString(facet->type),
18650 (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18651 BAD_CAST "nonNegativeInteger" :
18652 BAD_CAST "positiveInteger",
18653 NULL);
18654 }
18655 }
18656 break;
18657
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018658 case XML_SCHEMA_FACET_WHITESPACE:{
18659 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18660 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18661 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18662 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18663 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18664 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18665 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018666 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18667 /* No error message for RelaxNG. */
18668 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018669 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018670 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018671 ret, facet->node, WXS_BASIC_CAST typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018672 "The value '%s' of the facet 'whitespace' is not "
18673 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018674 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018675 }
18676 }
18677 default:
18678 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018679 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018680exit:
18681 if ((! ctxtGiven) && (pctxt != NULL))
18682 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018683 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018684internal_error:
18685 if ((! ctxtGiven) && (pctxt != NULL))
18686 xmlSchemaFreeParserCtxt(pctxt);
18687 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018688}
18689
18690/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018691 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000018692 * @typeDecl: the schema type definition
18693 * @ctxt: the schema parser context
18694 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018695 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000018696 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018697static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018698xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018699 xmlSchemaParserCtxtPtr pctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000018700{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018701 int res, olderrs = pctxt->nberrors;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018702 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018703 /*
18704 * NOTE: It is intended to use the facets list, instead
18705 * of facetSet.
18706 */
18707 if (typeDecl->facets != NULL) {
18708 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018709
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018710 /*
18711 * Temporarily assign the "schema" to the validation context
18712 * of the parser context. This is needed for NOTATION validation.
18713 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018714 if (pctxt->vctxt == NULL) {
18715 if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18716 return(-1);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018717 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018718 pctxt->vctxt->schema = pctxt->schema;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018719 while (facet != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018720 res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18721 HFAILURE
Daniel Veillard01fa6152004-06-29 17:04:39 +000018722 facet = facet->next;
18723 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018724 pctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018725 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018726 if (olderrs != pctxt->nberrors)
18727 return(pctxt->err);
18728 return(0);
18729exit_failure:
18730 return(-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018731}
18732
18733/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018734 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018735 * @ctxtMGroup: the searched model group
18736 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018737 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018738 *
18739 * This one is intended to be used by
18740 * xmlSchemaCheckGroupDefCircular only.
18741 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018742 * Returns the particle with the circular model group definition reference,
18743 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018744 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018745static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018746xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018747 xmlSchemaTreeItemPtr particle)
18748{
18749 xmlSchemaTreeItemPtr circ = NULL;
18750 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018751 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018752
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018753 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018754 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018755 if (term == NULL)
18756 continue;
18757 switch (term->type) {
18758 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018759 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018760 if (gdef == groupDef)
18761 return (particle);
18762 /*
18763 * Mark this model group definition to avoid infinite
18764 * recursion on circular references not yet examined.
18765 */
18766 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18767 continue;
18768 if (gdef->children != NULL) {
18769 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18770 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18771 gdef->children->children);
18772 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18773 if (circ != NULL)
18774 return (circ);
18775 }
18776 break;
18777 case XML_SCHEMA_TYPE_SEQUENCE:
18778 case XML_SCHEMA_TYPE_CHOICE:
18779 case XML_SCHEMA_TYPE_ALL:
18780 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18781 if (circ != NULL)
18782 return (circ);
18783 break;
18784 default:
18785 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018786 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018787 }
18788 return (NULL);
18789}
18790
18791/**
18792 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018793 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018794 * @ctxt: the parser context
18795 * @name: the name
18796 *
18797 * Checks for circular references to model group definitions.
18798 */
18799static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018800xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018801 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018802{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018803 /*
18804 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018805 * 2 Circular groups are disallowed. That is, within the {particles}
18806 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018807 * is the group itself.
18808 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018809 if ((item == NULL) ||
18810 (item->type != XML_SCHEMA_TYPE_GROUP) ||
18811 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018812 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018813 {
18814 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018815
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018816 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018817 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018818 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018819 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018820 * TODO: The error report is not adequate: this constraint
18821 * is defined for model groups but not definitions, but since
18822 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018823 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018824 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018825 */
18826 xmlSchemaPCustomErr(ctxt,
18827 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018828 NULL, WXS_ITEM_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018829 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018830 "defined", xmlSchemaFormatQName(&str,
18831 item->targetNamespace, item->name));
18832 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018833 /*
18834 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018835 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018836 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018837 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018838 }
18839 }
18840}
18841
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018842/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018843 * xmlSchemaModelGroupToModelGroupDefFixup:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018844 * @ctxt: the parser context
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018845 * @mg: the model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018846 *
18847 * Assigns the model group of model group definitions to the "term"
18848 * of the referencing particle.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018849 * In xmlSchemaResolveModelGroupParticleReferences the model group
18850 * definitions were assigned to the "term", since needed for the
18851 * circularity check.
18852 *
18853 * Schema Component Constraint:
18854 * All Group Limited (cos-all-limited) (1.2)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018855 */
18856static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018857xmlSchemaModelGroupToModelGroupDefFixup(
18858 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18859 xmlSchemaModelGroupPtr mg)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018860{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018861 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
18862
18863 while (particle != NULL) {
18864 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
18865 ((WXS_PARTICLE_TERM(particle))->type !=
18866 XML_SCHEMA_TYPE_GROUP))
18867 {
18868 particle = WXS_PTC_CAST particle->next;
18869 continue;
18870 }
18871 if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
18872 /*
18873 * TODO: Remove the particle.
18874 */
18875 WXS_PARTICLE_TERM(particle) = NULL;
18876 particle = WXS_PTC_CAST particle->next;
18877 continue;
18878 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018879 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018880 * Assign the model group to the {term} of the particle.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018881 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018882 WXS_PARTICLE_TERM(particle) =
18883 WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
18884
18885 particle = WXS_PTC_CAST particle->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018886 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018887}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018888
18889/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018890 * xmlSchemaCheckAttrGroupCircularRecur:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018891 * @ctxtGr: the searched attribute group
18892 * @attr: the current attribute list to be processed
18893 *
18894 * This one is intended to be used by
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018895 * xmlSchemaCheckAttrGroupCircular only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018896 *
18897 * Returns the circular attribute grou reference, otherwise NULL.
18898 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018899static xmlSchemaQNameRefPtr
18900xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
18901 xmlSchemaItemListPtr list)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018902{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018903 xmlSchemaAttributeGroupPtr gr;
18904 xmlSchemaQNameRefPtr ref, circ;
18905 int i;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018906 /*
18907 * We will search for an attribute group reference which
18908 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018909 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018910 for (i = 0; i < list->nbItems; i++) {
18911 ref = list->items[i];
18912 if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
18913 (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
18914 (ref->item != NULL))
18915 {
18916 gr = WXS_ATTR_GROUP_CAST ref->item;
18917 if (gr == ctxtGr)
18918 return(ref);
18919 if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
18920 continue;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018921 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018922 * Mark as visited to avoid infinite recursion on
18923 * circular references not yet examined.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018924 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018925 if ((gr->attrUses) &&
18926 (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
18927 {
18928 gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
18929 circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
18930 (xmlSchemaItemListPtr) gr->attrUses);
18931 gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
18932 if (circ != NULL)
18933 return (circ);
18934 }
18935
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018936 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018937 }
18938 return (NULL);
18939}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018940
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018941/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018942 * xmlSchemaCheckAttrGroupCircular:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018943 * attrGr: the attribute group definition
18944 * @ctxt: the parser context
18945 * @name: the name
18946 *
18947 * Checks for circular references of attribute groups.
18948 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018949static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018950xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018951 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018952{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018953 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018954 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018955 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018956 * 3 Circular group reference is disallowed outside <redefine>.
18957 * That is, unless this element information item's parent is
18958 * <redefine>, then among the [children], if any, there must
18959 * not be an <attributeGroup> with ref [attribute] which resolves
18960 * to the component corresponding to this <attributeGroup>. Indirect
18961 * circularity is also ruled out. That is, when QName resolution
18962 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
18963 * any <attributeGroup>s with a ref [attribute] among the [children],
18964 * it must not be the case that a ·QName· is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018965 * which resolves to the component corresponding to this <attributeGroup>.
18966 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018967 if (attrGr->attrUses == NULL)
18968 return(0);
18969 else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
18970 return(0);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018971 else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018972 xmlSchemaQNameRefPtr circ;
18973
18974 circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
18975 (xmlSchemaItemListPtr) attrGr->attrUses);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018976 if (circ != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018977 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018978 /*
18979 * TODO: Report the referenced attr group as QName.
18980 */
18981 xmlSchemaPCustomErr(ctxt,
18982 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018983 NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018984 "Circular reference to the attribute group '%s' "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018985 "defined", xmlSchemaGetComponentQName(&str, attrGr));
18986 FREE_AND_NULL(str);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018987 /*
18988 * NOTE: We will cut the reference to avoid further
18989 * confusion of the processor.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018990 * BADSPEC TODO: The spec should define how to process in this case.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018991 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018992 circ->item = NULL;
18993 return(ctxt->err);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018994 }
18995 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018996 return(0);
18997}
18998
18999static int
19000xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19001 xmlSchemaAttributeGroupPtr attrGr);
19002
19003/**
19004 * xmlSchemaExpandAttributeGroupRefs:
19005 * @pctxt: the parser context
19006 * @node: the node of the component holding the attribute uses
19007 * @completeWild: the intersected wildcard to be returned
19008 * @list: the attribute uses
19009 *
19010 * Substitutes contained attribute group references
19011 * for their attribute uses. Wilcards are intersected.
19012 * Attribute use prohibitions are removed from the list
19013 * and returned via the @prohibs list.
19014 * Pointlessness of attr. prohibs, if a matching attr. decl
19015 * is existent a well, are checked.
19016 */
19017static int
19018xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19019 xmlSchemaBasicItemPtr item,
19020 xmlSchemaWildcardPtr *completeWild,
19021 xmlSchemaItemListPtr list,
19022 xmlSchemaItemListPtr prohibs)
19023{
19024 xmlSchemaAttributeGroupPtr gr;
19025 xmlSchemaAttributeUsePtr use;
19026 xmlSchemaItemListPtr sublist;
19027 int i, j;
19028 int created = (*completeWild == NULL) ? 0 : 1;
19029
19030 if (prohibs)
19031 prohibs->nbItems = 0;
19032
19033 for (i = 0; i < list->nbItems; i++) {
19034 use = list->items[i];
19035
19036 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19037 if (prohibs == NULL) {
19038 PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19039 "unexpected attr prohibition found");
19040 return(-1);
19041 }
19042 /*
19043 * Remove from attribute uses.
19044 */
19045 if (xmlSchemaItemListRemove(list, i) == -1)
19046 return(-1);
19047 i--;
19048 /*
19049 * Note that duplicate prohibitions were already
19050 * handled at parsing time.
19051 */
19052 /*
19053 * Add to list of prohibitions.
19054 */
19055 xmlSchemaItemListAddSize(prohibs, 2, use);
19056 continue;
19057 }
19058 if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19059 ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19060 {
19061 if ((WXS_QNAME_CAST use)->item == NULL)
19062 return(-1);
19063 gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19064 /*
19065 * Expand the referenced attr. group.
19066 * TODO: remove this, this is done in a previous step, so
19067 * already done here.
19068 */
19069 if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19070 if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19071 return(-1);
19072 }
19073 /*
19074 * Build the 'complete' wildcard; i.e. intersect multiple
19075 * wildcards.
19076 */
19077 if (gr->attributeWildcard != NULL) {
19078 if (*completeWild == NULL) {
19079 *completeWild = gr->attributeWildcard;
19080 } else {
19081 if (! created) {
19082 xmlSchemaWildcardPtr tmpWild;
19083
19084 /*
19085 * Copy the first encountered wildcard as context,
19086 * except for the annotation.
19087 *
19088 * Although the complete wildcard might not correspond
19089 * to any node in the schema, we will anchor it on
19090 * the node of the owner component.
19091 */
19092 tmpWild = xmlSchemaAddWildcard(pctxt, pctxt->schema,
19093 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19094 WXS_ITEM_NODE(item));
19095 if (tmpWild == NULL)
19096 return(-1);
19097 if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19098 tmpWild, *completeWild) == -1)
19099 return (-1);
19100 tmpWild->processContents = (*completeWild)->processContents;
19101 *completeWild = tmpWild;
19102 created = 1;
19103 }
19104
19105 if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19106 gr->attributeWildcard) == -1)
19107 return(-1);
19108 }
19109 }
19110 /*
19111 * Just remove the reference if the referenced group does not
19112 * contain any attribute uses.
19113 */
19114 if (gr->attrUses == NULL) {
19115 if (xmlSchemaItemListRemove(list, i) == -1)
19116 return(-1);
19117 i--;
19118 continue;
19119 }
19120 /*
19121 * Add the attribute uses.
19122 */
19123 sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19124 if (sublist->nbItems != 0) {
19125 list->items[i] = sublist->items[0];
19126 if (sublist->nbItems != 1) {
19127 for (j = 1; j < sublist->nbItems; j++) {
19128 i++;
19129 if (xmlSchemaItemListInsert(list,
19130 sublist->items[j], i) == -1)
19131 return(-1);
19132 }
19133 }
19134 }
19135 }
19136
19137 }
19138 /*
19139 * Handle pointless prohibitions of declared attributes.
19140 */
19141 if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19142 xmlSchemaAttributeUseProhibPtr prohib;
19143
19144 for (i = prohibs->nbItems -1; i >= 0; i--) {
19145 prohib = prohibs->items[i];
19146 for (j = 0; j < list->nbItems; j++) {
19147 use = list->items[j];
19148
19149 if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19150 (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19151 {
19152 xmlChar *str = NULL;
19153
19154 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19155 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19156 prohib->node, NULL,
19157 "Skipping pointless attribute use prohibition "
19158 "'%s', since a corresponding attribute use "
19159 "exists already in the type definition",
19160 xmlSchemaFormatQName(&str,
19161 prohib->targetNamespace, prohib->name),
19162 NULL, NULL);
19163 FREE_AND_NULL(str);
19164 /*
19165 * Remove the prohibition.
19166 */
19167 if (xmlSchemaItemListRemove(prohibs, i) == -1)
19168 return(-1);
19169 break;
19170 }
19171 }
19172 }
19173 }
19174 return(0);
19175}
19176
19177/**
19178 * xmlSchemaAttributeGroupExpandRefs:
19179 * @pctxt: the parser context
19180 * @attrGr: the attribute group definition
19181 *
19182 * Computation of:
19183 * {attribute uses} property
19184 * {attribute wildcard} property
19185 *
19186 * Substitutes contained attribute group references
19187 * for their attribute uses. Wilcards are intersected.
19188 */
19189static int
19190xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19191 xmlSchemaAttributeGroupPtr attrGr)
19192{
19193 if ((attrGr->attrUses == NULL) ||
19194 (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19195 return(0);
19196
19197 attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19198 if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19199 &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19200 return(-1);
19201 return(0);
19202}
19203
19204/**
19205 * xmlSchemaAttributeGroupExpandRefs:
19206 * @pctxt: the parser context
19207 * @attrGr: the attribute group definition
19208 *
19209 * Substitutes contained attribute group references
19210 * for their attribute uses. Wilcards are intersected.
19211 *
19212 * Schema Component Constraint:
19213 * Attribute Group Definition Properties Correct (ag-props-correct)
19214 */
19215static int
19216xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19217 xmlSchemaAttributeGroupPtr attrGr)
19218{
19219 /*
19220 * SPEC ag-props-correct
19221 * (1) "The values of the properties of an attribute group definition
19222 * must be as described in the property tableau in The Attribute
19223 * Group Definition Schema Component (§3.6.1), modulo the impact of
19224 * Missing Sub-components (§5.3);"
19225 */
19226
19227 if ((attrGr->attrUses != NULL) &&
19228 (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19229 {
19230 xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19231 xmlSchemaAttributeUsePtr use, tmp;
19232 int i, j, hasId = 0;
19233
19234 for (i = uses->nbItems -1; i >= 0; i--) {
19235 use = uses->items[i];
19236 /*
19237 * SPEC ag-props-correct
19238 * (2) "Two distinct members of the {attribute uses} must not have
19239 * {attribute declaration}s both of whose {name}s match and whose
19240 * {target namespace}s are identical."
19241 */
19242 if (i > 0) {
19243 for (j = i -1; j >= 0; j--) {
19244 tmp = uses->items[j];
19245 if ((WXS_ATTRUSE_DECL_NAME(use) ==
19246 WXS_ATTRUSE_DECL_NAME(tmp)) &&
19247 (WXS_ATTRUSE_DECL_TNS(use) ==
19248 WXS_ATTRUSE_DECL_TNS(tmp)))
19249 {
19250 xmlChar *str = NULL;
19251
19252 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19253 XML_SCHEMAP_AG_PROPS_CORRECT,
19254 attrGr->node, WXS_BASIC_CAST attrGr,
19255 "Duplicate %s",
19256 xmlSchemaGetComponentDesignation(&str, use),
19257 NULL);
19258 FREE_AND_NULL(str);
19259 /*
19260 * Remove the duplicate.
19261 */
19262 if (xmlSchemaItemListRemove(uses, i) == -1)
19263 return(-1);
19264 goto next_use;
19265 }
19266 }
19267 }
19268 /*
19269 * SPEC ag-props-correct
19270 * (3) "Two distinct members of the {attribute uses} must not have
19271 * {attribute declaration}s both of whose {type definition}s are or
19272 * are derived from ID."
19273 * TODO: Does 'derived' include member-types of unions?
19274 */
19275 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19276 if (xmlSchemaIsDerivedFromBuiltInType(
19277 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19278 {
19279 if (hasId) {
19280 xmlChar *str = NULL;
19281
19282 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19283 XML_SCHEMAP_AG_PROPS_CORRECT,
19284 attrGr->node, WXS_BASIC_CAST attrGr,
19285 "There must not exist more than one attribute "
19286 "declaration of type 'xs:ID' "
19287 "(or derived from 'xs:ID'). The %s violates this "
19288 "constraint",
19289 xmlSchemaGetComponentDesignation(&str, use),
19290 NULL);
19291 FREE_AND_NULL(str);
19292 if (xmlSchemaItemListRemove(uses, i) == -1)
19293 return(-1);
19294 }
19295 hasId = 1;
19296 }
19297 }
19298next_use: {}
19299 }
19300 }
19301 return(0);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019302}
19303
19304/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019305 * xmlSchemaResolveAttrGroupReferences:
Daniel Veillard13e04c62002-04-23 17:51:29 +000019306 * @attrgrpDecl: the schema attribute definition
19307 * @ctxt: the schema parser context
19308 * @name: the attribute name
19309 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019310 * Resolves references to attribute group definitions.
Daniel Veillard13e04c62002-04-23 17:51:29 +000019311 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019312static int
19313xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19314 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard13e04c62002-04-23 17:51:29 +000019315{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019316 xmlSchemaAttributeGroupPtr group;
Daniel Veillard13e04c62002-04-23 17:51:29 +000019317
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019318 if (ref->item != NULL)
19319 return(0);
19320 group = xmlSchemaGetAttributeGroup(ctxt->schema,
19321 ref->name,
19322 ref->targetNamespace);
19323 if (group == NULL) {
19324 xmlSchemaPResCompAttrErr(ctxt,
19325 XML_SCHEMAP_SRC_RESOLVE,
19326 NULL, ref->node,
19327 "ref", ref->name, ref->targetNamespace,
19328 ref->itemType, NULL);
19329 return(ctxt->err);
Daniel Veillard3646d642004-06-02 19:19:14 +000019330 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019331 ref->item = WXS_BASIC_CAST group;
19332 return(0);
Daniel Veillard13e04c62002-04-23 17:51:29 +000019333}
19334
19335/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019336 * xmlSchemaCheckAttrPropsCorrect:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019337 * @item: an schema attribute declaration/use
19338 * @ctxt: a schema parser context
19339 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019340 *
19341 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019342 * Schema Component Constraint:
19343 * Attribute Declaration Properties Correct (a-props-correct)
Daniel Veillard4255d502002-04-16 15:50:10 +000019344 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019345 * Validates the value constraints of an attribute declaration/use.
19346 * NOTE that this needs the simle type definitions to be already
19347 * builded and checked.
Daniel Veillard4255d502002-04-16 15:50:10 +000019348 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019349static int
19350xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19351 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019352{
19353
19354 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019355 * SPEC a-props-correct (1)
19356 * "The values of the properties of an attribute declaration must
19357 * be as described in the property tableau in The Attribute
19358 * Declaration Schema Component (§3.2.1), modulo the impact of
19359 * Missing Sub-components (§5.3)."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019360 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019361
19362 if (WXS_ATTR_TYPEDEF(attr) == NULL)
19363 return(0);
19364
19365 if (attr->defValue != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019366 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019367
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019368 /*
19369 * SPEC a-props-correct (3)
19370 * "If the {type definition} is or is derived from ID then there
19371 * must not be a {value constraint}."
19372 */
19373 if (xmlSchemaIsDerivedFromBuiltInType(
19374 WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19375 {
19376 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19377 XML_SCHEMAP_A_PROPS_CORRECT_3,
19378 NULL, WXS_BASIC_CAST attr,
19379 "Value constraints are not allowed if the type definition "
19380 "is or is derived from xs:ID",
19381 NULL, NULL);
19382 return(pctxt->err);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019383 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019384 /*
19385 * SPEC a-props-correct (2)
19386 * "if there is a {value constraint}, the canonical lexical
19387 * representation of its value must be ·valid· with respect
19388 * to the {type definition} as defined in String Valid (§3.14.4)."
19389 * TODO: Don't care about the *cononical* stuff here, this requirement
19390 * will be removed in WXS 1.1 anyway.
19391 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019392 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019393 attr->node, WXS_ATTR_TYPEDEF(attr),
19394 attr->defValue, &(attr->defVal),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019395 1, 1, 0);
19396 if (ret != 0) {
19397 if (ret < 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019398 PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019399 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019400 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019401 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019402 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019403 XML_SCHEMAP_A_PROPS_CORRECT_2,
19404 NULL, WXS_BASIC_CAST attr,
19405 "The value of the value constraint is not valid",
19406 NULL, NULL);
19407 return(pctxt->err);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019408 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019409 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019410
19411 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019412}
19413
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019414static xmlSchemaElementPtr
19415xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19416 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019417{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019418 xmlSchemaElementPtr ret;
19419
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019420 if (WXS_SUBST_HEAD(ancestor) == NULL)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019421 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019422 if (WXS_SUBST_HEAD(ancestor) == elemDecl)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019423 return (ancestor);
19424
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019425 if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019426 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019427 WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019428 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019429 WXS_SUBST_HEAD(ancestor));
19430 WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019431
19432 return (ret);
19433}
19434
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019435/**
19436 * xmlSchemaCheckElemPropsCorrect:
19437 * @ctxt: a schema parser context
19438 * @decl: the element declaration
19439 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019440 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019441 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019442 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019443 *
19444 * STATUS:
19445 * missing: (6)
19446 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019447static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019448xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19449 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019450{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019451 int ret = 0;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019452 xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019453 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019454 * SPEC (1) "The values of the properties of an element declaration
19455 * must be as described in the property tableau in The Element
19456 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
19457 * Sub-components (§5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019458 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019459 if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19460 xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019461
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019462 xmlSchemaCheckElementDeclComponent(head, pctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019463 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019464 * SPEC (3) "If there is a non-·absent· {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019465 * affiliation}, then {scope} must be global."
19466 */
19467 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19468 xmlSchemaPCustomErr(pctxt,
19469 XML_SCHEMAP_E_PROPS_CORRECT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019470 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019471 "Only global element declarations can have a "
19472 "substitution group affiliation", NULL);
19473 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019474 }
19475 /*
19476 * TODO: SPEC (6) "Circular substitution groups are disallowed.
19477 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019478 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019479 * property."
19480 */
19481 if (head == elemDecl)
19482 circ = head;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019483 else if (WXS_SUBST_HEAD(head) != NULL)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019484 circ = xmlSchemaCheckSubstGroupCircular(head, head);
19485 else
19486 circ = NULL;
19487 if (circ != NULL) {
19488 xmlChar *strA = NULL, *strB = NULL;
19489
19490 xmlSchemaPCustomErrExt(pctxt,
19491 XML_SCHEMAP_E_PROPS_CORRECT_6,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019492 WXS_BASIC_CAST circ, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019493 "The element declaration '%s' defines a circular "
19494 "substitution group to element declaration '%s'",
19495 xmlSchemaGetComponentQName(&strA, circ),
19496 xmlSchemaGetComponentQName(&strB, head),
19497 NULL);
19498 FREE_AND_NULL(strA)
19499 FREE_AND_NULL(strB)
19500 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19501 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019502 /*
19503 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019504 * the {type definition}
19505 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019506 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019507 * of the {substitution group exclusions} of the {substitution group
19508 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
19509 * (if the {type definition} is complex) or as defined in
19510 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019511 * simple)."
19512 *
19513 * NOTE: {substitution group exclusions} means the values of the
19514 * attribute "final".
19515 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019516
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019517 if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019518 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019519
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019520 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19521 set |= SUBSET_EXTENSION;
19522 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19523 set |= SUBSET_RESTRICTION;
19524
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000019525 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019526 WXS_ELEM_TYPEDEF(head), set) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019527 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19528
19529 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019530 xmlSchemaPCustomErrExt(pctxt,
19531 XML_SCHEMAP_E_PROPS_CORRECT_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019532 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019533 "The type definition '%s' was "
19534 "either rejected by the substitution group "
19535 "affiliation '%s', or not validly derived from its type "
19536 "definition '%s'",
19537 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019538 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019539 xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019540 FREE_AND_NULL(strA)
19541 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019542 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019543 }
19544 }
19545 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019546 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019547 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019548 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019549 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019550 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019551 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019552 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019553 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019554 ((WXS_IS_SIMPLE(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019555 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019556 (WXS_IS_COMPLEX(typeDef) &&
19557 WXS_HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019558 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19559 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019560
19561 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19562 xmlSchemaPCustomErr(pctxt,
19563 XML_SCHEMAP_E_PROPS_CORRECT_5,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019564 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019565 "The type definition (or type definition's content type) is or "
19566 "is derived from ID; value constraints are not allowed in "
19567 "conjunction with such a type definition", NULL);
19568 } else if (elemDecl->value != NULL) {
19569 int vcret;
19570 xmlNodePtr node = NULL;
19571
19572 /*
19573 * SPEC (2) "If there is a {value constraint}, the canonical lexical
19574 * representation of its value must be ·valid· with respect to the
19575 * {type definition} as defined in Element Default Valid (Immediate)
19576 * (§3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019577 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019578 if (typeDef == NULL) {
19579 xmlSchemaPErr(pctxt, elemDecl->node,
19580 XML_SCHEMAP_INTERNAL,
19581 "Internal error: xmlSchemaCheckElemPropsCorrect, "
19582 "type is missing... skipping validation of "
19583 "the value constraint", NULL, NULL);
19584 return (-1);
19585 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019586 if (elemDecl->node != NULL) {
19587 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19588 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19589 BAD_CAST "fixed");
19590 else
19591 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19592 BAD_CAST "default");
19593 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019594 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19595 typeDef, elemDecl->value, &(elemDecl->defVal));
19596 if (vcret != 0) {
19597 if (vcret < 0) {
19598 PERROR_INT("xmlSchemaElemCheckValConstr",
19599 "failed to validate the value constraint of an "
19600 "element declaration");
19601 return (-1);
19602 }
19603 return (vcret);
19604 }
19605 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019606
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019607 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019608}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019609
19610/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019611 * xmlSchemaCheckElemSubstGroup:
19612 * @ctxt: a schema parser context
19613 * @decl: the element declaration
19614 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019615 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019616 * Schema Component Constraint:
19617 * Substitution Group (cos-equiv-class)
19618 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019619 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019620 * a list will be built for each subst. group head, holding all direct
19621 * referents to this head.
19622 * NOTE that this function needs:
19623 * 1. circular subst. groups to be checked beforehand
19624 * 2. the declaration's type to be derived from the head's type
19625 *
19626 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019627 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019628 */
19629static void
19630xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19631 xmlSchemaElementPtr elemDecl)
19632{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019633 if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019634 /* SPEC (1) "Its {abstract} is false." */
19635 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19636 return;
19637 {
19638 xmlSchemaElementPtr head;
19639 xmlSchemaTypePtr headType, type;
19640 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019641 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019642 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19643 * {disallowed substitutions} as the blocking constraint, as defined in
19644 * Substitution Group OK (Transitive) (§3.3.6)."
19645 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019646 for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19647 head = WXS_SUBST_HEAD(head)) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019648 set = 0;
19649 methSet = 0;
19650 /*
19651 * The blocking constraints.
19652 */
19653 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19654 continue;
19655 headType = head->subtypes;
19656 type = elemDecl->subtypes;
19657 if (headType == type)
19658 goto add_member;
19659 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19660 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19661 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19662 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19663 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019664 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019665 * "The set of all {derivation method}s involved in the
19666 * derivation of D's {type definition} from C's {type definition}
19667 * does not intersect with the union of the blocking constraint,
19668 * C's {prohibited substitutions} (if C is complex, otherwise the
19669 * empty set) and the {prohibited substitutions} (respectively the
19670 * empty set) of any intermediate {type definition}s in the
19671 * derivation of D's {type definition} from C's {type definition}."
19672 */
19673 /*
19674 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19675 * subst.head axis, the methSet does not need to be computed for
19676 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019677 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019678 /*
19679 * The set of all {derivation method}s involved in the derivation
19680 */
19681 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019682 if ((WXS_IS_EXTENSION(type)) &&
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019683 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19684 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019685
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019686 if (WXS_IS_RESTRICTION(type) &&
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019687 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19688 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19689
19690 type = type->baseType;
19691 }
19692 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019693 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019694 * the head's type.
19695 */
19696 type = elemDecl->subtypes->baseType;
19697 while (type != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019698 if (WXS_IS_COMPLEX(type)) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019699 if ((type->flags &
19700 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19701 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19702 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19703 if ((type->flags &
19704 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19705 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19706 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19707 } else
19708 break;
19709 if (type == headType)
19710 break;
19711 type = type->baseType;
19712 }
19713 if ((set != 0) &&
19714 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19715 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19716 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19717 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19718 continue;
19719 }
19720add_member:
19721 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19722 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19723 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19724 }
19725 }
19726}
19727
19728/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019729 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019730 * @item: an schema element declaration/particle
19731 * @ctxt: a schema parser context
19732 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019733 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019734 * Validates the value constraints of an element declaration.
19735 *
19736 * Fixes finish doing the computations on the element declarations.
19737 */
19738static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019739xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019740 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019741{
19742 if (elemDecl == NULL)
19743 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019744 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19745 return;
19746 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019747 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
19748 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019749}
19750
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019751/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019752 * xmlSchemaResolveModelGroupParticleReferences:
19753 * @particle: a particle component
19754 * @ctxt: a parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019755 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019756 * Resolves references of a model group's {particles} to
19757 * model group definitions and to element declarations.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019758 */
19759static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019760xmlSchemaResolveModelGroupParticleReferences(
19761 xmlSchemaParserCtxtPtr ctxt,
19762 xmlSchemaModelGroupPtr mg)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019763{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019764 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19765 xmlSchemaQNameRefPtr ref;
19766 xmlSchemaBasicItemPtr refItem;
19767
19768 /*
19769 * URGENT TODO: Test this.
19770 */
19771 while (particle != NULL) {
19772 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19773 ((WXS_PARTICLE_TERM(particle))->type !=
19774 XML_SCHEMA_EXTRA_QNAMEREF))
19775 {
19776 goto next_particle;
19777 }
19778 ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019779 /*
19780 * Resolve the reference.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019781 * NULL the {term} by default.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019782 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019783 particle->children = NULL;
19784
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019785 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
19786 ref->itemType, ref->name, ref->targetNamespace);
19787 if (refItem == NULL) {
19788 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019789 NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019790 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019791 /* TODO: remove the particle. */
19792 goto next_particle;
19793 }
19794 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
19795 if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
19796 /* TODO: remove the particle. */
19797 goto next_particle;
19798 /*
19799 * NOTE that we will assign the model group definition
19800 * itself to the "term" of the particle. This will ease
19801 * the check for circular model group definitions. After
19802 * that the "term" will be assigned the model group of the
19803 * model group definition.
19804 */
19805 if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
19806 XML_SCHEMA_TYPE_ALL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019807 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019808 * SPEC cos-all-limited (1)
19809 * SPEC cos-all-limited (1.2)
19810 * "It appears only as the value of one or both of the
19811 * following properties:"
19812 * (1.1) "the {model group} property of a model group
19813 * definition."
19814 * (1.2) "the {term} property of a particle [... of] the "
19815 * {content type} of a complex type definition."
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019816 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019817 xmlSchemaCustomErr(ACTXT_CAST ctxt,
19818 /* TODO: error code */
19819 XML_SCHEMAP_COS_ALL_LIMITED,
19820 WXS_ITEM_NODE(particle), NULL,
19821 "A model group definition is referenced, but "
19822 "it contains an 'all' model group, which "
19823 "cannot be contained by model groups",
19824 NULL, NULL);
19825 /* TODO: remove the particle. */
19826 goto next_particle;
19827 }
19828 particle->children = (xmlSchemaTreeItemPtr) refItem;
19829 } else {
19830 /*
19831 * TODO: Are referenced element declarations the only
19832 * other components we expect here?
19833 */
19834 particle->children = (xmlSchemaTreeItemPtr) refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019835 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019836next_particle:
19837 particle = WXS_PTC_CAST particle->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019838 }
19839}
19840
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019841static int
19842xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
19843 xmlSchemaValPtr y)
19844{
19845 xmlSchemaTypePtr tx, ty, ptx, pty;
19846 int ret;
19847
19848 while (x != NULL) {
19849 /* Same types. */
19850 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
19851 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
19852 ptx = xmlSchemaGetPrimitiveType(tx);
19853 pty = xmlSchemaGetPrimitiveType(ty);
19854 /*
19855 * (1) if a datatype T' is ·derived· by ·restriction· from an
19856 * atomic datatype T then the ·value space· of T' is a subset of
19857 * the ·value space· of T. */
19858 /*
19859 * (2) if datatypes T' and T'' are ·derived· by ·restriction·
19860 * from a common atomic ancestor T then the ·value space·s of T'
19861 * and T'' may overlap.
19862 */
19863 if (ptx != pty)
19864 return(0);
19865 /*
19866 * We assume computed values to be normalized, so do a fast
19867 * string comparison for string based types.
19868 */
19869 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019870 WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019871 if (! xmlStrEqual(
19872 xmlSchemaValueGetAsString(x),
19873 xmlSchemaValueGetAsString(y)))
19874 return (0);
19875 } else {
19876 ret = xmlSchemaCompareValuesWhtsp(
19877 x, XML_SCHEMA_WHITESPACE_PRESERVE,
19878 y, XML_SCHEMA_WHITESPACE_PRESERVE);
19879 if (ret == -2)
19880 return(-1);
19881 if (ret != 0)
19882 return(0);
19883 }
19884 /*
19885 * Lists.
19886 */
19887 x = xmlSchemaValueGetNext(x);
19888 if (x != NULL) {
19889 y = xmlSchemaValueGetNext(y);
19890 if (y == NULL)
19891 return (0);
19892 } else if (xmlSchemaValueGetNext(y) != NULL)
19893 return (0);
19894 else
19895 return (1);
19896 }
19897 return (0);
19898}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019899
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019900/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019901 * xmlSchemaResolveAttrUseReferences:
19902 * @item: an attribute use
19903 * @ctxt: a parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019904 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019905 * Resolves the referenced attribute declaration.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019906 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019907static int
19908xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
19909 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000019910{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019911 if ((ctxt == NULL) || (ause == NULL))
19912 return(-1);
19913 if ((ause->attrDecl == NULL) ||
19914 (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
19915 return(0);
19916
19917 {
19918 xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
19919
19920 /*
19921 * TODO: Evaluate, what errors could occur if the declaration is not
19922 * found.
19923 */
19924 ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
19925 ref->name, ref->targetNamespace);
19926 if (ause->attrDecl == NULL) {
19927 xmlSchemaPResCompAttrErr(ctxt,
19928 XML_SCHEMAP_SRC_RESOLVE,
19929 WXS_BASIC_CAST ause, ause->node,
19930 "ref", ref->name, ref->targetNamespace,
19931 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
19932 return(ctxt->err);;
19933 }
19934 }
19935 return(0);
19936}
19937
19938/**
19939 * xmlSchemaCheckAttrUsePropsCorrect:
19940 * @ctxt: a parser context
19941 * @use: an attribute use
19942 *
19943 * Schema Component Constraint:
19944 * Attribute Use Correct (au-props-correct)
19945 *
19946 */
19947static int
19948xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
19949 xmlSchemaAttributeUsePtr use)
19950{
19951 if ((ctxt == NULL) || (use == NULL))
19952 return(-1);
19953 if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
19954 ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
19955 return(0);
19956
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019957 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019958 * SPEC au-props-correct (1)
19959 * "The values of the properties of an attribute use must be as
19960 * described in the property tableau in The Attribute Use Schema
19961 * Component (§3.5.1), modulo the impact of Missing
19962 * Sub-components (§5.3)."
Daniel Veillardc0826a72004-08-10 14:17:33 +000019963 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019964
19965 if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
19966 ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
19967 ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
19968 {
19969 xmlSchemaPCustomErr(ctxt,
19970 XML_SCHEMAP_AU_PROPS_CORRECT_2,
19971 WXS_BASIC_CAST use, NULL,
19972 "The attribute declaration has a 'fixed' value constraint "
19973 ", thus the attribute use must also have a 'fixed' value "
19974 "constraint",
19975 NULL);
19976 return(ctxt->err);
19977 }
19978 /*
19979 * Compute and check the value constraint's value.
19980 */
19981 if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
19982 int ret;
19983 /*
19984 * TODO: The spec seems to be missing a check of the
19985 * value constraint of the attribute use. We will do it here.
19986 */
19987 /*
19988 * SPEC a-props-correct (3)
19989 */
19990 if (xmlSchemaIsDerivedFromBuiltInType(
19991 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19992 {
19993 xmlSchemaCustomErr(ACTXT_CAST ctxt,
19994 XML_SCHEMAP_AU_PROPS_CORRECT,
19995 NULL, WXS_BASIC_CAST use,
19996 "Value constraints are not allowed if the type definition "
19997 "is or is derived from xs:ID",
19998 NULL, NULL);
19999 return(ctxt->err);
20000 }
20001
20002 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20003 use->node, WXS_ATTRUSE_TYPEDEF(use),
20004 use->defValue, &(use->defVal),
20005 1, 1, 0);
20006 if (ret != 0) {
20007 if (ret < 0) {
20008 PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20009 "calling xmlSchemaVCheckCVCSimpleType()");
20010 return(-1);
20011 }
20012 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20013 XML_SCHEMAP_AU_PROPS_CORRECT,
20014 NULL, WXS_BASIC_CAST use,
20015 "The value of the value constraint is not valid",
20016 NULL, NULL);
20017 return(ctxt->err);
20018 }
20019 }
20020 /*
20021 * SPEC au-props-correct (2)
20022 * "If the {attribute declaration} has a fixed
20023 * {value constraint}, then if the attribute use itself has a
20024 * {value constraint}, it must also be fixed and its value must match
20025 * that of the {attribute declaration}'s {value constraint}."
20026 */
20027 if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20028 (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20029 {
20030 if (! xmlSchemaAreValuesEqual(use->defVal,
20031 (WXS_ATTRUSE_DECL(use))->defVal))
20032 {
20033 xmlSchemaPCustomErr(ctxt,
20034 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20035 WXS_BASIC_CAST use, NULL,
20036 "The 'fixed' value constraint of the attribute use "
20037 "must match the attribute declaration's value "
20038 "constraint '%s'",
20039 (WXS_ATTRUSE_DECL(use))->defValue);
20040 }
20041 return(ctxt->err);
20042 }
20043 return(0);
20044}
20045
20046
20047
20048
20049/**
20050 * xmlSchemaResolveAttrTypeReferences:
20051 * @item: an attribute declaration
20052 * @ctxt: a parser context
20053 *
20054 * Resolves the referenced type definition component.
20055 */
20056static int
20057xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20058 xmlSchemaParserCtxtPtr ctxt)
20059{
Daniel Veillard01fa6152004-06-29 17:04:39 +000020060 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020061 * The simple type definition corresponding to the <simpleType> element
20062 * information item in the [children], if present, otherwise the simple
20063 * type definition ·resolved· to by the ·actual value· of the type
Daniel Veillard01fa6152004-06-29 17:04:39 +000020064 * [attribute], if present, otherwise the ·simple ur-type definition·.
20065 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020066 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020067 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020068 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20069 if (item->subtypes != NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020070 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020071 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020072 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000020073
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020074 type = xmlSchemaGetType(ctxt->schema, item->typeName,
20075 item->typeNs);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020076 if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000020077 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000020078 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020079 WXS_BASIC_CAST item, item->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020080 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020081 XML_SCHEMA_TYPE_SIMPLE, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020082 return(ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020083 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020084 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020085
Daniel Veillard3646d642004-06-02 19:19:14 +000020086 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020087 /*
20088 * The type defaults to the xs:anySimpleType.
20089 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020090 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20091 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020092 return(0);
Daniel Veillard4255d502002-04-16 15:50:10 +000020093}
20094
20095/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020096 * xmlSchemaResolveIDCKeyReferences:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020097 * @idc: the identity-constraint definition
20098 * @ctxt: the schema parser context
20099 * @name: the attribute name
20100 *
20101 * Resolve keyRef references to key/unique IDCs.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020102 * Schema Component Constraint:
20103 * Identity-constraint Definition Properties Correct (c-props-correct)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020104 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020105static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020106xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020107 xmlSchemaParserCtxtPtr pctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020108{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020109 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020110 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020111 if (idc->ref->name != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020112 idc->ref->item = (xmlSchemaBasicItemPtr)
20113 xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20114 idc->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020115 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020116 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020117 * TODO: It is actually not an error to fail to resolve
20118 * at this stage. BUT we need to be that strict!
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020119 */
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020120 xmlSchemaPResCompAttrErr(pctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020121 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020122 WXS_BASIC_CAST idc, idc->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020123 "refer", idc->ref->name,
20124 idc->ref->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020125 XML_SCHEMA_TYPE_IDC_KEY, NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020126 return(pctxt->err);
20127 } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20128 /*
20129 * SPEC c-props-correct (1)
20130 */
20131 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20132 XML_SCHEMAP_C_PROPS_CORRECT,
20133 NULL, WXS_BASIC_CAST idc,
20134 "The keyref references a keyref",
20135 NULL, NULL);
20136 idc->ref->item = NULL;
20137 return(pctxt->err);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020138 } else {
20139 if (idc->nbFields !=
20140 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20141 xmlChar *str = NULL;
20142 xmlSchemaIDCPtr refer;
20143
20144 refer = (xmlSchemaIDCPtr) idc->ref->item;
20145 /*
20146 * SPEC c-props-correct(2)
20147 * "If the {identity-constraint category} is keyref,
20148 * the cardinality of the {fields} must equal that of
20149 * the {fields} of the {referenced key}.
20150 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020151 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020152 XML_SCHEMAP_C_PROPS_CORRECT,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020153 NULL, WXS_BASIC_CAST idc,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020154 "The cardinality of the keyref differs from the "
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020155 "cardinality of the referenced key/unique '%s'",
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020156 xmlSchemaFormatQName(&str, refer->targetNamespace,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020157 refer->name),
20158 NULL);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020159 FREE_AND_NULL(str)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020160 return(pctxt->err);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020161 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020162 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020163 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020164 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020165}
20166
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020167static int
20168xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20169 xmlSchemaParserCtxtPtr pctxt)
20170{
20171 if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20172 prohib->targetNamespace) == NULL) {
20173
20174 xmlSchemaPResCompAttrErr(pctxt,
20175 XML_SCHEMAP_SRC_RESOLVE,
20176 NULL, prohib->node,
20177 "ref", prohib->name, prohib->targetNamespace,
20178 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20179 return(XML_SCHEMAP_SRC_RESOLVE);
20180 }
20181 return(0);
20182}
20183
20184#define WXS_REDEFINED_TYPE(c) \
20185(((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20186
20187#define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20188(((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20189
20190#define WXS_REDEFINED_ATTR_GROUP(c) \
20191(((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20192
20193static int
20194xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20195{
20196 int err = 0;
20197 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20198 xmlSchemaBasicItemPtr prev, item;
20199 int wasRedefined;
20200
20201 if (redef == NULL)
20202 return(0);
20203
20204 do {
20205 item = redef->item;
20206 /*
20207 * First try to locate the redefined component in the
20208 * schema graph starting with the redefined schema.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020209 * NOTE: According to this schema bug entry:
20210 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20211 * it's not clear if the referenced component needs to originate
20212 * from the <redefine>d schema _document_ or the schema; the latter
20213 * would include all imported and included sub-schemas of the
20214 * <redefine>d schema. Currenlty we latter approach is used.
20215 * SUPPLEMENT: It seems that the WG moves towards the latter
20216 * approach, so we are doing it right.
20217 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020218 */
20219 prev = xmlSchemaFindRedefCompInGraph(
20220 redef->targetBucket, item->type,
20221 redef->refName, redef->refTargetNs);
20222 if (prev == NULL) {
20223 xmlChar *str = NULL;
20224 xmlNodePtr node;
20225
20226 /*
20227 * SPEC src-redefine:
20228 * (6.2.1) "The ·actual value· of its own name attribute plus
20229 * target namespace must successfully ·resolve· to a model
20230 * group definition in I."
20231 * (7.2.1) "The ·actual value· of its own name attribute plus
20232 * target namespace must successfully ·resolve· to an attribute
20233 * group definition in I."
20234
20235 *
20236 * Note that, if we are redefining with the use of references
20237 * to components, the spec assumes the src-resolve to be used;
20238 * but this won't assure that we search only *inside* the
20239 * redefined schema.
20240 */
20241 if (redef->reference)
20242 node = WXS_ITEM_NODE(redef->reference);
20243 else
20244 node = WXS_ITEM_NODE(item);
20245 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20246 /*
20247 * TODO: error code.
20248 * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20249 * reference kind.
20250 */
20251 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
Kasimier T. Buchcik5d2998b2005-11-22 17:36:01 +000020252 "The %s '%s' to be redefined could not be found in "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020253 "the redefined schema",
20254 WXS_ITEM_TYPE_NAME(item),
20255 xmlSchemaFormatQName(&str, redef->refTargetNs,
20256 redef->refName));
20257 FREE_AND_NULL(str);
20258 err = pctxt->err;
20259 redef = redef->next;
20260 continue;
20261 }
20262 /*
20263 * TODO: Obtaining and setting the redefinition state is really
20264 * clumsy.
20265 */
20266 wasRedefined = 0;
20267 switch (item->type) {
20268 case XML_SCHEMA_TYPE_COMPLEX:
20269 case XML_SCHEMA_TYPE_SIMPLE:
20270 if ((WXS_TYPE_CAST prev)->flags &
20271 XML_SCHEMAS_TYPE_REDEFINED)
20272 {
20273 wasRedefined = 1;
20274 break;
20275 }
20276 /* Mark it as redefined. */
20277 (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20278 /*
20279 * Assign the redefined type to the
20280 * base type of the redefining type.
20281 * TODO: How
20282 */
20283 ((xmlSchemaTypePtr) item)->baseType =
20284 (xmlSchemaTypePtr) prev;
20285 break;
20286 case XML_SCHEMA_TYPE_GROUP:
20287 if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20288 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20289 {
20290 wasRedefined = 1;
20291 break;
20292 }
20293 /* Mark it as redefined. */
20294 (WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20295 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20296 if (redef->reference != NULL) {
20297 /*
20298 * Overwrite the QName-reference with the
20299 * referenced model group def.
20300 */
20301 (WXS_PTC_CAST redef->reference)->children =
20302 WXS_TREE_CAST prev;
20303 }
20304 redef->target = prev;
20305 break;
20306 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20307 if ((WXS_ATTR_GROUP_CAST prev)->flags &
20308 XML_SCHEMAS_ATTRGROUP_REDEFINED)
20309 {
20310 wasRedefined = 1;
20311 break;
20312 }
20313 (WXS_ATTR_GROUP_CAST prev)->flags |=
20314 XML_SCHEMAS_ATTRGROUP_REDEFINED;
20315 if (redef->reference != NULL) {
20316 /*
20317 * Assign the redefined attribute group to the
20318 * QName-reference component.
20319 * This is the easy case, since we will just
20320 * expand the redefined group.
20321 */
20322 (WXS_QNAME_CAST redef->reference)->item = prev;
20323 redef->target = NULL;
20324 } else {
20325 /*
20326 * This is the complicated case: we need
20327 * to apply src-redefine (7.2.2) at a later
20328 * stage, i.e. when attribute group references
20329 * have beed expanded and simple types have
20330 * beed fixed.
20331 */
20332 redef->target = prev;
20333 }
20334 break;
20335 default:
20336 PERROR_INT("xmlSchemaResolveRedefReferences",
20337 "Unexpected redefined component type");
20338 return(-1);
20339 }
20340 if (wasRedefined) {
20341 xmlChar *str = NULL;
20342 xmlNodePtr node;
20343
20344 if (redef->reference)
20345 node = WXS_ITEM_NODE(redef->reference);
20346 else
20347 node = WXS_ITEM_NODE(redef->item);
20348
20349 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20350 /* TODO: error code. */
20351 XML_SCHEMAP_SRC_REDEFINE,
20352 node, NULL,
20353 "The referenced %s was already redefined. Multiple "
20354 "redefinition of the same component is not supported",
20355 xmlSchemaGetComponentDesignation(&str, prev),
20356 NULL);
20357 FREE_AND_NULL(str)
20358 err = pctxt->err;
20359 redef = redef->next;
20360 continue;
20361 }
20362 redef = redef->next;
20363 } while (redef != NULL);
20364
20365 return(err);
20366}
20367
20368static int
20369xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20370{
20371 int err = 0;
20372 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20373 xmlSchemaBasicItemPtr item;
20374
20375 if (redef == NULL)
20376 return(0);
20377
20378 do {
20379 if (redef->target == NULL) {
20380 redef = redef->next;
20381 continue;
20382 }
20383 item = redef->item;
20384
20385 switch (item->type) {
20386 case XML_SCHEMA_TYPE_SIMPLE:
20387 case XML_SCHEMA_TYPE_COMPLEX:
20388 /*
20389 * Since the spec wants the {name} of the redefined
20390 * type to be 'absent', we'll NULL it.
20391 */
20392 (WXS_TYPE_CAST redef->target)->name = NULL;
20393
20394 /*
20395 * TODO: Seems like there's nothing more to do. The normal
20396 * inheritance mechanism is used. But not 100% sure.
20397 */
20398 break;
20399 case XML_SCHEMA_TYPE_GROUP:
20400 /*
20401 * URGENT TODO:
20402 * SPEC src-redefine:
20403 * (6.2.2) "The {model group} of the model group definition
20404 * which corresponds to it per XML Representation of Model
20405 * Group Definition Schema Components (§3.7.2) must be a
20406 * ·valid restriction· of the {model group} of that model
20407 * group definition in I, as defined in Particle Valid
20408 * (Restriction) (§3.9.6)."
20409 */
20410 break;
20411 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20412 /*
20413 * SPEC src-redefine:
20414 * (7.2.2) "The {attribute uses} and {attribute wildcard} of
20415 * the attribute group definition which corresponds to it
20416 * per XML Representation of Attribute Group Definition Schema
20417 * Components (§3.6.2) must be ·valid restrictions· of the
20418 * {attribute uses} and {attribute wildcard} of that attribute
20419 * group definition in I, as defined in clause 2, clause 3 and
20420 * clause 4 of Derivation Valid (Restriction, Complex)
20421 * (§3.4.6) (where references to the base type definition are
20422 * understood as references to the attribute group definition
20423 * in I)."
20424 */
20425 err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20426 XML_SCHEMA_ACTION_REDEFINE,
20427 item, redef->target,
20428 (WXS_ATTR_GROUP_CAST item)->attrUses,
20429 (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20430 (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20431 (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20432 if (err == -1)
20433 return(-1);
20434 break;
20435 default:
20436 break;
20437 }
20438 redef = redef->next;
20439 } while (redef != NULL);
20440 return(0);
20441}
20442
20443
20444static int
20445xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20446 xmlSchemaBucketPtr bucket)
20447{
20448 xmlSchemaBasicItemPtr item;
20449 int err;
20450 xmlHashTablePtr *table;
20451 const xmlChar *name;
20452 int i;
20453
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020454#define WXS_GET_GLOBAL_HASH(c, slot) { \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020455 if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20456 table = &(WXS_IMPBUCKET((c))->schema->slot); \
20457 else \
20458 table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20459
20460 /*
20461 * Add global components to the schema's hash tables.
20462 * This is the place where duplicate components will be
20463 * detected.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020464 * TODO: I think normally we should support imports of the
20465 * same namespace from multiple locations. We don't do currently,
20466 * but if we do then according to:
20467 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20468 * we would need, if imported directly, to import redefined
20469 * components as well to be able to catch clashing components.
20470 * (I hope I'll still know what this means after some months :-()
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020471 */
20472 if (bucket == NULL)
20473 return(-1);
20474 if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20475 return(0);
20476 bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20477
20478 for (i = 0; i < bucket->globals->nbItems; i++) {
20479 item = bucket->globals->items[i];
20480 table = NULL;
20481 switch (item->type) {
20482 case XML_SCHEMA_TYPE_COMPLEX:
20483 case XML_SCHEMA_TYPE_SIMPLE:
20484 if (WXS_REDEFINED_TYPE(item))
20485 continue;
20486 name = (WXS_TYPE_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020487 WXS_GET_GLOBAL_HASH(bucket, typeDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020488 break;
20489 case XML_SCHEMA_TYPE_ELEMENT:
20490 name = (WXS_ELEM_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020491 WXS_GET_GLOBAL_HASH(bucket, elemDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020492 break;
20493 case XML_SCHEMA_TYPE_ATTRIBUTE:
20494 name = (WXS_ATTR_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020495 WXS_GET_GLOBAL_HASH(bucket, attrDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020496 break;
20497 case XML_SCHEMA_TYPE_GROUP:
20498 if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20499 continue;
20500 name = (WXS_MODEL_GROUPDEF_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020501 WXS_GET_GLOBAL_HASH(bucket, groupDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020502 break;
20503 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20504 if (WXS_REDEFINED_ATTR_GROUP(item))
20505 continue;
20506 name = (WXS_ATTR_GROUP_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020507 WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020508 break;
20509 case XML_SCHEMA_TYPE_IDC_KEY:
20510 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20511 case XML_SCHEMA_TYPE_IDC_KEYREF:
20512 name = (WXS_IDC_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020513 WXS_GET_GLOBAL_HASH(bucket, idcDef)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020514 break;
20515 case XML_SCHEMA_TYPE_NOTATION:
20516 name = ((xmlSchemaNotationPtr) item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020517 WXS_GET_GLOBAL_HASH(bucket, notaDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020518 break;
20519 default:
20520 PERROR_INT("xmlSchemaAddComponents",
20521 "Unexpected global component type");
20522 continue;
20523 }
20524 if (*table == NULL) {
20525 *table = xmlHashCreateDict(10, pctxt->dict);
20526 if (*table == NULL) {
20527 PERROR_INT("xmlSchemaAddComponents",
20528 "failed to create a component hash table");
20529 return(-1);
20530 }
20531 }
20532 err = xmlHashAddEntry(*table, name, item);
20533 if (err != 0) {
20534 xmlChar *str = NULL;
20535
20536 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20537 XML_SCHEMAP_REDEFINED_TYPE,
20538 WXS_ITEM_NODE(item),
20539 WXS_BASIC_CAST item,
20540 "A global %s '%s' does already exist",
20541 WXS_ITEM_TYPE_NAME(item),
20542 xmlSchemaGetComponentQName(&str, item));
20543 FREE_AND_NULL(str);
20544 }
20545 }
20546 /*
20547 * Process imported/included schemas.
20548 */
20549 if (bucket->relations != NULL) {
20550 xmlSchemaSchemaRelationPtr rel = bucket->relations;
20551 do {
20552 if ((rel->bucket != NULL) &&
20553 ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20554 if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20555 return(-1);
20556 }
20557 rel = rel->next;
20558 } while (rel != NULL);
20559 }
20560 return(0);
20561}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020562
20563static int
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020564xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20565 xmlSchemaBucketPtr rootBucket)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020566{
20567 xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20568 xmlSchemaTreeItemPtr item, *items;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020569 int nbItems, i, ret = 0;
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000020570 xmlSchemaBucketPtr oldbucket = con->bucket;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020571
20572#define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20573
20574 if ((con->pending == NULL) ||
20575 (con->pending->nbItems == 0))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020576 return(0);
20577
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000020578 /*
20579 * Since xmlSchemaFixupComplexType() will create new particles
20580 * (local components), and those particle components need a bucket
20581 * on the constructor, we'll assure here that the constructor has
20582 * a bucket.
20583 * TODO: Think about storing locals _only_ on the main bucket.
20584 */
20585 if (con->bucket == NULL)
20586 con->bucket = rootBucket;
20587
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020588 /* TODO:
20589 * SPEC (src-redefine):
20590 * (6.2) "If it has no such self-reference, then all of the
20591 * following must be true:"
20592
20593 * (6.2.2) The {model group} of the model group definition which
20594 * corresponds to it per XML Representation of Model Group
20595 * Definition Schema Components (§3.7.2) must be a ·valid
20596 * restriction· of the {model group} of that model group definition
20597 * in I, as defined in Particle Valid (Restriction) (§3.9.6)."
20598 */
20599 xmlSchemaCheckSRCRedefineFirst(pctxt);
20600
20601 /*
20602 * Add global components to the schemata's hash tables.
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000020603 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020604 xmlSchemaAddComponents(pctxt, rootBucket);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020605
20606 pctxt->ctxtType = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020607 items = (xmlSchemaTreeItemPtr *) con->pending->items;
20608 nbItems = con->pending->nbItems;
20609 /*
20610 * Now that we have parsed *all* the schema document(s) and converted
20611 * them to schema components, we can resolve references, apply component
20612 * constraints, create the FSA from the content model, etc.
20613 */
20614 /*
20615 * Resolve references of..
20616 *
20617 * 1. element declarations:
20618 * - the type definition
20619 * - the substitution group affiliation
20620 * 2. simple/complex types:
20621 * - the base type definition
20622 * - the memberTypes of union types
20623 * - the itemType of list types
20624 * 3. attributes declarations and attribute uses:
20625 * - the type definition
20626 * - if an attribute use, then the attribute declaration
20627 * 4. attribute group references:
20628 * - the attribute group definition
20629 * 5. particles:
20630 * - the term of the particle (e.g. a model group)
20631 * 6. IDC key-references:
20632 * - the referenced IDC 'key' or 'unique' definition
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020633 * 7. Attribute prohibitions which had a "ref" attribute.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020634 */
20635 for (i = 0; i < nbItems; i++) {
20636 item = items[i];
20637 switch (item->type) {
20638 case XML_SCHEMA_TYPE_ELEMENT:
20639 xmlSchemaResolveElementReferences(
20640 (xmlSchemaElementPtr) item, pctxt);
20641 FIXHFAILURE;
20642 break;
20643 case XML_SCHEMA_TYPE_COMPLEX:
20644 case XML_SCHEMA_TYPE_SIMPLE:
20645 xmlSchemaResolveTypeReferences(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020646 (xmlSchemaTypePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020647 FIXHFAILURE;
20648 break;
20649 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020650 xmlSchemaResolveAttrTypeReferences(
20651 (xmlSchemaAttributePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020652 FIXHFAILURE;
20653 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020654 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20655 xmlSchemaResolveAttrUseReferences(
20656 (xmlSchemaAttributeUsePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020657 FIXHFAILURE;
20658 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020659 case XML_SCHEMA_EXTRA_QNAMEREF:
20660 if ((WXS_QNAME_CAST item)->itemType ==
20661 XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20662 {
20663 xmlSchemaResolveAttrGroupReferences(
20664 WXS_QNAME_CAST item, pctxt);
20665 }
20666 FIXHFAILURE;
20667 break;
20668 case XML_SCHEMA_TYPE_SEQUENCE:
20669 case XML_SCHEMA_TYPE_CHOICE:
20670 case XML_SCHEMA_TYPE_ALL:
20671 xmlSchemaResolveModelGroupParticleReferences(pctxt,
20672 WXS_MODEL_GROUP_CAST item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020673 FIXHFAILURE;
20674 break;
20675 case XML_SCHEMA_TYPE_IDC_KEY:
20676 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20677 case XML_SCHEMA_TYPE_IDC_KEYREF:
20678 xmlSchemaResolveIDCKeyReferences(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020679 (xmlSchemaIDCPtr) item, pctxt);
20680 FIXHFAILURE;
20681 break;
20682 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20683 /*
20684 * Handle attribue prohibition which had a
20685 * "ref" attribute.
20686 */
20687 xmlSchemaResolveAttrUseProhibReferences(
20688 WXS_ATTR_PROHIB_CAST item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020689 FIXHFAILURE;
20690 break;
20691 default:
20692 break;
20693 }
20694 }
20695 if (pctxt->nberrors != 0)
20696 goto exit_error;
20697
20698 /*
20699 * Now that all references are resolved we
20700 * can check for circularity of...
20701 * 1. the base axis of type definitions
20702 * 2. nested model group definitions
20703 * 3. nested attribute group definitions
20704 * TODO: check for circual substitution groups.
20705 */
20706 for (i = 0; i < nbItems; i++) {
20707 item = items[i];
20708 /*
20709 * Let's better stop on the first error here.
20710 */
20711 switch (item->type) {
20712 case XML_SCHEMA_TYPE_COMPLEX:
20713 case XML_SCHEMA_TYPE_SIMPLE:
20714 xmlSchemaCheckTypeDefCircular(
20715 (xmlSchemaTypePtr) item, pctxt);
20716 FIXHFAILURE;
20717 if (pctxt->nberrors != 0)
20718 goto exit_error;
20719 break;
20720 case XML_SCHEMA_TYPE_GROUP:
20721 xmlSchemaCheckGroupDefCircular(
20722 (xmlSchemaModelGroupDefPtr) item, pctxt);
20723 FIXHFAILURE;
20724 if (pctxt->nberrors != 0)
20725 goto exit_error;
20726 break;
20727 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20728 xmlSchemaCheckAttrGroupCircular(
20729 (xmlSchemaAttributeGroupPtr) item, pctxt);
20730 FIXHFAILURE;
20731 if (pctxt->nberrors != 0)
20732 goto exit_error;
20733 break;
20734 default:
20735 break;
20736 }
20737 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020738 if (pctxt->nberrors != 0)
20739 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020740 /*
20741 * Model group definition references:
20742 * Such a reference is reflected by a particle at the component
20743 * level. Until now the 'term' of such particles pointed
20744 * to the model group definition; this was done, in order to
20745 * ease circularity checks. Now we need to set the 'term' of
20746 * such particles to the model group of the model group definition.
20747 */
20748 for (i = 0; i < nbItems; i++) {
20749 item = items[i];
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020750 switch (item->type) {
20751 case XML_SCHEMA_TYPE_SEQUENCE:
20752 case XML_SCHEMA_TYPE_CHOICE:
20753 xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
20754 WXS_MODEL_GROUP_CAST item);
20755 break;
20756 default:
20757 break;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020758 }
20759 }
20760 if (pctxt->nberrors != 0)
20761 goto exit_error;
20762 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020763 * Expand attribute group references of attribute group definitions.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020764 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020765 for (i = 0; i < nbItems; i++) {
20766 item = items[i];
20767 switch (item->type) {
20768 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20769 if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
20770 WXS_ATTR_GROUP_HAS_REFS(item))
20771 {
20772 xmlSchemaAttributeGroupExpandRefs(pctxt,
20773 WXS_ATTR_GROUP_CAST item);
20774 FIXHFAILURE;
20775 }
20776 break;
20777 default:
20778 break;
20779 }
20780 }
20781 if (pctxt->nberrors != 0)
20782 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020783 /*
20784 * First compute the variety of simple types. This is needed as
20785 * a seperate step, since otherwise we won't be able to detect
20786 * circular union types in all cases.
20787 */
20788 for (i = 0; i < nbItems; i++) {
20789 item = items[i];
20790 switch (item->type) {
20791 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020792 if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020793 xmlSchemaFixupSimpleTypeStageOne(pctxt,
20794 (xmlSchemaTypePtr) item);
20795 FIXHFAILURE;
20796 }
20797 break;
20798 default:
20799 break;
20800 }
20801 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020802 if (pctxt->nberrors != 0)
20803 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020804 /*
20805 * Detect circular union types. Note that this needs the variety to
20806 * be already computed.
20807 */
20808 for (i = 0; i < nbItems; i++) {
20809 item = items[i];
20810 switch (item->type) {
20811 case XML_SCHEMA_TYPE_SIMPLE:
20812 if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
20813 xmlSchemaCheckUnionTypeDefCircular(pctxt,
20814 (xmlSchemaTypePtr) item);
20815 FIXHFAILURE;
20816 }
20817 break;
20818 default:
20819 break;
20820 }
20821 }
20822 if (pctxt->nberrors != 0)
20823 goto exit_error;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020824
20825 /*
20826 * Do the complete type fixup for simple types.
20827 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020828 for (i = 0; i < nbItems; i++) {
20829 item = items[i];
20830 switch (item->type) {
20831 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020832 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
20833 xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
20834 FIXHFAILURE;
20835 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020836 break;
20837 default:
20838 break;
20839 }
20840 }
20841 if (pctxt->nberrors != 0)
20842 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020843 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020844 * At this point we need all simple types to be builded and checked.
20845 */
20846 /*
20847 * Apply contraints for attribute declarations.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020848 */
20849 for (i = 0; i < nbItems; i++) {
20850 item = items[i];
20851 switch (item->type) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020852 case XML_SCHEMA_TYPE_ATTRIBUTE:
20853 xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
20854 FIXHFAILURE;
20855 break;
20856 default:
20857 break;
20858 }
20859 }
20860 if (pctxt->nberrors != 0)
20861 goto exit_error;
20862 /*
20863 * Apply constraints for attribute uses.
20864 */
20865 for (i = 0; i < nbItems; i++) {
20866 item = items[i];
20867 switch (item->type) {
20868 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20869 if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
20870 xmlSchemaCheckAttrUsePropsCorrect(pctxt,
20871 WXS_ATTR_USE_CAST item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020872 FIXHFAILURE;
20873 }
20874 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020875 default:
20876 break;
20877 }
20878 }
20879 if (pctxt->nberrors != 0)
20880 goto exit_error;
20881
20882 /*
20883 * Apply constraints for attribute group definitions.
20884 */
20885 for (i = 0; i < nbItems; i++) {
20886 item = items[i];
20887 switch (item->type) {
20888 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20889 if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
20890 ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
20891 {
20892 xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
20893 FIXHFAILURE;
20894 }
20895 break;
20896 default:
20897 break;
20898 }
20899 }
20900 if (pctxt->nberrors != 0)
20901 goto exit_error;
20902
20903 /*
20904 * Apply constraints for redefinitions.
20905 */
20906 if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
20907 xmlSchemaCheckSRCRedefineSecond(pctxt);
20908 if (pctxt->nberrors != 0)
20909 goto exit_error;
20910
20911 /*
20912 * Fixup complex types.
20913 */
20914 for (i = 0; i < nbItems; i++) {
20915 item = con->pending->items[i];
20916 switch (item->type) {
20917 case XML_SCHEMA_TYPE_COMPLEX:
20918 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
20919 xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
20920 FIXHFAILURE;
20921 }
20922 break;
20923 default:
20924 break;
20925 }
20926 }
20927 if (pctxt->nberrors != 0)
20928 goto exit_error;
20929
20930 /*
20931 * The list could have changed, since xmlSchemaFixupComplexType()
20932 * will create particles and model groups in some cases.
20933 */
20934 items = (xmlSchemaTreeItemPtr *) con->pending->items;
20935 nbItems = con->pending->nbItems;
20936
20937 /*
20938 * At this point all complex types need to be builded and checked.
20939 */
20940 /*
20941 * Apply some constraints for element declarations.
20942 */
20943 for (i = 0; i < nbItems; i++) {
20944 item = items[i];
20945 switch (item->type) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020946 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020947
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020948 if ((((xmlSchemaElementPtr) item)->flags &
20949 XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0) {
20950 xmlSchemaCheckElementDeclComponent(
20951 (xmlSchemaElementPtr) item, pctxt);
20952 FIXHFAILURE;
20953 }
20954 break;
20955 default:
20956 break;
20957 }
20958 }
20959 if (pctxt->nberrors != 0)
20960 goto exit_error;
20961 /*
20962 * Finally we can build the automaton from the content model of
20963 * complex types.
20964 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020965
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020966 for (i = 0; i < nbItems; i++) {
20967 item = items[i];
20968 switch (item->type) {
20969 case XML_SCHEMA_TYPE_COMPLEX:
20970 xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020971 /* FIXHFAILURE; */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020972 break;
20973 default:
20974 break;
20975 }
20976 }
20977 if (pctxt->nberrors != 0)
20978 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020979 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020980 * URGENT TODO: cos-element-consistent
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020981 */
20982 goto exit;
20983
20984exit_error:
20985 ret = pctxt->err;
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000020986 goto exit;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020987
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020988exit_failure:
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020989 ret = -1;
20990
20991exit:
20992 /*
20993 * Reset the constructor. This is needed for XSI acquisition, since
20994 * those items will be processed over and over again for every XSI
20995 * if not cleared here.
20996 */
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000020997 con->bucket = oldbucket;
20998 con->pending->nbItems = 0;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020999 if (con->substGroups != NULL) {
21000 xmlHashFree(con->substGroups,
21001 (xmlHashDeallocator) xmlSchemaSubstGroupFree);
21002 con->substGroups = NULL;
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000021003 }
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021004 if (con->redefs != NULL) {
21005 xmlSchemaRedefListFree(con->redefs);
21006 con->redefs = NULL;
21007 }
21008 return(ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021009}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021010/**
Daniel Veillard4255d502002-04-16 15:50:10 +000021011 * xmlSchemaParse:
21012 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000021013 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000021014 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000021015 * XML Shema struture which can be used to validate instances.
Daniel Veillard4255d502002-04-16 15:50:10 +000021016 *
21017 * Returns the internal XML Schema structure built from the resource or
21018 * NULL in case of error
21019 */
21020xmlSchemaPtr
21021xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21022{
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021023 xmlSchemaPtr mainSchema = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021024 xmlSchemaBucketPtr bucket = NULL;
21025 int res;
Daniel Veillard4255d502002-04-16 15:50:10 +000021026
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021027 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021028 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021029 * the API; i.e. not automatically by the validated instance document.
21030 */
21031
Daniel Veillard4255d502002-04-16 15:50:10 +000021032 xmlSchemaInitTypes();
21033
Daniel Veillard6045c902002-10-09 21:13:59 +000021034 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000021035 return (NULL);
21036
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021037 /* TODO: Init the context. Is this all we need?*/
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000021038 ctxt->nberrors = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021039 ctxt->err = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000021040 ctxt->counter = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000021041
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021042 /* Create the *main* schema. */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021043 mainSchema = xmlSchemaNewSchema(ctxt);
21044 if (mainSchema == NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021045 goto exit_failure;
Daniel Veillard4255d502002-04-16 15:50:10 +000021046 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021047 * Create the schema constructor.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021048 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021049 if (ctxt->constructor == NULL) {
21050 ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21051 if (ctxt->constructor == NULL)
21052 return(NULL);
21053 /* Take ownership of the constructor to be able to free it. */
21054 ctxt->ownsConstructor = 1;
21055 }
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021056 ctxt->constructor->mainSchema = mainSchema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021057 /*
21058 * Locate and add the schema document.
21059 */
21060 res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21061 ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21062 NULL, NULL, &bucket);
21063 if (res == -1)
21064 goto exit_failure;
21065 if (res != 0)
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000021066 goto exit;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021067
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021068 if (bucket == NULL) {
21069 /* TODO: Error code, actually we failed to *locate* the schema. */
21070 if (ctxt->URL)
21071 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21072 NULL, NULL,
21073 "Failed to locate the main schema resource at '%s'",
21074 ctxt->URL, NULL);
21075 else
21076 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21077 NULL, NULL,
21078 "Failed to locate the main schema resource",
21079 NULL, NULL);
21080 goto exit;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021081 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021082 /* Then do the parsing for good. */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021083 if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021084 goto exit_failure;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021085 if (ctxt->nberrors != 0)
21086 goto exit;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021087
21088 mainSchema->doc = bucket->doc;
21089 mainSchema->preserve = ctxt->preserve;
21090
21091 ctxt->schema = mainSchema;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021092
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021093 if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021094 goto exit_failure;
21095
21096 /*
21097 * TODO: This is not nice, since we cannot distinguish from the
21098 * result if there was an internal error or not.
21099 */
21100exit:
21101 if (ctxt->nberrors != 0) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021102 if (mainSchema) {
21103 xmlSchemaFree(mainSchema);
21104 mainSchema = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021105 }
21106 if (ctxt->constructor) {
21107 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21108 ctxt->constructor = NULL;
21109 ctxt->ownsConstructor = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021110 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021111 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021112 ctxt->schema = NULL;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021113 return(mainSchema);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021114exit_failure:
21115 /*
21116 * Quite verbose, but should catch internal errors, which were
21117 * not communitated.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021118 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021119 if (mainSchema) {
21120 xmlSchemaFree(mainSchema);
21121 mainSchema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021122 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021123 if (ctxt->constructor) {
21124 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21125 ctxt->constructor = NULL;
21126 ctxt->ownsConstructor = 0;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000021127 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021128 PERROR_INT2("xmlSchemaParse",
21129 "An internal error occured");
21130 ctxt->schema = NULL;
21131 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000021132}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021133
Daniel Veillard4255d502002-04-16 15:50:10 +000021134/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000021135 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000021136 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000021137 * @err: the error callback
21138 * @warn: the warning callback
21139 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000021140 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000021141 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000021142 */
21143void
21144xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021145 xmlSchemaValidityErrorFunc err,
21146 xmlSchemaValidityWarningFunc warn, void *ctx)
21147{
Daniel Veillard4255d502002-04-16 15:50:10 +000021148 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021149 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000021150 ctxt->error = err;
21151 ctxt->warning = warn;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021152 ctxt->errCtxt = ctx;
21153 if (ctxt->vctxt != NULL)
21154 xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21155}
21156
21157/**
21158 * xmlSchemaSetParserStructuredErrors:
21159 * @ctxt: a schema parser context
21160 * @serror: the structured error function
21161 * @ctx: the functions context
21162 *
21163 * Set the structured error callback
21164 */
21165void
21166xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21167 xmlStructuredErrorFunc serror,
21168 void *ctx)
21169{
21170 if (ctxt == NULL)
21171 return;
21172 ctxt->serror = serror;
21173 ctxt->errCtxt = ctx;
21174 if (ctxt->vctxt != NULL)
21175 xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000021176}
21177
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021178/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000021179 * xmlSchemaGetParserErrors:
21180 * @ctxt: a XMl-Schema parser context
21181 * @err: the error callback result
21182 * @warn: the warning callback result
21183 * @ctx: contextual data for the callbacks result
21184 *
21185 * Get the callback information used to handle errors for a parser context
21186 *
21187 * Returns -1 in case of failure, 0 otherwise
21188 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021189int
Daniel Veillard259f0df2004-08-18 09:13:18 +000021190xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021191 xmlSchemaValidityErrorFunc * err,
21192 xmlSchemaValidityWarningFunc * warn, void **ctx)
Daniel Veillard259f0df2004-08-18 09:13:18 +000021193{
21194 if (ctxt == NULL)
21195 return(-1);
21196 if (err != NULL)
21197 *err = ctxt->error;
21198 if (warn != NULL)
21199 *warn = ctxt->warning;
21200 if (ctx != NULL)
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021201 *ctx = ctxt->errCtxt;
Daniel Veillard259f0df2004-08-18 09:13:18 +000021202 return(0);
21203}
21204
21205/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021206 * xmlSchemaFacetTypeToString:
21207 * @type: the facet type
21208 *
21209 * Convert the xmlSchemaTypeType to a char string.
21210 *
21211 * Returns the char string representation of the facet type if the
21212 * type is a facet and an "Internal Error" string otherwise.
21213 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021214static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021215xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21216{
21217 switch (type) {
21218 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021219 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021220 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021221 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021222 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021223 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021224 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021225 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021226 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021227 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021228 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021229 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021230 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021231 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021232 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021233 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021234 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021235 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021236 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021237 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021238 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021239 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021240 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021241 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021242 default:
21243 break;
21244 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021245 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021246}
21247
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021248static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000021249xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21250{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021251 /*
21252 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000021253 * from xsd:string.
21254 */
21255 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021256 /*
21257 * Note that we assume a whitespace of preserve for anySimpleType.
21258 */
21259 if ((type->builtInType == XML_SCHEMAS_STRING) ||
21260 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21261 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000021262 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021263 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021264 else {
21265 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021266 * For all ·atomic· datatypes other than string (and types ·derived·
21267 * by ·restriction· from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000021268 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021269 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000021270 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021271 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021272 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021273 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021274 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021275 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021276 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021277 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021278 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021279 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021280 } else if (WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021281 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21282 return (XML_SCHEMA_WHITESPACE_PRESERVE);
21283 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21284 return (XML_SCHEMA_WHITESPACE_REPLACE);
21285 else
21286 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021287 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021288 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021289}
21290
Daniel Veillard4255d502002-04-16 15:50:10 +000021291/************************************************************************
21292 * *
21293 * Simple type validation *
21294 * *
21295 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000021296
Daniel Veillard4255d502002-04-16 15:50:10 +000021297
21298/************************************************************************
21299 * *
21300 * DOM Validation code *
21301 * *
21302 ************************************************************************/
21303
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021304/**
21305 * xmlSchemaAssembleByLocation:
21306 * @pctxt: a schema parser context
21307 * @vctxt: a schema validation context
21308 * @schema: the existing schema
21309 * @node: the node that fired the assembling
21310 * @nsName: the namespace name of the new schema
21311 * @location: the location of the schema
21312 *
21313 * Expands an existing schema by an additional schema.
21314 *
21315 * Returns 0 if the new schema is correct, a positive error code
21316 * number otherwise and -1 in case of an internal or API error.
21317 */
21318static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021319xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021320 xmlSchemaPtr schema,
21321 xmlNodePtr node,
21322 const xmlChar *nsName,
21323 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021324{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021325 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021326 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021327 xmlSchemaBucketPtr bucket = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021328
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021329 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021330 return (-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021331
21332 if (vctxt->pctxt == NULL) {
21333 VERROR_INT("xmlSchemaAssembleByLocation",
21334 "no parser context available");
21335 return(-1);
21336 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021337 pctxt = vctxt->pctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021338 if (pctxt->constructor == NULL) {
21339 PERROR_INT("xmlSchemaAssembleByLocation",
21340 "no constructor");
21341 return(-1);
21342 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021343 /*
21344 * Acquire the schema document.
21345 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021346 location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21347 location, node);
21348 /*
21349 * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21350 * the process will automatically change this to
21351 * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21352 */
21353 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21354 location, NULL, NULL, 0, node, NULL, nsName,
21355 &bucket);
21356 if (ret != 0)
21357 return(ret);
21358 if (bucket == NULL) {
21359 PERROR_INT("xmlSchemaAssembleByLocation",
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021360 "no schema bucket acquired");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021361 return(-1);
21362 }
21363 /*
21364 * The first located schema will be handled as if all other
21365 * schemas imported by XSI were imported by this first schema.
21366 */
21367 if ((bucket != NULL) &&
21368 (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21369 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21370 /*
21371 * TODO: Is this handled like an import? I.e. is it not an error
21372 * if the schema cannot be located?
21373 */
21374 if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21375 return(0);
21376 /*
21377 * We will reuse the parser context for every schema imported
21378 * directly via XSI. So reset the context.
21379 */
21380 pctxt->nberrors = 0;
21381 pctxt->err = 0;
21382 pctxt->doc = bucket->doc;
21383
21384 ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21385 if (ret == -1) {
21386 pctxt->doc = NULL;
21387 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021388 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021389 /* Paranoid error channelling. */
21390 if ((ret == 0) && (pctxt->nberrors != 0))
21391 ret = pctxt->err;
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000021392 if (pctxt->nberrors == 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021393 /*
21394 * Only bother to fixup pending components, if there was
21395 * no error yet.
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021396 * For every XSI acquired schema (and its sub-schemata) we will
21397 * fixup the components.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021398 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021399 xmlSchemaFixupComponents(pctxt, bucket);
Kasimier T. Buchcik215406f2005-12-07 12:14:09 +000021400 ret = pctxt->err;
21401 /*
21402 * Not nice, but we need somehow to channel the schema parser
21403 * error to the validation context.
21404 */
21405 if ((ret != 0) && (vctxt->err == 0))
21406 vctxt->err = ret;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021407 vctxt->nberrors += pctxt->nberrors;
21408 } else {
21409 /* Add to validation error sum. */
21410 vctxt->nberrors += pctxt->nberrors;
21411 }
21412 pctxt->doc = NULL;
21413 return(ret);
21414exit_failure:
21415 pctxt->doc = NULL;
21416 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021417}
21418
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021419static xmlSchemaAttrInfoPtr
21420xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21421 int metaType)
21422{
21423 if (vctxt->nbAttrInfos == 0)
21424 return (NULL);
21425 {
21426 int i;
21427 xmlSchemaAttrInfoPtr iattr;
21428
21429 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21430 iattr = vctxt->attrInfos[i];
21431 if (iattr->metaType == metaType)
21432 return (iattr);
21433 }
21434
21435 }
21436 return (NULL);
21437}
21438
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021439/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021440 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021441 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021442 *
21443 * Expands an existing schema by an additional schema using
21444 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21445 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21446 * must be set to 1.
21447 *
21448 * Returns 0 if the new schema is correct, a positive error code
21449 * number otherwise and -1 in case of an internal or API error.
21450 */
21451static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021452xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021453{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021454 const xmlChar *cur, *end;
21455 const xmlChar *nsname = NULL, *location;
21456 int count = 0;
21457 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021458 xmlSchemaAttrInfoPtr iattr;
21459
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021460 /*
21461 * Parse the value; we will assume an even number of values
21462 * to be given (this is how Xerces and XSV work).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021463 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021464 * URGENT TODO: !! This needs to work for both
21465 * @noNamespaceSchemaLocation AND @schemaLocation on the same
21466 * element !!
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021467 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021468 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21469 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21470 if (iattr == NULL)
Kasimier T. Buchcik81755ea2005-11-23 16:39:27 +000021471 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021472 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21473 if (iattr == NULL)
21474 return (0);
21475 cur = iattr->value;
21476 do {
21477 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021478 /*
21479 * Get the namespace name.
21480 */
21481 while (IS_BLANK_CH(*cur))
21482 cur++;
21483 end = cur;
21484 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21485 end++;
21486 if (end == cur)
21487 break;
21488 count++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021489 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021490 cur = end;
21491 }
21492 /*
21493 * Get the URI.
21494 */
21495 while (IS_BLANK_CH(*cur))
21496 cur++;
21497 end = cur;
21498 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21499 end++;
21500 if (end == cur)
21501 break;
21502 count++;
21503 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021504 cur = end;
21505 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21506 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021507 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021508 VERROR_INT("xmlSchemaAssembleByXSI",
21509 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021510 return (-1);
21511 }
21512 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021513 return (ret);
21514}
21515
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021516static const xmlChar *
21517xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21518 const xmlChar *prefix)
21519{
21520 if (vctxt->sax != NULL) {
21521 int i, j;
21522 xmlSchemaNodeInfoPtr inode;
21523
21524 for (i = vctxt->depth; i >= 0; i--) {
21525 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21526 inode = vctxt->elemInfos[i];
21527 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21528 if (((prefix == NULL) &&
21529 (inode->nsBindings[j] == NULL)) ||
21530 ((prefix != NULL) && xmlStrEqual(prefix,
21531 inode->nsBindings[j]))) {
21532
21533 /*
21534 * Note that the namespace bindings are already
21535 * in a string dict.
21536 */
21537 return (inode->nsBindings[j+1]);
21538 }
21539 }
21540 }
21541 }
21542 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000021543#ifdef LIBXML_WRITER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021544 } else if (vctxt->reader != NULL) {
21545 xmlChar *nsName;
21546
21547 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21548 if (nsName != NULL) {
21549 const xmlChar *ret;
21550
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021551 ret = xmlDictLookup(vctxt->dict, nsName, -1);
21552 xmlFree(nsName);
21553 return (ret);
21554 } else
21555 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000021556#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021557 } else {
21558 xmlNsPtr ns;
21559
21560 if ((vctxt->inode->node == NULL) ||
21561 (vctxt->inode->node->doc == NULL)) {
21562 VERROR_INT("xmlSchemaLookupNamespace",
21563 "no node or node's doc avaliable");
21564 return (NULL);
21565 }
21566 ns = xmlSearchNs(vctxt->inode->node->doc,
21567 vctxt->inode->node, prefix);
21568 if (ns != NULL)
21569 return (ns->href);
21570 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021571 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021572}
21573
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021574/*
21575* This one works on the schema of the validation context.
21576*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021577static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021578xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21579 xmlSchemaPtr schema,
21580 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021581 const xmlChar *value,
21582 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021583 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021584{
21585 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021586
21587 if (vctxt && (vctxt->schema == NULL)) {
21588 VERROR_INT("xmlSchemaValidateNotation",
21589 "a schema is needed on the validation context");
21590 return (-1);
21591 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021592 ret = xmlValidateQName(value, 1);
21593 if (ret != 0)
21594 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021595 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021596 xmlChar *localName = NULL;
21597 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021598
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021599 localName = xmlSplitQName2(value, &prefix);
21600 if (prefix != NULL) {
21601 const xmlChar *nsName = NULL;
21602
21603 if (vctxt != NULL)
21604 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21605 else if (node != NULL) {
21606 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21607 if (ns != NULL)
21608 nsName = ns->href;
21609 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021610 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021611 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021612 return (1);
21613 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021614 if (nsName == NULL) {
21615 xmlFree(prefix);
21616 xmlFree(localName);
21617 return (1);
21618 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021619 if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021620 if (valNeeded && (val != NULL)) {
21621 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
21622 BAD_CAST xmlStrdup(nsName));
21623 if (*val == NULL)
21624 ret = -1;
21625 }
21626 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021627 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021628 xmlFree(prefix);
21629 xmlFree(localName);
21630 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021631 if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021632 if (valNeeded && (val != NULL)) {
21633 (*val) = xmlSchemaNewNOTATIONValue(
21634 BAD_CAST xmlStrdup(value), NULL);
21635 if (*val == NULL)
21636 ret = -1;
21637 }
21638 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021639 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021640 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021641 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021642 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021643}
21644
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000021645static int
21646xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21647 const xmlChar* lname,
21648 const xmlChar* nsname)
21649{
21650 int i;
21651
21652 lname = xmlDictLookup(vctxt->dict, lname, -1);
21653 if (lname == NULL)
21654 return(-1);
21655 if (nsname != NULL) {
21656 nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21657 if (nsname == NULL)
21658 return(-1);
21659 }
21660 for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21661 if ((vctxt->nodeQNames->items [i] == lname) &&
21662 (vctxt->nodeQNames->items[i +1] == nsname))
21663 /* Already there */
21664 return(i);
21665 }
21666 /* Add new entry. */
21667 i = vctxt->nodeQNames->nbItems;
21668 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21669 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21670 return(i);
21671}
21672
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021673/************************************************************************
21674 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021675 * Validation of identity-constraints (IDC) *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021676 * *
21677 ************************************************************************/
21678
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021679/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021680 * xmlSchemaAugmentIDC:
21681 * @idcDef: the IDC definition
21682 *
21683 * Creates an augmented IDC definition item.
21684 *
21685 * Returns the item, or NULL on internal errors.
21686 */
21687static void
21688xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
21689 xmlSchemaValidCtxtPtr vctxt)
21690{
21691 xmlSchemaIDCAugPtr aidc;
21692
21693 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21694 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021695 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021696 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21697 NULL);
21698 return;
21699 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021700 aidc->keyrefDepth = -1;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021701 aidc->def = idcDef;
21702 aidc->next = NULL;
21703 if (vctxt->aidcs == NULL)
21704 vctxt->aidcs = aidc;
21705 else {
21706 aidc->next = vctxt->aidcs;
21707 vctxt->aidcs = aidc;
21708 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021709 /*
21710 * Save if we have keyrefs at all.
21711 */
21712 if ((vctxt->hasKeyrefs == 0) &&
21713 (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
21714 vctxt->hasKeyrefs = 1;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021715}
21716
21717/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021718 * xmlSchemaIDCNewBinding:
21719 * @idcDef: the IDC definition of this binding
21720 *
21721 * Creates a new IDC binding.
21722 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021723 * Returns the new IDC binding, NULL on internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021724 */
21725static xmlSchemaPSVIIDCBindingPtr
21726xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
21727{
21728 xmlSchemaPSVIIDCBindingPtr ret;
21729
21730 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
21731 sizeof(xmlSchemaPSVIIDCBinding));
21732 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021733 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021734 "allocating a PSVI IDC binding item", NULL);
21735 return (NULL);
21736 }
21737 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
21738 ret->definition = idcDef;
21739 return (ret);
21740}
21741
21742/**
21743 * xmlSchemaIDCStoreNodeTableItem:
21744 * @vctxt: the WXS validation context
21745 * @item: the IDC node table item
21746 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021747 * The validation context is used to store IDC node table items.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021748 * They are stored to avoid copying them if IDC node-tables are merged
21749 * with corresponding parent IDC node-tables (bubbling).
21750 *
21751 * Returns 0 if succeeded, -1 on internal errors.
21752 */
21753static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021754xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021755 xmlSchemaPSVIIDCNodePtr item)
21756{
21757 /*
21758 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021759 */
21760 if (vctxt->idcNodes == NULL) {
21761 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021762 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
21763 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021764 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021765 "allocating the IDC node table item list", NULL);
21766 return (-1);
21767 }
21768 vctxt->sizeIdcNodes = 20;
21769 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
21770 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021771 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
21772 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021773 sizeof(xmlSchemaPSVIIDCNodePtr));
21774 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021775 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021776 "re-allocating the IDC node table item list", NULL);
21777 return (-1);
21778 }
21779 }
21780 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021781
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021782 return (0);
21783}
21784
21785/**
21786 * xmlSchemaIDCStoreKey:
21787 * @vctxt: the WXS validation context
21788 * @item: the IDC key
21789 *
21790 * The validation context is used to store an IDC key.
21791 *
21792 * Returns 0 if succeeded, -1 on internal errors.
21793 */
21794static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021795xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021796 xmlSchemaPSVIIDCKeyPtr key)
21797{
21798 /*
21799 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021800 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021801 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021802 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021803 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
21804 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021805 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021806 "allocating the IDC key storage list", NULL);
21807 return (-1);
21808 }
21809 vctxt->sizeIdcKeys = 40;
21810 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
21811 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021812 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
21813 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021814 sizeof(xmlSchemaPSVIIDCKeyPtr));
21815 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021816 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021817 "re-allocating the IDC key storage list", NULL);
21818 return (-1);
21819 }
21820 }
21821 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021822
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021823 return (0);
21824}
21825
21826/**
21827 * xmlSchemaIDCAppendNodeTableItem:
21828 * @bind: the IDC binding
21829 * @ntItem: the node-table item
21830 *
21831 * Appends the IDC node-table item to the binding.
21832 *
21833 * Returns 0 on success and -1 on internal errors.
21834 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021835static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021836xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
21837 xmlSchemaPSVIIDCNodePtr ntItem)
21838{
21839 if (bind->nodeTable == NULL) {
21840 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021841 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021842 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
21843 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021844 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021845 "allocating an array of IDC node-table items", NULL);
21846 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021847 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021848 } else if (bind->sizeNodes <= bind->nbNodes) {
21849 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021850 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
21851 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021852 sizeof(xmlSchemaPSVIIDCNodePtr));
21853 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021854 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021855 "re-allocating an array of IDC node-table items", NULL);
21856 return(-1);
21857 }
21858 }
21859 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021860 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021861}
21862
21863/**
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021864 * xmlSchemaIDCAcquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021865 * @vctxt: the WXS validation context
21866 * @matcher: the IDC matcher
21867 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021868 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021869 * of the given matcher. If none found, a new one is created
21870 * and added to the IDC table.
21871 *
21872 * Returns an IDC binding or NULL on internal errors.
21873 */
21874static xmlSchemaPSVIIDCBindingPtr
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021875xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021876 xmlSchemaIDCMatcherPtr matcher)
21877{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021878 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021879
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021880 ielem = vctxt->elemInfos[matcher->depth];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021881
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021882 if (ielem->idcTable == NULL) {
21883 ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
21884 if (ielem->idcTable == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021885 return (NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021886 return(ielem->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021887 } else {
21888 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021889
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021890 bind = ielem->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021891 do {
21892 if (bind->definition == matcher->aidc->def)
21893 return(bind);
21894 if (bind->next == NULL) {
21895 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
21896 if (bind->next == NULL)
21897 return (NULL);
21898 return(bind->next);
21899 }
21900 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021901 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021902 }
21903 return (NULL);
21904}
21905
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021906static xmlSchemaItemListPtr
21907xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
21908 xmlSchemaIDCMatcherPtr matcher)
21909{
21910 if (matcher->targets == NULL)
21911 matcher->targets = xmlSchemaItemListCreate();
21912 return(matcher->targets);
21913}
21914
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021915/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021916 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021917 * @key: the IDC key
21918 *
21919 * Frees an IDC key together with its compiled value.
21920 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021921static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021922xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
21923{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021924 if (key->val != NULL)
21925 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021926 xmlFree(key);
21927}
21928
21929/**
21930 * xmlSchemaIDCFreeBinding:
21931 *
21932 * Frees an IDC binding. Note that the node table-items
21933 * are not freed.
21934 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021935static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021936xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
21937{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021938 if (bind->nodeTable != NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021939 xmlFree(bind->nodeTable);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021940 if (bind->dupls != NULL)
21941 xmlSchemaItemListFree(bind->dupls);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021942 xmlFree(bind);
21943}
21944
21945/**
21946 * xmlSchemaIDCFreeIDCTable:
21947 * @bind: the first IDC binding in the list
21948 *
21949 * Frees an IDC table, i.e. all the IDC bindings in the list.
21950 */
21951static void
21952xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
21953{
21954 xmlSchemaPSVIIDCBindingPtr prev;
21955
21956 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021957 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021958 bind = bind->next;
21959 xmlSchemaIDCFreeBinding(prev);
21960 }
21961}
21962
21963/**
21964 * xmlSchemaIDCFreeMatcherList:
21965 * @matcher: the first IDC matcher in the list
21966 *
21967 * Frees a list of IDC matchers.
21968 */
21969static void
21970xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
21971{
21972 xmlSchemaIDCMatcherPtr next;
21973
21974 while (matcher != NULL) {
21975 next = matcher->next;
21976 if (matcher->keySeqs != NULL) {
21977 int i;
21978 for (i = 0; i < matcher->sizeKeySeqs; i++)
21979 if (matcher->keySeqs[i] != NULL)
21980 xmlFree(matcher->keySeqs[i]);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021981 xmlFree(matcher->keySeqs);
21982 }
21983 if (matcher->targets != NULL) {
21984 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
21985 int i;
21986 xmlSchemaPSVIIDCNodePtr idcNode;
21987 /*
21988 * Node-table items for keyrefs are not stored globally
21989 * to the validation context, since they are not bubbled.
21990 * We need to free them here.
21991 */
21992 for (i = 0; i < matcher->targets->nbItems; i++) {
21993 idcNode =
21994 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
21995 xmlFree(idcNode->keys);
21996 xmlFree(idcNode);
21997 }
21998 }
21999 xmlSchemaItemListFree(matcher->targets);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022000 }
22001 xmlFree(matcher);
22002 matcher = next;
22003 }
22004}
22005
22006/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022007 * xmlSchemaIDCAddStateObject:
22008 * @vctxt: the WXS validation context
22009 * @matcher: the IDC matcher
22010 * @sel: the XPath information
22011 * @parent: the parent "selector" state object if any
22012 * @type: "selector" or "field"
22013 *
22014 * Creates/reuses and activates state objects for the given
22015 * XPath information; if the XPath expression consists of unions,
22016 * multiple state objects are created for every unioned expression.
22017 *
22018 * Returns 0 on success and -1 on internal errors.
22019 */
22020static int
22021xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22022 xmlSchemaIDCMatcherPtr matcher,
22023 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022024 int type)
22025{
22026 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022027
22028 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022029 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022030 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022031 if (vctxt->xpathStatePool != NULL) {
22032 sto = vctxt->xpathStatePool;
22033 vctxt->xpathStatePool = sto->next;
22034 sto->next = NULL;
22035 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022036 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022037 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022038 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022039 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22040 if (sto == NULL) {
22041 xmlSchemaVErrMemory(NULL,
22042 "allocating an IDC state object", NULL);
22043 return (-1);
22044 }
22045 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22046 }
22047 /*
22048 * Add to global list.
22049 */
22050 if (vctxt->xpathStates != NULL)
22051 sto->next = vctxt->xpathStates;
22052 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022053
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022054 /*
22055 * Free the old xpath validation context.
22056 */
22057 if (sto->xpathCtxt != NULL)
22058 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22059
22060 /*
22061 * Create a new XPath (pattern) validation context.
22062 */
22063 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22064 (xmlPatternPtr) sel->xpathComp);
22065 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022066 VERROR_INT("xmlSchemaIDCAddStateObject",
22067 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022068 return (-1);
22069 }
22070 sto->type = type;
22071 sto->depth = vctxt->depth;
22072 sto->matcher = matcher;
22073 sto->sel = sel;
22074 sto->nbHistory = 0;
22075
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022076#ifdef DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022077 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
22078 sto->sel->xpath);
22079#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022080 return (0);
22081}
22082
22083/**
22084 * xmlSchemaXPathEvaluate:
22085 * @vctxt: the WXS validation context
22086 * @nodeType: the nodeType of the current node
22087 *
22088 * Evaluates all active XPath state objects.
22089 *
22090 * Returns the number of IC "field" state objects which resolved to
22091 * this node, 0 if none resolved and -1 on internal errors.
22092 */
22093static int
22094xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022095 xmlElementType nodeType)
22096{
22097 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022098 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022099
22100 if (vctxt->xpathStates == NULL)
22101 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022102
22103 if (nodeType == XML_ATTRIBUTE_NODE)
22104 depth++;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022105#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022106 {
22107 xmlChar *str = NULL;
22108 xmlGenericError(xmlGenericErrorContext,
22109 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022110 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22111 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022112 FREE_AND_NULL(str)
22113 }
22114#endif
22115 /*
22116 * Process all active XPath state objects.
22117 */
22118 first = vctxt->xpathStates;
22119 sto = first;
22120 while (sto != head) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022121#ifdef DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022122 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022123 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
22124 sto->matcher->aidc->def->name, sto->sel->xpath);
22125 else
22126 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
22127 sto->matcher->aidc->def->name, sto->sel->xpath);
22128#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022129 if (nodeType == XML_ELEMENT_NODE)
22130 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022131 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022132 else
22133 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022134 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022135
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022136 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022137 VERROR_INT("xmlSchemaXPathEvaluate",
22138 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022139 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022140 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022141 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022142 goto next_sto;
22143 /*
22144 * Full match.
22145 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022146#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022147 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022148 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022149#endif
22150 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022151 * Register a match in the state object history.
22152 */
22153 if (sto->history == NULL) {
22154 sto->history = (int *) xmlMalloc(5 * sizeof(int));
22155 if (sto->history == NULL) {
22156 xmlSchemaVErrMemory(NULL,
22157 "allocating the state object history", NULL);
22158 return(-1);
22159 }
22160 sto->sizeHistory = 10;
22161 } else if (sto->sizeHistory <= sto->nbHistory) {
22162 sto->sizeHistory *= 2;
22163 sto->history = (int *) xmlRealloc(sto->history,
22164 sto->sizeHistory * sizeof(int));
22165 if (sto->history == NULL) {
22166 xmlSchemaVErrMemory(NULL,
22167 "re-allocating the state object history", NULL);
22168 return(-1);
22169 }
22170 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022171 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022172
22173#ifdef DEBUG_IDC
22174 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
22175 vctxt->depth);
22176#endif
22177
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022178 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22179 xmlSchemaIDCSelectPtr sel;
22180 /*
22181 * Activate state objects for the IDC fields of
22182 * the IDC selector.
22183 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022184#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022185 xmlGenericError(xmlGenericErrorContext, "IDC: "
22186 "activating field states\n");
22187#endif
22188 sel = sto->matcher->aidc->def->fields;
22189 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022190 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22191 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22192 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022193 sel = sel->next;
22194 }
22195 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22196 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022197 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022198 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022199#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022200 xmlGenericError(xmlGenericErrorContext,
22201 "IDC: key found\n");
22202#endif
22203 /*
22204 * Notify that the character value of this node is
22205 * needed.
22206 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022207 if (resolved == 0) {
22208 if ((vctxt->inode->flags &
22209 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22210 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22211 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022212 resolved++;
22213 }
22214next_sto:
22215 if (sto->next == NULL) {
22216 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022217 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022218 */
22219 head = first;
22220 sto = vctxt->xpathStates;
22221 } else
22222 sto = sto->next;
22223 }
22224 return (resolved);
22225}
22226
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022227static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022228xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022229 xmlChar **buf,
22230 xmlSchemaPSVIIDCKeyPtr *seq,
22231 int count)
22232{
22233 int i, res;
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022234 xmlChar *value = NULL;
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022235
22236 *buf = xmlStrdup(BAD_CAST "[");
22237 for (i = 0; i < count; i++) {
22238 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022239 res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22240 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22241 &value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022242 if (res == 0)
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022243 *buf = xmlStrcat(*buf, BAD_CAST value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022244 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022245 VERROR_INT("xmlSchemaFormatIDCKeySequence",
22246 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022247 *buf = xmlStrcat(*buf, BAD_CAST "???");
22248 }
22249 if (i < count -1)
22250 *buf = xmlStrcat(*buf, BAD_CAST "', ");
22251 else
22252 *buf = xmlStrcat(*buf, BAD_CAST "'");
22253 if (value != NULL) {
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022254 xmlFree(value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022255 value = NULL;
22256 }
22257 }
22258 *buf = xmlStrcat(*buf, BAD_CAST "]");
22259
22260 return (BAD_CAST *buf);
22261}
22262
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022263/**
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000022264 * xmlSchemaXPathPop:
22265 * @vctxt: the WXS validation context
22266 *
22267 * Pops all XPath states.
22268 *
22269 * Returns 0 on success and -1 on internal errors.
22270 */
22271static int
22272xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22273{
22274 xmlSchemaIDCStateObjPtr sto;
22275 int res;
22276
22277 if (vctxt->xpathStates == NULL)
22278 return(0);
22279 sto = vctxt->xpathStates;
22280 do {
22281 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22282 if (res == -1)
22283 return (-1);
22284 sto = sto->next;
22285 } while (sto != NULL);
22286 return(0);
22287}
22288
22289/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022290 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022291 * @vctxt: the WXS validation context
22292 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022293 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022294 *
22295 * Processes and pops the history items of the IDC state objects.
22296 * IDC key-sequences are validated/created on IDC bindings.
22297 *
22298 * Returns 0 on success and -1 on internal errors.
22299 */
22300static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022301xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022302 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022303{
22304 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022305 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022306 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022307 xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022308
22309 if (vctxt->xpathStates == NULL)
22310 return (0);
22311 sto = vctxt->xpathStates;
22312
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022313#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022314 {
22315 xmlChar *str = NULL;
22316 xmlGenericError(xmlGenericErrorContext,
22317 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022318 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22319 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022320 FREE_AND_NULL(str)
22321 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022322#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022323 /*
22324 * Evaluate the state objects.
22325 */
22326 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000022327 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22328 if (res == -1) {
22329 VERROR_INT("xmlSchemaXPathProcessHistory",
22330 "calling xmlStreamPop()");
22331 return (-1);
22332 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022333#ifdef DEBUG_IDC
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022334 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
22335 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022336#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022337 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022338 goto deregister_check;
22339
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022340 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022341
22342 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022343 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022344 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022345 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022346 sto = sto->next;
22347 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022348 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022349 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022350 /*
22351 * NOTE: According to
22352 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22353 * ... the simple-content of complex types is also allowed.
22354 */
22355
22356 if (WXS_IS_COMPLEX(type)) {
22357 if (WXS_HAS_SIMPLE_CONTENT(type)) {
22358 /*
22359 * Sanity check for complex types with simple content.
22360 */
22361 simpleType = type->contentTypeDef;
22362 if (simpleType == NULL) {
22363 VERROR_INT("xmlSchemaXPathProcessHistory",
22364 "field resolves to a CT with simple content "
22365 "but the CT is missing the ST definition");
22366 return (-1);
22367 }
22368 } else
22369 simpleType = NULL;
22370 } else
22371 simpleType = type;
22372 if (simpleType == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022373 xmlChar *str = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022374
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022375 /*
22376 * Not qualified if the field resolves to a node of non
22377 * simple type.
22378 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022379 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022380 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022381 WXS_BASIC_CAST sto->matcher->aidc->def,
22382 "The XPath '%s' of a field of %s does evaluate to a node of "
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022383 "non-simple type",
22384 sto->sel->xpath,
22385 xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22386 FREE_AND_NULL(str);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022387 sto->nbHistory--;
22388 goto deregister_check;
22389 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022390
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022391 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022392 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022393 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022394 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022395 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022396 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022397 WXS_BASIC_CAST sto->matcher->aidc->def,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000022398 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022399 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022400 sto->nbHistory--;
22401 goto deregister_check;
22402 } else {
22403 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22404 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022405 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022406
22407 /*
22408 * The key will be anchored on the matcher's list of
22409 * key-sequences. The position in this list is determined
22410 * by the target node's depth relative to the matcher's
22411 * depth of creation (i.e. the depth of the scope element).
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022412 *
22413 * Element Depth Pos List-entries
22414 * <scope> 0 NULL
22415 * <bar> 1 NULL
22416 * <target/> 2 2 target
22417 * <bar>
22418 * </scope>
22419 *
22420 * The size of the list is only dependant on the depth of
22421 * the tree.
22422 * An entry will be NULLed in selector_leave, i.e. when
22423 * we hit the target's
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022424 */
22425 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022426 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022427
22428 /*
22429 * Create/grow the array of key-sequences.
22430 */
22431 if (matcher->keySeqs == NULL) {
22432 if (pos > 9)
22433 matcher->sizeKeySeqs = pos * 2;
22434 else
22435 matcher->sizeKeySeqs = 10;
22436 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22437 xmlMalloc(matcher->sizeKeySeqs *
22438 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22439 if (matcher->keySeqs == NULL) {
22440 xmlSchemaVErrMemory(NULL,
22441 "allocating an array of key-sequences",
22442 NULL);
22443 return(-1);
22444 }
22445 memset(matcher->keySeqs, 0,
22446 matcher->sizeKeySeqs *
22447 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22448 } else if (pos >= matcher->sizeKeySeqs) {
22449 int i = matcher->sizeKeySeqs;
22450
22451 matcher->sizeKeySeqs *= 2;
22452 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22453 xmlRealloc(matcher->keySeqs,
22454 matcher->sizeKeySeqs *
22455 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022456 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022457 xmlSchemaVErrMemory(NULL,
22458 "reallocating an array of key-sequences",
22459 NULL);
22460 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022461 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022462 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022463 * The array needs to be NULLed.
22464 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022465 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022466 for (; i < matcher->sizeKeySeqs; i++)
22467 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022468 }
22469
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022470 /*
22471 * Get/create the key-sequence.
22472 */
22473 keySeq = matcher->keySeqs[pos];
22474 if (keySeq == NULL) {
22475 goto create_sequence;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022476 } else if (keySeq[idx] != NULL) {
22477 xmlChar *str = NULL;
22478 /*
22479 * cvc-identity-constraint:
22480 * 3 For each node in the ·target node set· all
22481 * of the {fields}, with that node as the context
22482 * node, evaluate to either an empty node-set or
22483 * a node-set with exactly one member, which must
22484 * have a simple type.
22485 *
22486 * The key was already set; report an error.
22487 */
22488 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22489 XML_SCHEMAV_CVC_IDC, NULL,
22490 WXS_BASIC_CAST matcher->aidc->def,
22491 "The XPath '%s' of a field of %s evaluates to a "
22492 "node-set with more than one member",
22493 sto->sel->xpath,
22494 xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22495 FREE_AND_NULL(str);
22496 sto->nbHistory--;
22497 goto deregister_check;
22498 } else
22499 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022500
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022501create_sequence:
22502 /*
22503 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022504 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022505 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22506 matcher->aidc->def->nbFields *
22507 sizeof(xmlSchemaPSVIIDCKeyPtr));
22508 if (keySeq == NULL) {
22509 xmlSchemaVErrMemory(NULL,
22510 "allocating an IDC key-sequence", NULL);
22511 return(-1);
22512 }
22513 memset(keySeq, 0, matcher->aidc->def->nbFields *
22514 sizeof(xmlSchemaPSVIIDCKeyPtr));
22515 matcher->keySeqs[pos] = keySeq;
22516create_key:
22517 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022518 * Create a key once per node only.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022519 */
22520 if (key == NULL) {
22521 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22522 sizeof(xmlSchemaPSVIIDCKey));
22523 if (key == NULL) {
22524 xmlSchemaVErrMemory(NULL,
22525 "allocating a IDC key", NULL);
22526 xmlFree(keySeq);
22527 matcher->keySeqs[pos] = NULL;
22528 return(-1);
22529 }
22530 /*
22531 * Consume the compiled value.
22532 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022533 key->type = simpleType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022534 key->val = vctxt->inode->val;
22535 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022536 /*
22537 * Store the key in a global list.
22538 */
22539 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22540 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022541 return (-1);
22542 }
22543 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022544 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022545 }
22546 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022547
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022548 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022549 /* xmlSchemaPSVIIDCBindingPtr bind; */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022550 xmlSchemaPSVIIDCNodePtr ntItem;
22551 xmlSchemaIDCMatcherPtr matcher;
22552 xmlSchemaIDCPtr idc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022553 xmlSchemaItemListPtr targets;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022554 int pos, i, j, nbKeys;
22555 /*
22556 * Here we have the following scenario:
22557 * An IDC 'selector' state object resolved to a target node,
22558 * during the time this target node was in the
22559 * ancestor-or-self axis, the 'field' state object(s) looked
22560 * out for matching nodes to create a key-sequence for this
22561 * target node. Now we are back to this target node and need
22562 * to put the key-sequence, together with the target node
22563 * itself, into the node-table of the corresponding IDC
22564 * binding.
22565 */
22566 matcher = sto->matcher;
22567 idc = matcher->aidc->def;
22568 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022569 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022570 /*
22571 * Check if the matcher has any key-sequences at all, plus
22572 * if it has a key-sequence for the current target node.
22573 */
22574 if ((matcher->keySeqs == NULL) ||
22575 (matcher->sizeKeySeqs <= pos)) {
22576 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22577 goto selector_key_error;
22578 else
22579 goto selector_leave;
22580 }
22581
22582 keySeq = &(matcher->keySeqs[pos]);
22583 if (*keySeq == NULL) {
22584 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22585 goto selector_key_error;
22586 else
22587 goto selector_leave;
22588 }
22589
22590 for (i = 0; i < nbKeys; i++) {
22591 if ((*keySeq)[i] == NULL) {
22592 /*
22593 * Not qualified, if not all fields did resolve.
22594 */
22595 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22596 /*
22597 * All fields of a "key" IDC must resolve.
22598 */
22599 goto selector_key_error;
22600 }
22601 goto selector_leave;
22602 }
22603 }
22604 /*
22605 * All fields did resolve.
22606 */
22607
22608 /*
22609 * 4.1 If the {identity-constraint category} is unique(/key),
22610 * then no two members of the ·qualified node set· have
22611 * ·key-sequences· whose members are pairwise equal, as
22612 * defined by Equal in [XML Schemas: Datatypes].
22613 *
22614 * Get the IDC binding from the matcher and check for
22615 * duplicate key-sequences.
22616 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022617#if 0
22618 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22619#endif
22620 targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022621 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022622 (targets->nbItems != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022623 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022624
22625 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022626 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022627 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022628 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022629 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022630 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022631 bkeySeq =
22632 ((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022633 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022634 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022635 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022636 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022637 if (res == -1) {
22638 return (-1);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022639 } else if (res == 0) {
22640 /*
22641 * One of the keys differs, so the key-sequence
22642 * won't be equal; get out.
22643 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022644 break;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022645 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022646 }
22647 if (res == 1) {
22648 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022649 * Duplicate key-sequence found.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022650 */
22651 break;
22652 }
22653 i++;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022654 } while (i < targets->nbItems);
22655 if (i != targets->nbItems) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022656 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022657 /*
22658 * TODO: Try to report the key-sequence.
22659 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022660 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022661 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022662 WXS_BASIC_CAST idc,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022663 "Duplicate key-sequence %s in %s",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022664 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022665 (*keySeq), nbKeys),
22666 xmlSchemaGetIDCDesignation(&strB, idc));
22667 FREE_AND_NULL(str);
22668 FREE_AND_NULL(strB);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022669 goto selector_leave;
22670 }
22671 }
22672 /*
22673 * Add a node-table item to the IDC binding.
22674 */
22675 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
22676 sizeof(xmlSchemaPSVIIDCNode));
22677 if (ntItem == NULL) {
22678 xmlSchemaVErrMemory(NULL,
22679 "allocating an IDC node-table item", NULL);
22680 xmlFree(*keySeq);
22681 *keySeq = NULL;
22682 return(-1);
22683 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022684 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022685
22686 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022687 * Store the node-table item in a global list.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022688 */
22689 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
22690 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
22691 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022692 xmlFree(*keySeq);
22693 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022694 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022695 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022696 ntItem->nodeQNameID = -1;
22697 } else {
22698 /*
22699 * Save a cached QName for this node on the IDC node, to be
22700 * able to report it, even if the node is not saved.
22701 */
22702 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
22703 vctxt->inode->localName, vctxt->inode->nsName);
22704 if (ntItem->nodeQNameID == -1) {
22705 xmlFree(ntItem);
22706 xmlFree(*keySeq);
22707 *keySeq = NULL;
22708 return (-1);
22709 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022710 }
22711 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022712 * Init the node-table item: Save the node, position and
22713 * consume the key-sequence.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022714 */
22715 ntItem->node = vctxt->node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022716 ntItem->nodeLine = vctxt->inode->nodeLine;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022717 ntItem->keys = *keySeq;
22718 *keySeq = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022719#if 0
22720 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
22721#endif
22722 if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022723 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
22724 /*
22725 * Free the item, since keyref items won't be
22726 * put on a global list.
22727 */
22728 xmlFree(ntItem->keys);
22729 xmlFree(ntItem);
22730 }
22731 return (-1);
22732 }
22733
22734 goto selector_leave;
22735selector_key_error:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022736 {
22737 xmlChar *str = NULL;
22738 /*
22739 * 4.2.1 (KEY) The ·target node set· and the
22740 * ·qualified node set· are equal, that is, every
22741 * member of the ·target node set· is also a member
22742 * of the ·qualified node set· and vice versa.
22743 */
22744 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22745 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022746 WXS_BASIC_CAST idc,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022747 "Not all fields of %s evaluate to a node",
22748 xmlSchemaGetIDCDesignation(&str, idc), NULL);
22749 FREE_AND_NULL(str);
22750 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022751selector_leave:
22752 /*
22753 * Free the key-sequence if not added to the IDC table.
22754 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022755 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022756 xmlFree(*keySeq);
22757 *keySeq = NULL;
22758 }
22759 } /* if selector */
22760
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022761 sto->nbHistory--;
22762
22763deregister_check:
22764 /*
22765 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022766 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022767 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022768#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022769 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
22770 sto->sel->xpath);
22771#endif
22772 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022773 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022774 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022775 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022776 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022777 nextsto = sto->next;
22778 /*
22779 * Unlink from the list of active XPath state objects.
22780 */
22781 vctxt->xpathStates = sto->next;
22782 sto->next = vctxt->xpathStatePool;
22783 /*
22784 * Link it to the pool of reusable state objects.
22785 */
22786 vctxt->xpathStatePool = sto;
22787 sto = nextsto;
22788 } else
22789 sto = sto->next;
22790 } /* while (sto != NULL) */
22791 return (0);
22792}
22793
22794/**
22795 * xmlSchemaIDCRegisterMatchers:
22796 * @vctxt: the WXS validation context
22797 * @elemDecl: the element declaration
22798 *
22799 * Creates helper objects to evaluate IDC selectors/fields
22800 * successively.
22801 *
22802 * Returns 0 if OK and -1 on internal errors.
22803 */
22804static int
22805xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
22806 xmlSchemaElementPtr elemDecl)
22807{
22808 xmlSchemaIDCMatcherPtr matcher, last = NULL;
22809 xmlSchemaIDCPtr idc, refIdc;
22810 xmlSchemaIDCAugPtr aidc;
22811
22812 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
22813 if (idc == NULL)
22814 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022815
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022816#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022817 {
22818 xmlChar *str = NULL;
22819 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022820 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022821 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22822 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022823 FREE_AND_NULL(str)
22824 }
22825#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022826 if (vctxt->inode->idcMatchers != NULL) {
22827 VERROR_INT("xmlSchemaIDCRegisterMatchers",
22828 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022829 return (-1);
22830 }
22831 do {
22832 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
22833 /*
22834 * Since IDCs bubbles are expensive we need to know the
22835 * depth at which the bubbles should stop; this will be
22836 * the depth of the top-most keyref IDC. If no keyref
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022837 * references a key/unique IDC, the keyrefDepth will
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022838 * be -1, indicating that no bubbles are needed.
22839 */
22840 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
22841 if (refIdc != NULL) {
22842 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022843 * Remember that we have keyrefs on this node.
22844 */
22845 vctxt->inode->hasKeyrefs = 1;
22846 /*
22847 * Lookup the referenced augmented IDC info.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022848 */
22849 aidc = vctxt->aidcs;
22850 while (aidc != NULL) {
22851 if (aidc->def == refIdc)
22852 break;
22853 aidc = aidc->next;
22854 }
22855 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022856 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022857 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022858 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022859 return (-1);
22860 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022861 if ((aidc->keyrefDepth == -1) ||
22862 (vctxt->depth < aidc->keyrefDepth))
22863 aidc->keyrefDepth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022864 }
22865 }
22866 /*
22867 * Lookup the augmented IDC item for the IDC definition.
22868 */
22869 aidc = vctxt->aidcs;
22870 while (aidc != NULL) {
22871 if (aidc->def == idc)
22872 break;
22873 aidc = aidc->next;
22874 }
22875 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022876 VERROR_INT("xmlSchemaIDCRegisterMatchers",
22877 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022878 return (-1);
22879 }
22880 /*
22881 * Create an IDC matcher for every IDC definition.
22882 */
22883 matcher = (xmlSchemaIDCMatcherPtr)
22884 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
22885 if (matcher == NULL) {
22886 xmlSchemaVErrMemory(vctxt,
22887 "allocating an IDC matcher", NULL);
22888 return (-1);
22889 }
22890 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
22891 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022892 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022893 else
22894 last->next = matcher;
22895 last = matcher;
22896
22897 matcher->type = IDC_MATCHER;
22898 matcher->depth = vctxt->depth;
22899 matcher->aidc = aidc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022900 matcher->idcType = aidc->def->type;
22901#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022902 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
22903#endif
22904 /*
22905 * Init the automaton state object.
22906 */
22907 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022908 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022909 return (-1);
22910
22911 idc = idc->next;
22912 } while (idc != NULL);
22913 return (0);
22914}
22915
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022916static int
22917xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
22918 xmlSchemaNodeInfoPtr ielem)
22919{
22920 xmlSchemaPSVIIDCBindingPtr bind;
22921 int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
22922 xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
22923 xmlSchemaPSVIIDCNodePtr *targets, *dupls;
22924
22925 xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
22926 /* vctxt->createIDCNodeTables */
22927 while (matcher != NULL) {
22928 /*
22929 * Skip keyref IDCs and empty IDC target-lists.
22930 */
22931 if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
22932 WXS_ILIST_IS_EMPTY(matcher->targets))
22933 {
22934 matcher = matcher->next;
22935 continue;
22936 }
22937 /*
22938 * If we _want_ the IDC node-table to be created in any case
22939 * then do so. Otherwise create them only if keyrefs need them.
22940 */
22941 if ((! vctxt->createIDCNodeTables) &&
22942 ((matcher->aidc->keyrefDepth == -1) ||
22943 (matcher->aidc->keyrefDepth > vctxt->depth)))
22944 {
22945 matcher = matcher->next;
22946 continue;
22947 }
22948 /*
22949 * Get/create the IDC binding on this element for the IDC definition.
22950 */
22951 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22952
22953 if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
22954 dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
22955 nbDupls = bind->dupls->nbItems;
22956 } else {
22957 dupls = NULL;
22958 nbDupls = 0;
22959 }
22960 if (bind->nodeTable != NULL) {
22961 nbNodeTable = bind->nbNodes;
22962 } else {
22963 nbNodeTable = 0;
22964 }
22965
22966 if ((nbNodeTable == 0) && (nbDupls == 0)) {
22967 /*
22968 * Transfer all IDC target-nodes to the IDC node-table.
22969 */
22970 bind->nodeTable =
22971 (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
22972 bind->sizeNodes = matcher->targets->sizeItems;
22973 bind->nbNodes = matcher->targets->nbItems;
22974
22975 matcher->targets->items = NULL;
22976 matcher->targets->sizeItems = 0;
22977 matcher->targets->nbItems = 0;
22978 } else {
22979 /*
22980 * Compare the key-sequences and add to the IDC node-table.
22981 */
22982 nbTargets = matcher->targets->nbItems;
22983 targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
22984 nbFields = matcher->aidc->def->nbFields;
22985 i = 0;
22986 do {
22987 keys = targets[i]->keys;
22988 if (nbDupls) {
22989 /*
22990 * Search in already found duplicates first.
22991 */
22992 j = 0;
22993 do {
22994 if (nbFields == 1) {
22995 res = xmlSchemaAreValuesEqual(keys[0]->val,
22996 dupls[j]->keys[0]->val);
22997 if (res == -1)
22998 goto internal_error;
22999 if (res == 1) {
23000 /*
23001 * Equal key-sequence.
23002 */
23003 goto next_target;
23004 }
23005 } else {
23006 res = 0;
23007 ntkeys = dupls[j]->keys;
23008 for (k = 0; k < nbFields; k++) {
23009 res = xmlSchemaAreValuesEqual(keys[k]->val,
23010 ntkeys[k]->val);
23011 if (res == -1)
23012 goto internal_error;
23013 if (res == 0) {
23014 /*
23015 * One of the keys differs.
23016 */
23017 break;
23018 }
23019 }
23020 if (res == 1) {
23021 /*
23022 * Equal key-sequence found.
23023 */
23024 goto next_target;
23025 }
23026 }
23027 j++;
23028 } while (j < nbDupls);
23029 }
23030 if (nbNodeTable) {
23031 j = 0;
23032 do {
23033 if (nbFields == 1) {
23034 res = xmlSchemaAreValuesEqual(keys[0]->val,
23035 bind->nodeTable[j]->keys[0]->val);
23036 if (res == -1)
23037 goto internal_error;
23038 if (res == 0) {
23039 /*
23040 * The key-sequence differs.
23041 */
23042 goto next_node_table_entry;
23043 }
23044 } else {
23045 res = 0;
23046 ntkeys = bind->nodeTable[j]->keys;
23047 for (k = 0; k < nbFields; k++) {
23048 res = xmlSchemaAreValuesEqual(keys[k]->val,
23049 ntkeys[k]->val);
23050 if (res == -1)
23051 goto internal_error;
23052 if (res == 0) {
23053 /*
23054 * One of the keys differs.
23055 */
23056 goto next_node_table_entry;
23057 }
23058 }
23059 }
23060 /*
23061 * Add the duplicate to the list of duplicates.
23062 */
23063 if (bind->dupls == NULL) {
23064 bind->dupls = xmlSchemaItemListCreate();
23065 if (bind->dupls == NULL)
23066 goto internal_error;
23067 }
23068 if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23069 goto internal_error;
23070 /*
23071 * Remove the duplicate entry from the IDC node-table.
23072 */
23073 bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23074 bind->nbNodes--;
23075
23076 goto next_target;
23077
23078next_node_table_entry:
23079 j++;
23080 } while (j < nbNodeTable);
23081 }
23082 /*
23083 * If everything is fine, then add the IDC target-node to
23084 * the IDC node-table.
23085 */
23086 if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23087 goto internal_error;
23088
23089next_target:
23090 i++;
23091 } while (i < nbTargets);
23092 }
23093 matcher = matcher->next;
23094 }
23095 return(0);
23096
23097internal_error:
23098 return(-1);
23099}
23100
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023101/**
23102 * xmlSchemaBubbleIDCNodeTables:
23103 * @depth: the current tree depth
23104 *
23105 * Merges IDC bindings of an element at @depth into the corresponding IDC
23106 * bindings of its parent element. If a duplicate note-table entry is found,
23107 * both, the parent node-table entry and child entry are discarded from the
23108 * node-table of the parent.
23109 *
23110 * Returns 0 if OK and -1 on internal errors.
23111 */
23112static int
23113xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23114{
23115 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023116 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23117 xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023118 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023119 int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023120
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023121 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023122 if (bind == NULL) {
23123 /* Fine, no table, no bubbles. */
23124 return (0);
23125 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000023126
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023127 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23128 /*
23129 * Walk all bindings; create new or add to existing bindings.
23130 * Remove duplicate key-sequences.
23131 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023132 while (bind != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023133
23134 if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23135 goto next_binding;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023136 /*
23137 * Check if the key/unique IDC table needs to be bubbled.
23138 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023139 if (! vctxt->createIDCNodeTables) {
23140 aidc = vctxt->aidcs;
23141 do {
23142 if (aidc->def == bind->definition) {
23143 if ((aidc->keyrefDepth == -1) ||
23144 (aidc->keyrefDepth >= vctxt->depth)) {
23145 goto next_binding;
23146 }
23147 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023148 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023149 aidc = aidc->next;
23150 } while (aidc != NULL);
23151 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023152
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023153 if (parTable != NULL)
23154 parBind = *parTable;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023155 /*
23156 * Search a matching parent binding for the
23157 * IDC definition.
23158 */
23159 while (parBind != NULL) {
23160 if (parBind->definition == bind->definition)
23161 break;
23162 parBind = parBind->next;
23163 }
23164
23165 if (parBind != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023166 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023167 * Compare every node-table entry of the child node,
23168 * i.e. the key-sequence within, ...
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023169 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023170 oldNum = parBind->nbNodes; /* Skip newly added items. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023171
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023172 if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23173 oldDupls = parBind->dupls->nbItems;
23174 dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23175 } else {
23176 dupls = NULL;
23177 oldDupls = 0;
23178 }
23179
23180 parNodes = parBind->nodeTable;
23181 nbFields = bind->definition->nbFields;
23182
23183 for (i = 0; i < bind->nbNodes; i++) {
23184 node = bind->nodeTable[i];
23185 if (node == NULL)
23186 continue;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023187 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023188 * ...with every key-sequence of the parent node, already
23189 * evaluated to be a duplicate key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023190 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023191 if (oldDupls) {
23192 j = 0;
23193 while (j < oldDupls) {
23194 if (nbFields == 1) {
23195 ret = xmlSchemaAreValuesEqual(
23196 node->keys[0]->val,
23197 dupls[j]->keys[0]->val);
23198 if (ret == -1)
23199 goto internal_error;
23200 if (ret == 0) {
23201 j++;
23202 continue;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023203 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023204 } else {
23205 parNode = dupls[j];
23206 for (k = 0; k < nbFields; k++) {
23207 ret = xmlSchemaAreValuesEqual(
23208 node->keys[k]->val,
23209 parNode->keys[k]->val);
23210 if (ret == -1)
23211 goto internal_error;
23212 if (ret == 0)
23213 break;
23214 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023215 }
23216 if (ret == 1)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023217 /* Duplicate found. */
23218 break;
23219 j++;
23220 }
23221 if (j != oldDupls) {
23222 /* Duplicate found. Skip this entry. */
23223 continue;
23224 }
23225 }
23226 /*
23227 * ... and with every key-sequence of the parent node.
23228 */
23229 if (oldNum) {
23230 j = 0;
23231 while (j < oldNum) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +000023232 parNode = parNodes[j];
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023233 if (nbFields == 1) {
23234 ret = xmlSchemaAreValuesEqual(
23235 node->keys[0]->val,
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +000023236 parNode->keys[0]->val);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023237 if (ret == -1)
23238 goto internal_error;
23239 if (ret == 0) {
23240 j++;
23241 continue;
23242 }
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +000023243 } else {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023244 for (k = 0; k < nbFields; k++) {
23245 ret = xmlSchemaAreValuesEqual(
23246 node->keys[k]->val,
23247 parNode->keys[k]->val);
23248 if (ret == -1)
23249 goto internal_error;
23250 if (ret == 0)
23251 break;
23252 }
23253 }
23254 if (ret == 1)
23255 /* Duplicate found. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023256 break;
23257 j++;
23258 }
23259 if (j != oldNum) {
23260 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023261 * Handle duplicates. Move the duplicate in
23262 * the parent's node-table to the list of
23263 * duplicates.
23264 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023265 oldNum--;
23266 parBind->nbNodes--;
23267 /*
23268 * Move last old item to pos of duplicate.
23269 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023270 parNodes[j] = parNodes[oldNum];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023271
23272 if (parBind->nbNodes != oldNum) {
23273 /*
23274 * If new items exist, move last new item to
23275 * last of old items.
23276 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023277 parNodes[oldNum] =
23278 parNodes[parBind->nbNodes];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023279 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023280 if (parBind->dupls == NULL) {
23281 parBind->dupls = xmlSchemaItemListCreate();
23282 if (parBind->dupls == NULL)
23283 goto internal_error;
23284 }
23285 xmlSchemaItemListAdd(parBind->dupls, parNode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023286 } else {
23287 /*
23288 * Add the node-table entry (node and key-sequence) of
23289 * the child node to the node table of the parent node.
23290 */
23291 if (parBind->nodeTable == NULL) {
23292 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000023293 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023294 if (parBind->nodeTable == NULL) {
23295 xmlSchemaVErrMemory(NULL,
23296 "allocating IDC list of node-table items", NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023297 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023298 }
23299 parBind->sizeNodes = 1;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023300 } else if (parBind->nbNodes >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000023301 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023302 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23303 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23304 sizeof(xmlSchemaPSVIIDCNodePtr));
23305 if (parBind->nodeTable == NULL) {
23306 xmlSchemaVErrMemory(NULL,
23307 "re-allocating IDC list of node-table items", NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023308 goto internal_error;
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000023309 }
23310 }
23311 parNodes = parBind->nodeTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023312 /*
23313 * Append the new node-table entry to the 'new node-table
23314 * entries' section.
23315 */
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000023316 parNodes[parBind->nbNodes++] = node;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023317 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023318
23319 }
23320
23321 }
23322 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023323 /*
23324 * No binding for the IDC was found: create a new one and
23325 * copy all node-tables.
23326 */
23327 parBind = xmlSchemaIDCNewBinding(bind->definition);
23328 if (parBind == NULL)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023329 goto internal_error;
23330
23331 /*
23332 * TODO: Hmm, how to optimize the initial number of
23333 * allocated entries?
23334 */
23335 if (bind->nbNodes != 0) {
23336 /*
23337 * Add all IDC node-table entries.
23338 */
23339 if (! vctxt->psviExposeIDCNodeTables) {
23340 /*
23341 * Just move the entries.
23342 * NOTE: this is quite save here, since
23343 * all the keyref lookups have already been
23344 * performed.
23345 */
23346 parBind->nodeTable = bind->nodeTable;
23347 bind->nodeTable = NULL;
23348 parBind->sizeNodes = bind->sizeNodes;
23349 bind->sizeNodes = 0;
23350 parBind->nbNodes = bind->nbNodes;
23351 bind->nbNodes = 0;
23352 } else {
23353 /*
23354 * Copy the entries.
23355 */
23356 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23357 xmlMalloc(bind->nbNodes *
23358 sizeof(xmlSchemaPSVIIDCNodePtr));
23359 if (parBind->nodeTable == NULL) {
23360 xmlSchemaVErrMemory(NULL,
23361 "allocating an array of IDC node-table "
23362 "items", NULL);
23363 xmlSchemaIDCFreeBinding(parBind);
23364 goto internal_error;
23365 }
23366 parBind->sizeNodes = bind->nbNodes;
23367 parBind->nbNodes = bind->nbNodes;
23368 memcpy(parBind->nodeTable, bind->nodeTable,
23369 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23370 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023371 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023372 if (bind->dupls) {
23373 /*
23374 * Move the duplicates.
23375 */
23376 if (parBind->dupls != NULL)
23377 xmlSchemaItemListFree(parBind->dupls);
23378 parBind->dupls = bind->dupls;
23379 bind->dupls = NULL;
23380 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023381 if (*parTable == NULL)
23382 *parTable = parBind;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023383 else {
23384 parBind->next = *parTable;
23385 *parTable = parBind;
23386 }
23387 }
23388
23389next_binding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023390 bind = bind->next;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023391 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023392 return (0);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023393
23394internal_error:
23395 return(-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023396}
23397
23398/**
23399 * xmlSchemaCheckCVCIDCKeyRef:
23400 * @vctxt: the WXS validation context
23401 * @elemDecl: the element declaration
23402 *
23403 * Check the cvc-idc-keyref constraints.
23404 */
23405static int
23406xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23407{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023408 xmlSchemaIDCMatcherPtr matcher;
23409 xmlSchemaPSVIIDCBindingPtr bind;
23410
23411 matcher = vctxt->inode->idcMatchers;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023412 /*
23413 * Find a keyref.
23414 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023415 while (matcher != NULL) {
23416 if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23417 matcher->targets &&
23418 matcher->targets->nbItems)
23419 {
23420 int i, j, k, res, nbFields, hasDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023421 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023422 xmlSchemaPSVIIDCNodePtr refNode = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023423
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023424 nbFields = matcher->aidc->def->nbFields;
23425
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023426 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023427 * Find the IDC node-table for the referenced IDC key/unique.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023428 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023429 bind = vctxt->inode->idcTable;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023430 while (bind != NULL) {
23431 if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023432 bind->definition)
23433 break;
23434 bind = bind->next;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023435 }
23436 hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023437 /*
23438 * Search for a matching key-sequences.
23439 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023440 for (i = 0; i < matcher->targets->nbItems; i++) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023441 res = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023442 refNode = matcher->targets->items[i];
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023443 if (bind != NULL) {
23444 refKeys = refNode->keys;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023445 for (j = 0; j < bind->nbNodes; j++) {
23446 keys = bind->nodeTable[j]->keys;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023447 for (k = 0; k < nbFields; k++) {
23448 res = xmlSchemaAreValuesEqual(keys[k]->val,
23449 refKeys[k]->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023450 if (res == 0)
23451 break;
23452 else if (res == -1) {
23453 return (-1);
23454 }
23455 }
23456 if (res == 1) {
23457 /*
23458 * Match found.
23459 */
23460 break;
23461 }
23462 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023463 if ((res == 0) && hasDupls) {
23464 /*
23465 * Search in duplicates
23466 */
23467 for (j = 0; j < bind->dupls->nbItems; j++) {
23468 keys = ((xmlSchemaPSVIIDCNodePtr)
23469 bind->dupls->items[j])->keys;
23470 for (k = 0; k < nbFields; k++) {
23471 res = xmlSchemaAreValuesEqual(keys[k]->val,
23472 refKeys[k]->val);
23473 if (res == 0)
23474 break;
23475 else if (res == -1) {
23476 return (-1);
23477 }
23478 }
23479 if (res == 1) {
23480 /*
23481 * Match in duplicates found.
23482 */
23483 xmlChar *str = NULL, *strB = NULL;
23484 xmlSchemaKeyrefErr(vctxt,
23485 XML_SCHEMAV_CVC_IDC, refNode,
23486 (xmlSchemaTypePtr) matcher->aidc->def,
23487 "More than one match found for "
23488 "key-sequence %s of keyref '%s'",
23489 xmlSchemaFormatIDCKeySequence(vctxt, &str,
23490 refNode->keys, nbFields),
23491 xmlSchemaGetComponentQName(&strB,
23492 matcher->aidc->def));
23493 FREE_AND_NULL(str);
23494 FREE_AND_NULL(strB);
23495 break;
23496 }
23497 }
23498 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023499 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023500
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023501 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023502 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023503 xmlSchemaKeyrefErr(vctxt,
23504 XML_SCHEMAV_CVC_IDC, refNode,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023505 (xmlSchemaTypePtr) matcher->aidc->def,
23506 "No match found for key-sequence %s of keyref '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000023507 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023508 refNode->keys, nbFields),
23509 xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023510 FREE_AND_NULL(str);
23511 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023512 }
23513 }
23514 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023515 matcher = matcher->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023516 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023517 /* TODO: Return an error if any error encountered. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023518 return (0);
23519}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023520
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023521/************************************************************************
23522 * *
23523 * XML Reader validation code *
23524 * *
23525 ************************************************************************/
23526
23527static xmlSchemaAttrInfoPtr
23528xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023529{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023530 xmlSchemaAttrInfoPtr iattr;
23531 /*
23532 * Grow/create list of attribute infos.
23533 */
23534 if (vctxt->attrInfos == NULL) {
23535 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23536 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23537 vctxt->sizeAttrInfos = 1;
23538 if (vctxt->attrInfos == NULL) {
23539 xmlSchemaVErrMemory(vctxt,
23540 "allocating attribute info list", NULL);
23541 return (NULL);
23542 }
23543 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23544 vctxt->sizeAttrInfos++;
23545 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23546 xmlRealloc(vctxt->attrInfos,
23547 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23548 if (vctxt->attrInfos == NULL) {
23549 xmlSchemaVErrMemory(vctxt,
23550 "re-allocating attribute info list", NULL);
23551 return (NULL);
23552 }
23553 } else {
23554 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23555 if (iattr->localName != NULL) {
23556 VERROR_INT("xmlSchemaGetFreshAttrInfo",
23557 "attr info not cleared");
23558 return (NULL);
23559 }
23560 iattr->nodeType = XML_ATTRIBUTE_NODE;
23561 return (iattr);
23562 }
23563 /*
23564 * Create an attribute info.
23565 */
23566 iattr = (xmlSchemaAttrInfoPtr)
23567 xmlMalloc(sizeof(xmlSchemaAttrInfo));
23568 if (iattr == NULL) {
23569 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23570 return (NULL);
23571 }
23572 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23573 iattr->nodeType = XML_ATTRIBUTE_NODE;
23574 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23575
23576 return (iattr);
23577}
23578
23579static int
23580xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23581 xmlNodePtr attrNode,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023582 int nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023583 const xmlChar *localName,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023584 const xmlChar *nsName,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023585 int ownedNames,
23586 xmlChar *value,
23587 int ownedValue)
23588{
23589 xmlSchemaAttrInfoPtr attr;
23590
23591 attr = xmlSchemaGetFreshAttrInfo(vctxt);
23592 if (attr == NULL) {
23593 VERROR_INT("xmlSchemaPushAttribute",
23594 "calling xmlSchemaGetFreshAttrInfo()");
23595 return (-1);
23596 }
23597 attr->node = attrNode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023598 attr->nodeLine = nodeLine;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023599 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23600 attr->localName = localName;
23601 attr->nsName = nsName;
23602 if (ownedNames)
23603 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23604 /*
23605 * Evaluate if it's an XSI attribute.
23606 */
23607 if (nsName != NULL) {
23608 if (xmlStrEqual(localName, BAD_CAST "nil")) {
23609 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23610 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23611 }
23612 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
23613 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23614 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23615 }
23616 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23617 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23618 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23619 }
23620 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23621 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23622 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23623 }
23624 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
23625 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
23626 }
23627 }
23628 attr->value = value;
23629 if (ownedValue)
23630 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23631 if (attr->metaType != 0)
23632 attr->state = XML_SCHEMAS_ATTR_META;
23633 return (0);
23634}
23635
23636static void
23637xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
23638{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023639 ielem->hasKeyrefs = 0;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000023640 ielem->appliedXPath = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023641 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
23642 FREE_AND_NULL(ielem->localName);
23643 FREE_AND_NULL(ielem->nsName);
23644 } else {
23645 ielem->localName = NULL;
23646 ielem->nsName = NULL;
23647 }
23648 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
23649 FREE_AND_NULL(ielem->value);
23650 } else {
23651 ielem->value = NULL;
23652 }
23653 if (ielem->val != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023654 /*
23655 * PSVI TODO: Be careful not to free it when the value is
23656 * exposed via PSVI.
23657 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023658 xmlSchemaFreeValue(ielem->val);
23659 ielem->val = NULL;
23660 }
23661 if (ielem->idcMatchers != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023662 /*
23663 * URGENT OPTIMIZE TODO: Use a pool of IDC matchers.
23664 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023665 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
23666 ielem->idcMatchers = NULL;
23667 }
23668 if (ielem->idcTable != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023669 /*
23670 * OPTIMIZE TODO: Use a pool of IDC tables??.
23671 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023672 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
23673 ielem->idcTable = NULL;
23674 }
23675 if (ielem->regexCtxt != NULL) {
23676 xmlRegFreeExecCtxt(ielem->regexCtxt);
23677 ielem->regexCtxt = NULL;
23678 }
23679 if (ielem->nsBindings != NULL) {
23680 xmlFree((xmlChar **)ielem->nsBindings);
23681 ielem->nsBindings = NULL;
23682 ielem->nbNsBindings = 0;
23683 ielem->sizeNsBindings = 0;
23684 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023685}
23686
23687/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023688 * xmlSchemaGetFreshElemInfo:
23689 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023690 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023691 * Creates/reuses and initializes the element info item for
23692 * the currect tree depth.
23693 *
23694 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023695 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023696static xmlSchemaNodeInfoPtr
23697xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023698{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023699 xmlSchemaNodeInfoPtr info = NULL;
23700
23701 if (vctxt->depth > vctxt->sizeElemInfos) {
23702 VERROR_INT("xmlSchemaGetFreshElemInfo",
23703 "inconsistent depth encountered");
23704 return (NULL);
23705 }
23706 if (vctxt->elemInfos == NULL) {
23707 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
23708 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
23709 if (vctxt->elemInfos == NULL) {
23710 xmlSchemaVErrMemory(vctxt,
23711 "allocating the element info array", NULL);
23712 return (NULL);
23713 }
23714 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
23715 vctxt->sizeElemInfos = 10;
23716 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
23717 int i = vctxt->sizeElemInfos;
23718
23719 vctxt->sizeElemInfos *= 2;
23720 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
23721 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
23722 sizeof(xmlSchemaNodeInfoPtr));
23723 if (vctxt->elemInfos == NULL) {
23724 xmlSchemaVErrMemory(vctxt,
23725 "re-allocating the element info array", NULL);
23726 return (NULL);
23727 }
23728 /*
23729 * We need the new memory to be NULLed.
23730 * TODO: Use memset instead?
23731 */
23732 for (; i < vctxt->sizeElemInfos; i++)
23733 vctxt->elemInfos[i] = NULL;
23734 } else
23735 info = vctxt->elemInfos[vctxt->depth];
23736
23737 if (info == NULL) {
23738 info = (xmlSchemaNodeInfoPtr)
23739 xmlMalloc(sizeof(xmlSchemaNodeInfo));
23740 if (info == NULL) {
23741 xmlSchemaVErrMemory(vctxt,
23742 "allocating an element info", NULL);
23743 return (NULL);
23744 }
23745 vctxt->elemInfos[vctxt->depth] = info;
23746 } else {
23747 if (info->localName != NULL) {
23748 VERROR_INT("xmlSchemaGetFreshElemInfo",
23749 "elem info has not been cleared");
23750 return (NULL);
23751 }
23752 }
23753 memset(info, 0, sizeof(xmlSchemaNodeInfo));
23754 info->nodeType = XML_ELEMENT_NODE;
23755 info->depth = vctxt->depth;
23756
23757 return (info);
23758}
23759
23760#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
23761#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
23762#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
23763
23764static int
23765xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
23766 xmlNodePtr node,
23767 xmlSchemaTypePtr type,
23768 xmlSchemaValType valType,
23769 const xmlChar * value,
23770 xmlSchemaValPtr val,
23771 unsigned long length,
23772 int fireErrors)
23773{
23774 int ret, error = 0;
23775
23776 xmlSchemaTypePtr tmpType;
23777 xmlSchemaFacetLinkPtr facetLink;
23778 xmlSchemaFacetPtr facet;
23779 unsigned long len = 0;
23780 xmlSchemaWhitespaceValueType ws;
23781
23782 /*
23783 * In Libxml2, derived built-in types have currently no explicit facets.
23784 */
23785 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023786 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023787
23788 /*
23789 * NOTE: Do not jump away, if the facetSet of the given type is
23790 * empty: until now, "pattern" and "enumeration" facets of the
23791 * *base types* need to be checked as well.
23792 */
23793 if (type->facetSet == NULL)
23794 goto pattern_and_enum;
23795
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023796 if (! WXS_IS_ATOMIC(type)) {
23797 if (WXS_IS_LIST(type))
23798 goto WXS_IS_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023799 else
23800 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023801 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023802 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023803 * Whitespace handling is only of importance for string-based
23804 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023805 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023806 tmpType = xmlSchemaGetPrimitiveType(type);
23807 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023808 WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023809 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
23810 } else
23811 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
23812 /*
23813 * If the value was not computed (for string or
23814 * anySimpleType based types), then use the provided
23815 * type.
23816 */
23817 if (val == NULL)
23818 valType = valType;
23819 else
23820 valType = xmlSchemaGetValType(val);
23821
23822 ret = 0;
23823 for (facetLink = type->facetSet; facetLink != NULL;
23824 facetLink = facetLink->next) {
23825 /*
23826 * Skip the pattern "whiteSpace": it is used to
23827 * format the character content beforehand.
23828 */
23829 switch (facetLink->facet->type) {
23830 case XML_SCHEMA_FACET_WHITESPACE:
23831 case XML_SCHEMA_FACET_PATTERN:
23832 case XML_SCHEMA_FACET_ENUMERATION:
23833 continue;
23834 case XML_SCHEMA_FACET_LENGTH:
23835 case XML_SCHEMA_FACET_MINLENGTH:
23836 case XML_SCHEMA_FACET_MAXLENGTH:
23837 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
23838 valType, value, val, &len, ws);
23839 break;
23840 default:
23841 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
23842 valType, value, val, ws);
23843 break;
23844 }
23845 if (ret < 0) {
23846 AERROR_INT("xmlSchemaValidateFacets",
23847 "validating against a atomic type facet");
23848 return (-1);
23849 } else if (ret > 0) {
23850 if (fireErrors)
23851 xmlSchemaFacetErr(actxt, ret, node,
23852 value, len, type, facetLink->facet, NULL, NULL, NULL);
23853 else
23854 return (ret);
23855 if (error == 0)
23856 error = ret;
23857 }
23858 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023859 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023860
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023861WXS_IS_LIST:
23862 if (! WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023863 goto pattern_and_enum;
23864 /*
23865 * "length", "minLength" and "maxLength" of list types.
23866 */
23867 ret = 0;
23868 for (facetLink = type->facetSet; facetLink != NULL;
23869 facetLink = facetLink->next) {
23870
23871 switch (facetLink->facet->type) {
23872 case XML_SCHEMA_FACET_LENGTH:
23873 case XML_SCHEMA_FACET_MINLENGTH:
23874 case XML_SCHEMA_FACET_MAXLENGTH:
23875 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
23876 value, length, NULL);
23877 break;
23878 default:
23879 continue;
23880 }
23881 if (ret < 0) {
23882 AERROR_INT("xmlSchemaValidateFacets",
23883 "validating against a list type facet");
23884 return (-1);
23885 } else if (ret > 0) {
23886 if (fireErrors)
23887 xmlSchemaFacetErr(actxt, ret, node,
23888 value, length, type, facetLink->facet, NULL, NULL, NULL);
23889 else
23890 return (ret);
23891 if (error == 0)
23892 error = ret;
23893 }
23894 ret = 0;
23895 }
23896
23897pattern_and_enum:
23898 if (error >= 0) {
23899 int found = 0;
23900 /*
23901 * Process enumerations. Facet values are in the value space
23902 * of the defining type's base type. This seems to be a bug in the
23903 * XML Schema 1.0 spec. Use the whitespace type of the base type.
23904 * Only the first set of enumerations in the ancestor-or-self axis
23905 * is used for validation.
23906 */
23907 ret = 0;
23908 tmpType = type;
23909 do {
23910 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
23911 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
23912 continue;
23913 found = 1;
23914 ret = xmlSchemaAreValuesEqual(facet->val, val);
23915 if (ret == 1)
23916 break;
23917 else if (ret < 0) {
23918 AERROR_INT("xmlSchemaValidateFacets",
23919 "validating against an enumeration facet");
23920 return (-1);
23921 }
23922 }
23923 if (ret != 0)
23924 break;
23925 tmpType = tmpType->baseType;
23926 } while ((tmpType != NULL) &&
23927 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
23928 if (found && (ret == 0)) {
23929 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
23930 if (fireErrors) {
23931 xmlSchemaFacetErr(actxt, ret, node,
23932 value, 0, type, NULL, NULL, NULL, NULL);
23933 } else
23934 return (ret);
23935 if (error == 0)
23936 error = ret;
23937 }
23938 }
23939
23940 if (error >= 0) {
23941 int found;
23942 /*
23943 * Process patters. Pattern facets are ORed at type level
23944 * and ANDed if derived. Walk the base type axis.
23945 */
23946 tmpType = type;
23947 facet = NULL;
23948 do {
23949 found = 0;
23950 for (facetLink = tmpType->facetSet; facetLink != NULL;
23951 facetLink = facetLink->next) {
23952 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
23953 continue;
23954 found = 1;
23955 /*
23956 * NOTE that for patterns, @value needs to be the
23957 * normalized vaule.
23958 */
23959 ret = xmlRegexpExec(facetLink->facet->regexp, value);
23960 if (ret == 1)
23961 break;
23962 else if (ret < 0) {
23963 AERROR_INT("xmlSchemaValidateFacets",
23964 "validating against a pattern facet");
23965 return (-1);
23966 } else {
23967 /*
23968 * Save the last non-validating facet.
23969 */
23970 facet = facetLink->facet;
23971 }
23972 }
23973 if (found && (ret != 1)) {
23974 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
23975 if (fireErrors) {
23976 xmlSchemaFacetErr(actxt, ret, node,
23977 value, 0, type, facet, NULL, NULL, NULL);
23978 } else
23979 return (ret);
23980 if (error == 0)
23981 error = ret;
23982 break;
23983 }
23984 tmpType = tmpType->baseType;
23985 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
23986 }
23987
23988 return (error);
23989}
23990
23991static xmlChar *
23992xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
23993 const xmlChar *value)
23994{
23995 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
23996 case XML_SCHEMA_WHITESPACE_COLLAPSE:
23997 return (xmlSchemaCollapseString(value));
23998 case XML_SCHEMA_WHITESPACE_REPLACE:
23999 return (xmlSchemaWhiteSpaceReplace(value));
24000 default:
24001 return (NULL);
24002 }
24003}
24004
24005static int
24006xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24007 const xmlChar *value,
24008 xmlSchemaValPtr *val,
24009 int valNeeded)
24010{
24011 int ret;
24012 const xmlChar *nsName;
24013 xmlChar *local, *prefix = NULL;
24014
24015 ret = xmlValidateQName(value, 1);
24016 if (ret != 0) {
24017 if (ret == -1) {
24018 VERROR_INT("xmlSchemaValidateQName",
24019 "calling xmlValidateQName()");
24020 return (-1);
24021 }
24022 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24023 }
24024 /*
24025 * NOTE: xmlSplitQName2 will always return a duplicated
24026 * strings.
24027 */
24028 local = xmlSplitQName2(value, &prefix);
24029 if (local == NULL)
24030 local = xmlStrdup(value);
24031 /*
24032 * OPTIMIZE TODO: Use flags for:
24033 * - is there any namespace binding?
24034 * - is there a default namespace?
24035 */
24036 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24037
24038 if (prefix != NULL) {
24039 xmlFree(prefix);
24040 /*
24041 * A namespace must be found if the prefix is
24042 * NOT NULL.
24043 */
24044 if (nsName == NULL) {
24045 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024046 xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024047 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024048 "The QName value '%s' has no "
24049 "corresponding namespace declaration in "
24050 "scope", value, NULL);
24051 if (local != NULL)
24052 xmlFree(local);
24053 return (ret);
24054 }
24055 }
24056 if (valNeeded && val) {
24057 if (nsName != NULL)
24058 *val = xmlSchemaNewQNameValue(
24059 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24060 else
24061 *val = xmlSchemaNewQNameValue(NULL,
24062 BAD_CAST local);
24063 } else
24064 xmlFree(local);
24065 return (0);
24066}
24067
24068/*
24069* cvc-simple-type
24070*/
24071static int
24072xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24073 xmlNodePtr node,
24074 xmlSchemaTypePtr type,
24075 const xmlChar *value,
24076 xmlSchemaValPtr *retVal,
24077 int fireErrors,
24078 int normalize,
24079 int isNormalized)
24080{
24081 int ret = 0, valNeeded = (retVal) ? 1 : 0;
24082 xmlSchemaValPtr val = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024083 /* xmlSchemaWhitespaceValueType ws; */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024084 xmlChar *normValue = NULL;
24085
24086#define NORMALIZE(atype) \
24087 if ((! isNormalized) && \
24088 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24089 normValue = xmlSchemaNormalizeValue(atype, value); \
24090 if (normValue != NULL) \
24091 value = normValue; \
24092 isNormalized = 1; \
24093 }
24094
24095 if ((retVal != NULL) && (*retVal != NULL)) {
24096 xmlSchemaFreeValue(*retVal);
24097 *retVal = NULL;
24098 }
24099 /*
24100 * 3.14.4 Simple Type Definition Validation Rules
24101 * Validation Rule: String Valid
24102 */
24103 /*
24104 * 1 It is schema-valid with respect to that definition as defined
24105 * by Datatype Valid in [XML Schemas: Datatypes].
24106 */
24107 /*
24108 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24109 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
24110 * the string must be a ·declared entity name·.
24111 */
24112 /*
24113 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24114 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
24115 * then every whitespace-delimited substring of the string must be a ·declared
24116 * entity name·.
24117 */
24118 /*
24119 * 2.3 otherwise no further condition applies.
24120 */
24121 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24122 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000024123 if (value == NULL)
24124 value = BAD_CAST "";
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024125 if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024126 xmlSchemaTypePtr biType; /* The built-in type. */
24127 /*
24128 * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match·
24129 * a literal in the ·lexical space· of {base type definition}"
24130 */
24131 /*
24132 * Whitespace-normalize.
24133 */
24134 NORMALIZE(type);
24135 if (type->type != XML_SCHEMA_TYPE_BASIC) {
24136 /*
24137 * Get the built-in type.
24138 */
24139 biType = type->baseType;
24140 while ((biType != NULL) &&
24141 (biType->type != XML_SCHEMA_TYPE_BASIC))
24142 biType = biType->baseType;
24143
24144 if (biType == NULL) {
24145 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24146 "could not get the built-in type");
24147 goto internal_error;
24148 }
24149 } else
24150 biType = type;
24151 /*
24152 * NOTATIONs need to be processed here, since they need
24153 * to lookup in the hashtable of NOTATION declarations of the schema.
24154 */
24155 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24156 switch (biType->builtInType) {
24157 case XML_SCHEMAS_NOTATION:
24158 ret = xmlSchemaValidateNotation(
24159 (xmlSchemaValidCtxtPtr) actxt,
24160 ((xmlSchemaValidCtxtPtr) actxt)->schema,
24161 NULL, value, &val, valNeeded);
24162 break;
24163 case XML_SCHEMAS_QNAME:
24164 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24165 value, &val, valNeeded);
24166 break;
24167 default:
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024168 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024169 if (valNeeded)
24170 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24171 value, &val, NULL);
24172 else
24173 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24174 value, NULL, NULL);
24175 break;
24176 }
24177 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24178 switch (biType->builtInType) {
24179 case XML_SCHEMAS_NOTATION:
24180 ret = xmlSchemaValidateNotation(NULL,
24181 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24182 value, &val, valNeeded);
24183 break;
24184 default:
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024185 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024186 if (valNeeded)
24187 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24188 value, &val, node);
24189 else
24190 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24191 value, NULL, node);
24192 break;
24193 }
24194 } else {
24195 /*
24196 * Validation via a public API is not implemented yet.
24197 */
24198 TODO
24199 goto internal_error;
24200 }
24201 if (ret != 0) {
24202 if (ret < 0) {
24203 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24204 "validating against a built-in type");
24205 goto internal_error;
24206 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024207 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024208 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24209 else
24210 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24211 }
24212 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24213 /*
24214 * Check facets.
24215 */
24216 ret = xmlSchemaValidateFacets(actxt, node, type,
24217 (xmlSchemaValType) biType->builtInType, value, val,
24218 0, fireErrors);
24219 if (ret != 0) {
24220 if (ret < 0) {
24221 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24222 "validating facets of atomic simple type");
24223 goto internal_error;
24224 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024225 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024226 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24227 else
24228 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24229 }
24230 }
24231 if (fireErrors && (ret > 0))
24232 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024233 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024234
24235 xmlSchemaTypePtr itemType;
24236 const xmlChar *cur, *end;
24237 xmlChar *tmpValue = NULL;
24238 unsigned long len = 0;
24239 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24240 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
24241 * of white space separated tokens, each of which ·match·es a literal
24242 * in the ·lexical space· of {item type definition}
24243 */
24244 /*
24245 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24246 * the list type has an enum or pattern facet.
24247 */
24248 NORMALIZE(type);
24249 /*
24250 * VAL TODO: Optimize validation of empty values.
24251 * VAL TODO: We do not have computed values for lists.
24252 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024253 itemType = WXS_LIST_ITEMTYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024254 cur = value;
24255 do {
24256 while (IS_BLANK_CH(*cur))
24257 cur++;
24258 end = cur;
24259 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24260 end++;
24261 if (end == cur)
24262 break;
24263 tmpValue = xmlStrndup(cur, end - cur);
24264 len++;
24265
24266 if (valNeeded)
24267 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24268 tmpValue, &curVal, fireErrors, 0, 1);
24269 else
24270 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24271 tmpValue, NULL, fireErrors, 0, 1);
24272 FREE_AND_NULL(tmpValue);
24273 if (curVal != NULL) {
24274 /*
24275 * Add to list of computed values.
24276 */
24277 if (val == NULL)
24278 val = curVal;
24279 else
24280 xmlSchemaValueAppend(prevVal, curVal);
24281 prevVal = curVal;
24282 curVal = NULL;
24283 }
24284 if (ret != 0) {
24285 if (ret < 0) {
24286 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24287 "validating an item of list simple type");
24288 goto internal_error;
24289 }
24290 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24291 break;
24292 }
24293 cur = end;
24294 } while (*cur != 0);
24295 FREE_AND_NULL(tmpValue);
24296 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24297 /*
24298 * Apply facets (pattern, enumeration).
24299 */
24300 ret = xmlSchemaValidateFacets(actxt, node, type,
24301 XML_SCHEMAS_UNKNOWN, value, val,
24302 len, fireErrors);
24303 if (ret != 0) {
24304 if (ret < 0) {
24305 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24306 "validating facets of list simple type");
24307 goto internal_error;
24308 }
24309 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24310 }
24311 }
24312 if (fireErrors && (ret > 0)) {
24313 /*
24314 * Report the normalized value.
24315 */
24316 normalize = 1;
24317 NORMALIZE(type);
24318 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24319 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024320 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024321 xmlSchemaTypeLinkPtr memberLink;
24322 /*
24323 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
24324 * not apply directly; however, the normalization behavior of ·union·
24325 * types is controlled by the value of whiteSpace on that one of the
24326 * ·memberTypes· against which the ·union· is successfully validated.
24327 *
24328 * This means that the value is normalized by the first validating
24329 * member type, then the facets of the union type are applied. This
24330 * needs changing of the value!
24331 */
24332
24333 /*
24334 * 1.2.3 if {variety} is ·union· then the string must ·match· a
24335 * literal in the ·lexical space· of at least one member of
24336 * {member type definitions}
24337 */
24338 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24339 if (memberLink == NULL) {
24340 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24341 "union simple type has no member types");
24342 goto internal_error;
24343 }
24344 /*
24345 * Always normalize union type values, since we currently
24346 * cannot store the whitespace information with the value
24347 * itself; otherwise a later value-comparison would be
24348 * not possible.
24349 */
24350 while (memberLink != NULL) {
24351 if (valNeeded)
24352 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24353 memberLink->type, value, &val, 0, 1, 0);
24354 else
24355 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24356 memberLink->type, value, NULL, 0, 1, 0);
24357 if (ret <= 0)
24358 break;
24359 memberLink = memberLink->next;
24360 }
24361 if (ret != 0) {
24362 if (ret < 0) {
24363 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24364 "validating members of union simple type");
24365 goto internal_error;
24366 }
24367 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24368 }
24369 /*
24370 * Apply facets (pattern, enumeration).
24371 */
24372 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24373 /*
24374 * The normalization behavior of ·union· types is controlled by
24375 * the value of whiteSpace on that one of the ·memberTypes·
24376 * against which the ·union· is successfully validated.
24377 */
24378 NORMALIZE(memberLink->type);
24379 ret = xmlSchemaValidateFacets(actxt, node, type,
24380 XML_SCHEMAS_UNKNOWN, value, val,
24381 0, fireErrors);
24382 if (ret != 0) {
24383 if (ret < 0) {
24384 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24385 "validating facets of union simple type");
24386 goto internal_error;
24387 }
24388 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24389 }
24390 }
24391 if (fireErrors && (ret > 0))
24392 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24393 }
24394
24395 if (normValue != NULL)
24396 xmlFree(normValue);
24397 if (ret == 0) {
24398 if (retVal != NULL)
24399 *retVal = val;
24400 else if (val != NULL)
24401 xmlSchemaFreeValue(val);
24402 } else if (val != NULL)
24403 xmlSchemaFreeValue(val);
24404 return (ret);
24405internal_error:
24406 if (normValue != NULL)
24407 xmlFree(normValue);
24408 if (val != NULL)
24409 xmlSchemaFreeValue(val);
24410 return (-1);
24411}
24412
24413static int
24414xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24415 const xmlChar *value,
24416 const xmlChar **nsName,
24417 const xmlChar **localName)
24418{
24419 int ret = 0;
24420
24421 if ((nsName == NULL) || (localName == NULL))
24422 return (-1);
24423 *nsName = NULL;
24424 *localName = NULL;
24425
24426 ret = xmlValidateQName(value, 1);
24427 if (ret == -1)
24428 return (-1);
24429 if (ret > 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024430 xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024431 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24432 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24433 return (1);
24434 }
24435 {
24436 xmlChar *local = NULL;
24437 xmlChar *prefix;
24438
24439 /*
24440 * NOTE: xmlSplitQName2 will return a duplicated
24441 * string.
24442 */
24443 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024444 if (local == NULL)
24445 *localName = xmlDictLookup(vctxt->dict, value, -1);
24446 else {
24447 *localName = xmlDictLookup(vctxt->dict, local, -1);
24448 xmlFree(local);
24449 }
24450
24451 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24452
24453 if (prefix != NULL) {
24454 xmlFree(prefix);
24455 /*
24456 * A namespace must be found if the prefix is NOT NULL.
24457 */
24458 if (*nsName == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024459 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024460 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024461 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024462 "The QName value '%s' has no "
24463 "corresponding namespace declaration in scope",
24464 value, NULL);
24465 return (2);
24466 }
24467 }
24468 }
24469 return (0);
24470}
24471
24472static int
24473xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24474 xmlSchemaAttrInfoPtr iattr,
24475 xmlSchemaTypePtr *localType,
24476 xmlSchemaElementPtr elemDecl)
24477{
24478 int ret = 0;
24479 /*
24480 * cvc-elt (3.3.4) : (4)
24481 * AND
24482 * Schema-Validity Assessment (Element) (cvc-assess-elt)
24483 * (1.2.1.2.1) - (1.2.1.2.4)
24484 * Handle 'xsi:type'.
24485 */
24486 if (localType == NULL)
24487 return (-1);
24488 *localType = NULL;
24489 if (iattr == NULL)
24490 return (0);
24491 else {
24492 const xmlChar *nsName = NULL, *local = NULL;
24493 /*
24494 * TODO: We should report a *warning* that the type was overriden
24495 * by the instance.
24496 */
24497 ACTIVATE_ATTRIBUTE(iattr);
24498 /*
24499 * (cvc-elt) (3.3.4) : (4.1)
24500 * (cvc-assess-elt) (1.2.1.2.2)
24501 */
24502 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24503 &nsName, &local);
24504 if (ret != 0) {
24505 if (ret < 0) {
24506 VERROR_INT("xmlSchemaValidateElementByDeclaration",
24507 "calling xmlSchemaQNameExpand() to validate the "
24508 "attribute 'xsi:type'");
24509 goto internal_error;
24510 }
24511 goto exit;
24512 }
24513 /*
24514 * (cvc-elt) (3.3.4) : (4.2)
24515 * (cvc-assess-elt) (1.2.1.2.3)
24516 */
24517 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24518 if (*localType == NULL) {
24519 xmlChar *str = NULL;
24520
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024521 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024522 XML_SCHEMAV_CVC_ELT_4_2, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024523 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024524 "The QName value '%s' of the xsi:type attribute does not "
24525 "resolve to a type definition",
24526 xmlSchemaFormatQName(&str, nsName, local), NULL);
24527 FREE_AND_NULL(str);
24528 ret = vctxt->err;
24529 goto exit;
24530 }
24531 if (elemDecl != NULL) {
24532 int set = 0;
24533
24534 /*
24535 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24536 * "The ·local type definition· must be validly
24537 * derived from the {type definition} given the union of
24538 * the {disallowed substitutions} and the {type definition}'s
24539 * {prohibited substitutions}, as defined in
24540 * Type Derivation OK (Complex) (§3.4.6)
24541 * (if it is a complex type definition),
24542 * or given {disallowed substitutions} as defined in Type
24543 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
24544 * definition)."
24545 *
24546 * {disallowed substitutions}: the "block" on the element decl.
24547 * {prohibited substitutions}: the "block" on the type def.
24548 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000024549 /*
24550 * OPTIMIZE TODO: We could map types already evaluated
24551 * to be validly derived from other types to avoid checking
24552 * this over and over for the same types.
24553 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024554 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24555 (elemDecl->subtypes->flags &
24556 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24557 set |= SUBSET_EXTENSION;
24558
24559 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24560 (elemDecl->subtypes->flags &
24561 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24562 set |= SUBSET_RESTRICTION;
24563
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000024564 /*
24565 * REMOVED and CHANGED since this produced a parser context
24566 * which adds to the string dict of the schema. So this would
24567 * change the schema and we don't want this. We don't need
24568 * the parser context anymore.
24569 *
24570 * if ((vctxt->pctxt == NULL) &&
24571 * (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24572 * return (-1);
24573 */
24574
24575 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024576 elemDecl->subtypes, set) != 0) {
24577 xmlChar *str = NULL;
24578
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024579 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024580 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24581 "The type definition '%s', specified by xsi:type, is "
24582 "blocked or not validly derived from the type definition "
24583 "of the element declaration",
24584 xmlSchemaFormatQName(&str,
24585 (*localType)->targetNamespace,
24586 (*localType)->name),
24587 NULL);
24588 FREE_AND_NULL(str);
24589 ret = vctxt->err;
24590 *localType = NULL;
24591 }
24592 }
24593 }
24594exit:
24595 ACTIVATE_ELEM;
24596 return (ret);
24597internal_error:
24598 ACTIVATE_ELEM;
24599 return (-1);
24600}
24601
24602static int
24603xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24604{
24605 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
Daniel Veillard14b56432006-03-09 18:41:40 +000024606 xmlSchemaTypePtr actualType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024607
24608 /*
24609 * cvc-elt (3.3.4) : 1
24610 */
24611 if (elemDecl == NULL) {
24612 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
24613 "No matching declaration available");
24614 return (vctxt->err);
24615 }
Daniel Veillard14b56432006-03-09 18:41:40 +000024616 actualType = WXS_ELEM_TYPEDEF(elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024617 /*
24618 * cvc-elt (3.3.4) : 2
24619 */
24620 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
24621 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
24622 "The element declaration is abstract");
24623 return (vctxt->err);
24624 }
24625 if (actualType == NULL) {
24626 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24627 "The type definition is absent");
24628 return (XML_SCHEMAV_CVC_TYPE_1);
24629 }
24630 if (vctxt->nbAttrInfos != 0) {
24631 int ret;
24632 xmlSchemaAttrInfoPtr iattr;
24633 /*
24634 * cvc-elt (3.3.4) : 3
24635 * Handle 'xsi:nil'.
24636 */
24637 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24638 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
24639 if (iattr) {
24640 ACTIVATE_ATTRIBUTE(iattr);
24641 /*
24642 * Validate the value.
24643 */
24644 ret = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024645 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024646 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
24647 iattr->value, &(iattr->val), 1, 0, 0);
24648 ACTIVATE_ELEM;
24649 if (ret < 0) {
24650 VERROR_INT("xmlSchemaValidateElemDecl",
24651 "calling xmlSchemaVCheckCVCSimpleType() to "
24652 "validate the attribute 'xsi:nil'");
24653 return (-1);
24654 }
24655 if (ret == 0) {
24656 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
24657 /*
24658 * cvc-elt (3.3.4) : 3.1
24659 */
24660 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
24661 "The element is not 'nillable'");
24662 /* Does not return an error on purpose. */
24663 } else {
24664 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
24665 /*
24666 * cvc-elt (3.3.4) : 3.2.2
24667 */
24668 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
24669 (elemDecl->value != NULL)) {
24670 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
24671 "The element cannot be 'nilled' because "
24672 "there is a fixed value constraint defined "
24673 "for it");
24674 /* Does not return an error on purpose. */
24675 } else
24676 vctxt->inode->flags |=
24677 XML_SCHEMA_ELEM_INFO_NILLED;
24678 }
24679 }
24680 }
24681 }
24682 /*
24683 * cvc-elt (3.3.4) : 4
24684 * Handle 'xsi:type'.
24685 */
24686 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24687 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
24688 if (iattr) {
24689 xmlSchemaTypePtr localType = NULL;
24690
24691 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
24692 elemDecl);
24693 if (ret != 0) {
24694 if (ret == -1) {
24695 VERROR_INT("xmlSchemaValidateElemDecl",
24696 "calling xmlSchemaProcessXSIType() to "
24697 "process the attribute 'xsi:type'");
24698 return (-1);
24699 }
24700 /* Does not return an error on purpose. */
24701 }
24702 if (localType != NULL) {
24703 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
24704 actualType = localType;
24705 }
24706 }
24707 }
24708 /*
24709 * IDC: Register identity-constraint XPath matchers.
24710 */
24711 if ((elemDecl->idcs != NULL) &&
24712 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
24713 return (-1);
24714 /*
24715 * No actual type definition.
24716 */
24717 if (actualType == NULL) {
24718 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24719 "The type definition is absent");
24720 return (XML_SCHEMAV_CVC_TYPE_1);
24721 }
24722 /*
24723 * Remember the actual type definition.
24724 */
24725 vctxt->inode->typeDef = actualType;
24726
24727 return (0);
24728}
24729
24730static int
24731xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
24732{
24733 xmlSchemaAttrInfoPtr iattr;
24734 int ret = 0, i;
24735
24736 /*
24737 * SPEC cvc-type (3.1.1)
24738 * "The attributes of must be empty, excepting those whose namespace
24739 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
24740 * whose local name is one of type, nil, schemaLocation or
24741 * noNamespaceSchemaLocation."
24742 */
24743 if (vctxt->nbAttrInfos == 0)
24744 return (0);
24745 for (i = 0; i < vctxt->nbAttrInfos; i++) {
24746 iattr = vctxt->attrInfos[i];
24747 if (! iattr->metaType) {
24748 ACTIVATE_ATTRIBUTE(iattr)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024749 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024750 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
24751 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
24752 }
24753 }
24754 ACTIVATE_ELEM
24755 return (ret);
24756}
24757
24758/*
24759* Cleanup currently used attribute infos.
24760*/
24761static void
24762xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
24763{
24764 int i;
24765 xmlSchemaAttrInfoPtr attr;
24766
24767 if (vctxt->nbAttrInfos == 0)
24768 return;
24769 for (i = 0; i < vctxt->nbAttrInfos; i++) {
24770 attr = vctxt->attrInfos[i];
24771 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24772 if (attr->localName != NULL)
24773 xmlFree((xmlChar *) attr->localName);
24774 if (attr->nsName != NULL)
24775 xmlFree((xmlChar *) attr->nsName);
24776 }
24777 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24778 if (attr->value != NULL)
24779 xmlFree((xmlChar *) attr->value);
24780 }
24781 if (attr->val != NULL) {
24782 xmlSchemaFreeValue(attr->val);
24783 attr->val = NULL;
24784 }
24785 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
24786 }
24787 vctxt->nbAttrInfos = 0;
24788}
24789
24790/*
24791* 3.4.4 Complex Type Definition Validation Rules
24792* Element Locally Valid (Complex Type) (cvc-complex-type)
24793* 3.2.4 Attribute Declaration Validation Rules
24794* Validation Rule: Attribute Locally Valid (cvc-attribute)
24795* Attribute Locally Valid (Use) (cvc-au)
24796*
24797* Only "assessed" attribute information items will be visible to
24798* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
24799*/
24800static int
24801xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
24802{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024803 xmlSchemaTypePtr type = vctxt->inode->typeDef;
24804 xmlSchemaItemListPtr attrUseList;
24805 xmlSchemaAttributeUsePtr attrUse = NULL;
24806 xmlSchemaAttributePtr attrDecl = NULL;
24807 xmlSchemaAttrInfoPtr iattr, tmpiattr;
24808 int i, j, found, nbAttrs, nbUses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024809 int xpathRes = 0, res, wildIDs = 0, fixed;
24810
24811 /*
24812 * SPEC (cvc-attribute)
24813 * (1) "The declaration must not be ·absent· (see Missing
24814 * Sub-components (§5.3) for how this can fail to be
24815 * the case)."
24816 * (2) "Its {type definition} must not be absent."
24817 *
24818 * NOTE (1) + (2): This is not handled here, since we currently do not
24819 * allow validation against schemas which have missing sub-components.
24820 *
24821 * SPEC (cvc-complex-type)
24822 * (3) "For each attribute information item in the element information
24823 * item's [attributes] excepting those whose [namespace name] is
24824 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
24825 * [local name] is one of type, nil, schemaLocation or
24826 * noNamespaceSchemaLocation, the appropriate case among the following
24827 * must be true:
24828 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024829 */
24830 attrUseList = (xmlSchemaItemListPtr) type->attrUses;
24831 /*
24832 * @nbAttrs is the number of attributes present in the instance.
24833 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024834 nbAttrs = vctxt->nbAttrInfos;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024835 if (attrUseList != NULL)
24836 nbUses = attrUseList->nbItems;
24837 else
24838 nbUses = 0;
24839 for (i = 0; i < nbUses; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024840 found = 0;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024841 attrUse = attrUseList->items[i];
24842 attrDecl = WXS_ATTRUSE_DECL(attrUse);
24843 for (j = 0; j < nbAttrs; j++) {
24844 iattr = vctxt->attrInfos[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024845 /*
24846 * SPEC (cvc-complex-type) (3)
24847 * Skip meta attributes.
24848 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024849 if (iattr->metaType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024850 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024851 if (iattr->localName[0] != attrDecl->name[0])
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024852 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024853 if (!xmlStrEqual(iattr->localName, attrDecl->name))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024854 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024855 if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024856 continue;
24857 found = 1;
24858 /*
24859 * SPEC (cvc-complex-type)
24860 * (3.1) "If there is among the {attribute uses} an attribute
24861 * use with an {attribute declaration} whose {name} matches
24862 * the attribute information item's [local name] and whose
24863 * {target namespace} is identical to the attribute information
24864 * item's [namespace name] (where an ·absent· {target namespace}
24865 * is taken to be identical to a [namespace name] with no value),
24866 * then the attribute information must be ·valid· with respect
24867 * to that attribute use as per Attribute Locally Valid (Use)
24868 * (§3.5.4). In this case the {attribute declaration} of that
24869 * attribute use is the ·context-determined declaration· for the
24870 * attribute information item with respect to Schema-Validity
24871 * Assessment (Attribute) (§3.2.4) and
24872 * Assessment Outcome (Attribute) (§3.2.5).
24873 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024874 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
24875 iattr->use = attrUse;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024876 /*
24877 * Context-determined declaration.
24878 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024879 iattr->decl = attrDecl;
24880 iattr->typeDef = attrDecl->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024881 break;
24882 }
24883
24884 if (found)
24885 continue;
24886
24887 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
24888 /*
24889 * Handle non-existent, required attributes.
24890 *
24891 * SPEC (cvc-complex-type)
24892 * (4) "The {attribute declaration} of each attribute use in
24893 * the {attribute uses} whose {required} is true matches one
24894 * of the attribute information items in the element information
24895 * item's [attributes] as per clause 3.1 above."
24896 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024897 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
24898 if (tmpiattr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024899 VERROR_INT(
24900 "xmlSchemaVAttributesComplex",
24901 "calling xmlSchemaGetFreshAttrInfo()");
24902 return (-1);
24903 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024904 tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
24905 tmpiattr->use = attrUse;
24906 tmpiattr->decl = attrDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024907 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
24908 ((attrUse->defValue != NULL) ||
24909 (attrDecl->defValue != NULL))) {
24910 /*
24911 * Handle non-existent, optional, default/fixed attributes.
24912 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024913 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
24914 if (tmpiattr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024915 VERROR_INT(
24916 "xmlSchemaVAttributesComplex",
24917 "calling xmlSchemaGetFreshAttrInfo()");
24918 return (-1);
24919 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024920 tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
24921 tmpiattr->use = attrUse;
24922 tmpiattr->decl = attrDecl;
24923 tmpiattr->typeDef = attrDecl->subtypes;
24924 tmpiattr->localName = attrDecl->name;
24925 tmpiattr->nsName = attrDecl->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024926 }
24927 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024928
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024929 if (vctxt->nbAttrInfos == 0)
24930 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024931 nbUses = vctxt->nbAttrInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024932 /*
24933 * Validate against the wildcard.
24934 */
24935 if (type->attributeWildcard != NULL) {
24936 /*
24937 * SPEC (cvc-complex-type)
24938 * (3.2.1) "There must be an {attribute wildcard}."
24939 */
24940 for (i = 0; i < nbAttrs; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024941 iattr = vctxt->attrInfos[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024942 /*
24943 * SPEC (cvc-complex-type) (3)
24944 * Skip meta attributes.
24945 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024946 if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024947 continue;
24948 /*
24949 * SPEC (cvc-complex-type)
24950 * (3.2.2) "The attribute information item must be ·valid· with
24951 * respect to it as defined in Item Valid (Wildcard) (§3.10.4)."
24952 *
24953 * SPEC Item Valid (Wildcard) (cvc-wildcard)
24954 * "... its [namespace name] must be ·valid· with respect to
24955 * the wildcard constraint, as defined in Wildcard allows
24956 * Namespace Name (§3.10.4)."
24957 */
24958 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024959 iattr->nsName) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024960 /*
24961 * Handle processContents.
24962 *
24963 * SPEC (cvc-wildcard):
24964 * processContents | context-determined declaration:
24965 * "strict" "mustFind"
24966 * "lax" "none"
24967 * "skip" "skip"
24968 */
24969 if (type->attributeWildcard->processContents ==
24970 XML_SCHEMAS_ANY_SKIP) {
24971 /*
24972 * context-determined declaration = "skip"
24973 *
24974 * SPEC PSVI Assessment Outcome (Attribute)
24975 * [validity] = "notKnown"
24976 * [validation attempted] = "none"
24977 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024978 iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024979 continue;
24980 }
24981 /*
24982 * Find an attribute declaration.
24983 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024984 iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
24985 iattr->localName, iattr->nsName);
24986 if (iattr->decl != NULL) {
24987 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024988 /*
24989 * SPEC (cvc-complex-type)
24990 * (5) "Let [Definition:] the wild IDs be the set of
24991 * all attribute information item to which clause 3.2
24992 * applied and whose ·validation· resulted in a
24993 * ·context-determined declaration· of mustFind or no
24994 * ·context-determined declaration· at all, and whose
24995 * [local name] and [namespace name] resolve (as
24996 * defined by QName resolution (Instance) (§3.15.4)) to
24997 * an attribute declaration whose {type definition} is
24998 * or is derived from ID. Then all of the following
24999 * must be true:"
25000 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025001 iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025002 if (xmlSchemaIsDerivedFromBuiltInType(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025003 iattr->typeDef, XML_SCHEMAS_ID)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025004 /*
25005 * SPEC (5.1) "There must be no more than one
25006 * item in ·wild IDs·."
25007 */
25008 if (wildIDs != 0) {
25009 /* VAL TODO */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025010 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025011 TODO
25012 continue;
25013 }
25014 wildIDs++;
25015 /*
25016 * SPEC (cvc-complex-type)
25017 * (5.2) "If ·wild IDs· is non-empty, there must not
25018 * be any attribute uses among the {attribute uses}
25019 * whose {attribute declaration}'s {type definition}
25020 * is or is derived from ID."
25021 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025022 for (j = 0; j < attrUseList->nbItems; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025023 if (xmlSchemaIsDerivedFromBuiltInType(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025024 WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025025 XML_SCHEMAS_ID)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025026 /* URGENT VAL TODO: implement */
25027 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025028 TODO
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025029 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025030 }
25031 }
25032 }
25033 } else if (type->attributeWildcard->processContents ==
25034 XML_SCHEMAS_ANY_LAX) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025035 iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025036 /*
25037 * SPEC PSVI Assessment Outcome (Attribute)
25038 * [validity] = "notKnown"
25039 * [validation attempted] = "none"
25040 */
25041 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025042 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025043 }
25044 }
25045 }
25046 }
25047
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025048 if (vctxt->nbAttrInfos == 0)
25049 return (0);
25050
25051 /*
25052 * Validate values, create default attributes, evaluate IDCs.
25053 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025054 for (i = 0; i < vctxt->nbAttrInfos; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025055 iattr = vctxt->attrInfos[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025056 /*
25057 * VAL TODO: Note that we won't try to resolve IDCs to
25058 * "lax" and "skip" validated attributes. Check what to
25059 * do in this case.
25060 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025061 if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25062 (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025063 continue;
25064 /*
25065 * VAL TODO: What to do if the type definition is missing?
25066 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025067 if (iattr->typeDef == NULL) {
25068 iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025069 continue;
25070 }
25071
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025072 ACTIVATE_ATTRIBUTE(iattr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000025073 fixed = 0;
25074 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025075
25076 if (vctxt->xpathStates != NULL) {
25077 /*
25078 * Evaluate IDCs.
25079 */
25080 xpathRes = xmlSchemaXPathEvaluate(vctxt,
25081 XML_ATTRIBUTE_NODE);
25082 if (xpathRes == -1) {
25083 VERROR_INT("xmlSchemaVAttributesComplex",
25084 "calling xmlSchemaXPathEvaluate()");
25085 goto internal_error;
25086 }
25087 }
25088
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025089 if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025090 /*
25091 * Default/fixed attributes.
25092 */
25093 if (xpathRes) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025094 if (iattr->use->defValue != NULL) {
25095 iattr->value = (xmlChar *) iattr->use->defValue;
25096 iattr->val = iattr->use->defVal;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025097 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025098 iattr->value = (xmlChar *) iattr->decl->defValue;
25099 iattr->val = iattr->decl->defVal;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025100 }
25101 /*
25102 * IDCs will consume the precomputed default value,
25103 * so we need to clone it.
25104 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025105 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025106 VERROR_INT("xmlSchemaVAttributesComplex",
25107 "default/fixed value on an attribute use was "
25108 "not precomputed");
25109 goto internal_error;
25110 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025111 iattr->val = xmlSchemaCopyValue(iattr->val);
25112 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025113 VERROR_INT("xmlSchemaVAttributesComplex",
25114 "calling xmlSchemaCopyValue()");
25115 goto internal_error;
25116 }
25117 }
25118 /*
25119 * PSVI: Add the default attribute to the current element.
25120 * VAL TODO: Should we use the *normalized* value? This currently
25121 * uses the *initial* value.
25122 */
25123 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025124 (iattr->node != NULL) && (iattr->node->doc != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025125 xmlChar *normValue;
25126 const xmlChar *value;
25127
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025128 value = iattr->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025129 /*
25130 * Normalize the value.
25131 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025132 normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25133 iattr->value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025134 if (normValue != NULL)
25135 value = BAD_CAST normValue;
25136
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025137 if (iattr->nsName == NULL) {
25138 if (xmlNewProp(iattr->node->parent,
25139 iattr->localName, value) == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025140 VERROR_INT("xmlSchemaVAttributesComplex",
25141 "callling xmlNewProp()");
25142 if (normValue != NULL)
25143 xmlFree(normValue);
25144 goto internal_error;
25145 }
25146 } else {
25147 xmlNsPtr ns;
25148
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025149 ns = xmlSearchNsByHref(iattr->node->doc,
25150 iattr->node->parent, iattr->nsName);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025151 if (ns == NULL) {
25152 xmlChar prefix[12];
25153 int counter = 0;
25154
25155 /*
25156 * Create a namespace declaration on the validation
25157 * root node if no namespace declaration is in scope.
25158 */
25159 do {
25160 snprintf((char *) prefix, 12, "p%d", counter++);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025161 ns = xmlSearchNs(iattr->node->doc,
25162 iattr->node->parent, BAD_CAST prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025163 if (counter > 1000) {
25164 VERROR_INT(
25165 "xmlSchemaVAttributesComplex",
25166 "could not compute a ns prefix for a "
25167 "default/fixed attribute");
25168 if (normValue != NULL)
25169 xmlFree(normValue);
25170 goto internal_error;
25171 }
25172 } while (ns != NULL);
25173 ns = xmlNewNs(vctxt->validationRoot,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025174 iattr->nsName, BAD_CAST prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025175 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025176 /*
25177 * TODO:
25178 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25179 * If we have QNames: do we need to ensure there's a
25180 * prefix defined for the QName?
25181 */
25182 xmlNewNsProp(iattr->node->parent, ns,
25183 iattr->localName, value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025184 }
25185 if (normValue != NULL)
25186 xmlFree(normValue);
25187 }
25188 /*
25189 * Go directly to IDC evaluation.
25190 */
25191 goto eval_idcs;
25192 }
25193 /*
25194 * Validate the value.
25195 */
25196 if (vctxt->value != NULL) {
25197 /*
25198 * Free last computed value; just for safety reasons.
25199 */
25200 xmlSchemaFreeValue(vctxt->value);
25201 vctxt->value = NULL;
25202 }
25203 /*
25204 * Note that the attribute *use* can be unavailable, if
25205 * the attribute was a wild attribute.
25206 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025207 if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25208 ((iattr->use != NULL) &&
25209 (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025210 fixed = 1;
25211 else
25212 fixed = 0;
25213 /*
25214 * SPEC (cvc-attribute)
25215 * (3) "The item's ·normalized value· must be locally ·valid·
25216 * with respect to that {type definition} as per
25217 * String Valid (§3.14.4)."
25218 *
25219 * VAL TODO: Do we already have the
25220 * "normalized attribute value" here?
25221 */
25222 if (xpathRes || fixed) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025223 iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025224 /*
25225 * Request a computed value.
25226 */
25227 res = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025228 ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025229 iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025230 1, 1, 0);
25231 } else {
25232 res = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025233 ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025234 iattr->node, iattr->typeDef, iattr->value, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025235 1, 0, 0);
25236 }
25237
25238 if (res != 0) {
25239 if (res == -1) {
25240 VERROR_INT("xmlSchemaVAttributesComplex",
25241 "calling xmlSchemaStreamValidateSimpleTypeValue()");
25242 goto internal_error;
25243 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025244 iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025245 /*
25246 * SPEC PSVI Assessment Outcome (Attribute)
25247 * [validity] = "invalid"
25248 */
25249 goto eval_idcs;
25250 }
25251
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025252 if (fixed) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025253 /*
25254 * SPEC Attribute Locally Valid (Use) (cvc-au)
25255 * "For an attribute information item to be·valid·
25256 * with respect to an attribute use its *normalized*
25257 * value· must match the *canonical* lexical
25258 * representation of the attribute use's {value
25259 * constraint}value, if it is present and fixed."
25260 *
25261 * VAL TODO: The requirement for the *canonical* value
25262 * will be removed in XML Schema 1.1.
25263 */
25264 /*
25265 * SPEC Attribute Locally Valid (cvc-attribute)
25266 * (4) "The item's *actual* value· must match the *value* of
25267 * the {value constraint}, if it is present and fixed."
25268 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025269 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025270 /* VAL TODO: A value was not precomputed. */
25271 TODO
25272 goto eval_idcs;
25273 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025274 if ((iattr->use != NULL) &&
25275 (iattr->use->defValue != NULL)) {
25276 if (iattr->use->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025277 /* VAL TODO: A default value was not precomputed. */
25278 TODO
25279 goto eval_idcs;
25280 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025281 iattr->vcValue = iattr->use->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025282 /*
25283 if (xmlSchemaCompareValuesWhtsp(attr->val,
25284 (xmlSchemaWhitespaceValueType) ws,
25285 attr->use->defVal,
25286 (xmlSchemaWhitespaceValueType) ws) != 0) {
25287 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025288 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25289 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025290 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025291 if (iattr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025292 /* VAL TODO: A default value was not precomputed. */
25293 TODO
25294 goto eval_idcs;
25295 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025296 iattr->vcValue = iattr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025297 /*
25298 if (xmlSchemaCompareValuesWhtsp(attr->val,
25299 (xmlSchemaWhitespaceValueType) ws,
25300 attrDecl->defVal,
25301 (xmlSchemaWhitespaceValueType) ws) != 0) {
25302 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025303 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25304 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025305 }
25306 /*
25307 * [validity] = "valid"
25308 */
25309 }
25310eval_idcs:
25311 /*
25312 * Evaluate IDCs.
25313 */
25314 if (xpathRes) {
25315 if (xmlSchemaXPathProcessHistory(vctxt,
25316 vctxt->depth +1) == -1) {
25317 VERROR_INT("xmlSchemaVAttributesComplex",
25318 "calling xmlSchemaXPathEvaluate()");
25319 goto internal_error;
25320 }
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000025321 } else if (vctxt->xpathStates != NULL)
25322 xmlSchemaXPathPop(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025323 }
25324
25325 /*
25326 * Report errors.
25327 */
25328 for (i = 0; i < vctxt->nbAttrInfos; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025329 iattr = vctxt->attrInfos[i];
25330 if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25331 (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25332 (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25333 (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025334 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025335 ACTIVATE_ATTRIBUTE(iattr);
25336 switch (iattr->state) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025337 case XML_SCHEMAS_ATTR_ERR_MISSING: {
25338 xmlChar *str = NULL;
25339 ACTIVATE_ELEM;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025340 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025341 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25342 "The attribute '%s' is required but missing",
25343 xmlSchemaFormatQName(&str,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025344 iattr->decl->targetNamespace,
25345 iattr->decl->name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025346 NULL);
25347 FREE_AND_NULL(str)
25348 break;
25349 }
25350 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25351 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25352 "The type definition is absent");
25353 break;
25354 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025355 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025356 XML_SCHEMAV_CVC_AU, NULL, NULL,
25357 "The value '%s' does not match the fixed "
25358 "value constraint '%s'",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025359 iattr->value, iattr->vcValue);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025360 break;
25361 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25362 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25363 "No matching global attribute declaration available, but "
25364 "demanded by the strict wildcard");
25365 break;
25366 case XML_SCHEMAS_ATTR_UNKNOWN:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025367 if (iattr->metaType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025368 break;
25369 /*
25370 * MAYBE VAL TODO: One might report different error messages
25371 * for the following errors.
25372 */
25373 if (type->attributeWildcard == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025374 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025375 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025376 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025377 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025378 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025379 }
25380 break;
25381 default:
25382 break;
25383 }
25384 }
25385
25386 ACTIVATE_ELEM;
25387 return (0);
25388internal_error:
25389 ACTIVATE_ELEM;
25390 return (-1);
25391}
25392
25393static int
25394xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25395 int *skip)
25396{
25397 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25398 /*
25399 * The namespace of the element was already identified to be
25400 * matching the wildcard.
25401 */
25402 if ((skip == NULL) || (wild == NULL) ||
25403 (wild->type != XML_SCHEMA_TYPE_ANY)) {
25404 VERROR_INT("xmlSchemaValidateElemWildcard",
25405 "bad arguments");
25406 return (-1);
25407 }
25408 *skip = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025409 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25410 /*
25411 * URGENT VAL TODO: Either we need to position the stream to the
25412 * next sibling, or walk the whole subtree.
25413 */
25414 *skip = 1;
25415 return (0);
25416 }
25417 {
25418 xmlSchemaElementPtr decl = NULL;
25419
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025420 decl = xmlSchemaGetElem(vctxt->schema,
25421 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025422 if (decl != NULL) {
25423 vctxt->inode->decl = decl;
25424 return (0);
25425 }
25426 }
25427 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25428 /* VAL TODO: Change to proper error code. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025429 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025430 "No matching global element declaration available, but "
25431 "demanded by the strict wildcard");
25432 return (vctxt->err);
25433 }
25434 if (vctxt->nbAttrInfos != 0) {
25435 xmlSchemaAttrInfoPtr iattr;
25436 /*
25437 * SPEC Validation Rule: Schema-Validity Assessment (Element)
25438 * (1.2.1.2.1) - (1.2.1.2.3 )
25439 *
25440 * Use the xsi:type attribute for the type definition.
25441 */
25442 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25443 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25444 if (iattr != NULL) {
25445 if (xmlSchemaProcessXSIType(vctxt, iattr,
25446 &(vctxt->inode->typeDef), NULL) == -1) {
25447 VERROR_INT("xmlSchemaValidateElemWildcard",
25448 "calling xmlSchemaProcessXSIType() to "
25449 "process the attribute 'xsi:nil'");
25450 return (-1);
25451 }
25452 /*
25453 * Don't return an error on purpose.
25454 */
25455 return (0);
25456 }
25457 }
25458 /*
25459 * SPEC Validation Rule: Schema-Validity Assessment (Element)
25460 *
25461 * Fallback to "anyType".
25462 */
25463 vctxt->inode->typeDef =
25464 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25465 return (0);
25466}
25467
25468/*
25469* xmlSchemaCheckCOSValidDefault:
25470*
25471* This will be called if: not nilled, no content and a default/fixed
25472* value is provided.
25473*/
25474
25475static int
25476xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25477 const xmlChar *value,
25478 xmlSchemaValPtr *val)
25479{
25480 int ret = 0;
25481 xmlSchemaNodeInfoPtr inode = vctxt->inode;
25482
25483 /*
25484 * cos-valid-default:
25485 * Schema Component Constraint: Element Default Valid (Immediate)
25486 * For a string to be a valid default with respect to a type
25487 * definition the appropriate case among the following must be true:
25488 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025489 if WXS_IS_COMPLEX(inode->typeDef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025490 /*
25491 * Complex type.
25492 *
25493 * SPEC (2.1) "its {content type} must be a simple type definition
25494 * or mixed."
25495 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
25496 * type}'s particle must be ·emptiable· as defined by
25497 * Particle Emptiable (§3.9.6)."
25498 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025499 if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25500 ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25501 (! WXS_EMPTIABLE(inode->typeDef)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025502 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25503 /* NOTE that this covers (2.2.2) as well. */
25504 VERROR(ret, NULL,
25505 "For a string to be a valid default, the type definition "
25506 "must be a simple type or a complex type with simple content "
25507 "or mixed content and a particle emptiable");
25508 return(ret);
25509 }
25510 }
25511 /*
25512 * 1 If the type definition is a simple type definition, then the string
25513 * must be ·valid· with respect to that definition as defined by String
25514 * Valid (§3.14.4).
25515 *
25516 * AND
25517 *
25518 * 2.2.1 If the {content type} is a simple type definition, then the
25519 * string must be ·valid· with respect to that simple type definition
25520 * as defined by String Valid (§3.14.4).
25521 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025522 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025523
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025524 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025525 NULL, inode->typeDef, value, val, 1, 1, 0);
25526
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025527 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025528
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025529 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025530 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25531 }
25532 if (ret < 0) {
25533 VERROR_INT("xmlSchemaCheckCOSValidDefault",
25534 "calling xmlSchemaVCheckCVCSimpleType()");
25535 }
25536 return (ret);
25537}
25538
25539static void
25540xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25541 const xmlChar * name ATTRIBUTE_UNUSED,
25542 xmlSchemaElementPtr item,
25543 xmlSchemaNodeInfoPtr inode)
25544{
25545 inode->decl = item;
25546#ifdef DEBUG_CONTENT
25547 {
25548 xmlChar *str = NULL;
25549
25550 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25551 xmlGenericError(xmlGenericErrorContext,
25552 "AUTOMATON callback for '%s' [declaration]\n",
25553 xmlSchemaFormatQName(&str,
25554 inode->localName, inode->nsName));
25555 } else {
25556 xmlGenericError(xmlGenericErrorContext,
25557 "AUTOMATON callback for '%s' [wildcard]\n",
25558 xmlSchemaFormatQName(&str,
25559 inode->localName, inode->nsName));
25560
25561 }
25562 FREE_AND_NULL(str)
25563 }
25564#endif
25565}
25566
25567static int
25568xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000025569{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025570 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25571 if (vctxt->inode == NULL) {
25572 VERROR_INT("xmlSchemaValidatorPushElem",
25573 "calling xmlSchemaGetFreshElemInfo()");
25574 return (-1);
25575 }
25576 vctxt->nbAttrInfos = 0;
25577 return (0);
25578}
25579
25580static int
25581xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25582 xmlSchemaNodeInfoPtr inode,
25583 xmlSchemaTypePtr type,
25584 const xmlChar *value)
25585{
25586 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25587 return (xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025588 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025589 type, value, &(inode->val), 1, 1, 0));
25590 else
25591 return (xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025592 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025593 type, value, NULL, 1, 0, 0));
25594}
25595
25596
25597
25598/*
25599* Process END of element.
25600*/
25601static int
25602xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
25603{
25604 int ret = 0;
25605 xmlSchemaNodeInfoPtr inode = vctxt->inode;
25606
25607 if (vctxt->nbAttrInfos != 0)
25608 xmlSchemaClearAttrInfos(vctxt);
25609 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
25610 /*
25611 * This element was not expected;
25612 * we will not validate child elements of broken parents.
25613 * Skip validation of all content of the parent.
25614 */
25615 vctxt->skipDepth = vctxt->depth -1;
25616 goto end_elem;
25617 }
25618 if ((inode->typeDef == NULL) ||
25619 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
25620 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000025621 * 1. the type definition might be missing if the element was
25622 * error prone
25623 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025624 */
25625 goto end_elem;
25626 }
25627 /*
25628 * Check the content model.
25629 */
25630 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
25631 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
25632
25633 /*
25634 * Workaround for "anyType".
25635 */
25636 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
25637 goto character_content;
25638
25639 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
25640 xmlChar *values[10];
25641 int terminal, nbval = 10, nbneg;
25642
25643 if (inode->regexCtxt == NULL) {
25644 /*
25645 * Create the regex context.
25646 */
25647 inode->regexCtxt =
25648 xmlRegNewExecCtxt(inode->typeDef->contModel,
25649 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
25650 vctxt);
25651 if (inode->regexCtxt == NULL) {
25652 VERROR_INT("xmlSchemaValidatorPopElem",
25653 "failed to create a regex context");
25654 goto internal_error;
25655 }
25656#ifdef DEBUG_AUTOMATA
25657 xmlGenericError(xmlGenericErrorContext,
25658 "AUTOMATON create on '%s'\n", inode->localName);
25659#endif
25660 }
25661 /*
25662 * Get hold of the still expected content, since a further
25663 * call to xmlRegExecPushString() will loose this information.
25664 */
25665 xmlRegExecNextValues(inode->regexCtxt,
25666 &nbval, &nbneg, &values[0], &terminal);
25667 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
25668 if (ret <= 0) {
25669 /*
25670 * Still missing something.
25671 */
25672 ret = 1;
25673 inode->flags |=
25674 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025675 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025676 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
25677 "Missing child element(s)",
25678 nbval, nbneg, values);
25679#ifdef DEBUG_AUTOMATA
25680 xmlGenericError(xmlGenericErrorContext,
25681 "AUTOMATON missing ERROR on '%s'\n",
25682 inode->localName);
25683#endif
25684 } else {
25685 /*
25686 * Content model is satisfied.
25687 */
25688 ret = 0;
25689#ifdef DEBUG_AUTOMATA
25690 xmlGenericError(xmlGenericErrorContext,
25691 "AUTOMATON succeeded on '%s'\n",
25692 inode->localName);
25693#endif
25694 }
25695
25696 }
25697 }
25698 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
25699 goto end_elem;
25700
25701character_content:
25702
25703 if (vctxt->value != NULL) {
25704 xmlSchemaFreeValue(vctxt->value);
25705 vctxt->value = NULL;
25706 }
25707 /*
25708 * Check character content.
25709 */
25710 if (inode->decl == NULL) {
25711 /*
25712 * Speedup if no declaration exists.
25713 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025714 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025715 ret = xmlSchemaVCheckINodeDataType(vctxt,
25716 inode, inode->typeDef, inode->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025717 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025718 ret = xmlSchemaVCheckINodeDataType(vctxt,
25719 inode, inode->typeDef->contentTypeDef,
25720 inode->value);
25721 }
25722 if (ret < 0) {
25723 VERROR_INT("xmlSchemaValidatorPopElem",
25724 "calling xmlSchemaVCheckCVCSimpleType()");
25725 goto internal_error;
25726 }
25727 goto end_elem;
25728 }
25729 /*
25730 * cvc-elt (3.3.4) : 5
25731 * The appropriate case among the following must be true:
25732 */
25733 /*
25734 * cvc-elt (3.3.4) : 5.1
25735 * If the declaration has a {value constraint},
25736 * the item has neither element nor character [children] and
25737 * clause 3.2 has not applied, then all of the following must be true:
25738 */
25739 if ((inode->decl->value != NULL) &&
25740 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
25741 (! INODE_NILLED(inode))) {
25742 /*
25743 * cvc-elt (3.3.4) : 5.1.1
25744 * If the ·actual type definition· is a ·local type definition·
25745 * then the canonical lexical representation of the {value constraint}
25746 * value must be a valid default for the ·actual type definition· as
25747 * defined in Element Default Valid (Immediate) (§3.3.6).
25748 */
25749 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025750 * NOTE: 'local' above means types acquired by xsi:type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025751 * NOTE: Although the *canonical* value is stated, it is not
25752 * relevant if canonical or not. Additionally XML Schema 1.1
25753 * will removed this requirement as well.
25754 */
25755 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
25756
25757 ret = xmlSchemaCheckCOSValidDefault(vctxt,
25758 inode->decl->value, &(inode->val));
25759 if (ret != 0) {
25760 if (ret < 0) {
25761 VERROR_INT("xmlSchemaValidatorPopElem",
25762 "calling xmlSchemaCheckCOSValidDefault()");
25763 goto internal_error;
25764 }
25765 goto end_elem;
25766 }
25767 /*
25768 * Stop here, to avoid redundant validation of the value
25769 * (see following).
25770 */
25771 goto default_psvi;
25772 }
25773 /*
25774 * cvc-elt (3.3.4) : 5.1.2
25775 * The element information item with the canonical lexical
25776 * representation of the {value constraint} value used as its
25777 * ·normalized value· must be ·valid· with respect to the
25778 * ·actual type definition· as defined by Element Locally Valid (Type)
25779 * (§3.3.4).
25780 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025781 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025782 ret = xmlSchemaVCheckINodeDataType(vctxt,
25783 inode, inode->typeDef, inode->decl->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025784 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025785 ret = xmlSchemaVCheckINodeDataType(vctxt,
25786 inode, inode->typeDef->contentTypeDef,
25787 inode->decl->value);
25788 }
25789 if (ret != 0) {
25790 if (ret < 0) {
25791 VERROR_INT("xmlSchemaValidatorPopElem",
25792 "calling xmlSchemaVCheckCVCSimpleType()");
25793 goto internal_error;
25794 }
25795 goto end_elem;
25796 }
25797
25798default_psvi:
25799 /*
25800 * PSVI: Create a text node on the instance element.
25801 */
25802 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
25803 (inode->node != NULL)) {
25804 xmlNodePtr textChild;
25805 xmlChar *normValue;
25806 /*
25807 * VAL TODO: Normalize the value.
25808 */
25809 normValue = xmlSchemaNormalizeValue(inode->typeDef,
25810 inode->decl->value);
25811 if (normValue != NULL) {
25812 textChild = xmlNewText(BAD_CAST normValue);
25813 xmlFree(normValue);
25814 } else
25815 textChild = xmlNewText(inode->decl->value);
25816 if (textChild == NULL) {
25817 VERROR_INT("xmlSchemaValidatorPopElem",
25818 "calling xmlNewText()");
25819 goto internal_error;
25820 } else
25821 xmlAddChild(inode->node, textChild);
25822 }
25823
25824 } else if (! INODE_NILLED(inode)) {
25825 /*
25826 * 5.2.1 The element information item must be ·valid· with respect
25827 * to the ·actual type definition· as defined by Element Locally
25828 * Valid (Type) (§3.3.4).
25829 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025830 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025831 /*
25832 * SPEC (cvc-type) (3.1)
25833 * "If the type definition is a simple type definition, ..."
25834 * (3.1.3) "If clause 3.2 of Element Locally Valid
25835 * (Element) (§3.3.4) did not apply, then the ·normalized value·
25836 * must be ·valid· with respect to the type definition as defined
25837 * by String Valid (§3.14.4).
25838 */
25839 ret = xmlSchemaVCheckINodeDataType(vctxt,
25840 inode, inode->typeDef, inode->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025841 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025842 /*
25843 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
25844 * definition, then the element information item must be
25845 * ·valid· with respect to the type definition as per
25846 * Element Locally Valid (Complex Type) (§3.4.4);"
25847 *
25848 * SPEC (cvc-complex-type) (2.2)
25849 * "If the {content type} is a simple type definition, ...
25850 * the ·normalized value· of the element information item is
25851 * ·valid· with respect to that simple type definition as
25852 * defined by String Valid (§3.14.4)."
25853 */
25854 ret = xmlSchemaVCheckINodeDataType(vctxt,
25855 inode, inode->typeDef->contentTypeDef, inode->value);
25856 }
25857 if (ret != 0) {
25858 if (ret < 0) {
25859 VERROR_INT("xmlSchemaValidatorPopElem",
25860 "calling xmlSchemaVCheckCVCSimpleType()");
25861 goto internal_error;
25862 }
25863 goto end_elem;
25864 }
25865 /*
25866 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
25867 * not applied, all of the following must be true:
25868 */
25869 if ((inode->decl->value != NULL) &&
25870 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
25871
25872 /*
25873 * TODO: We will need a computed value, when comparison is
25874 * done on computed values.
25875 */
25876 /*
25877 * 5.2.2.1 The element information item must have no element
25878 * information item [children].
25879 */
25880 if (inode->flags &
25881 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
25882 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
25883 VERROR(ret, NULL,
25884 "The content must not containt element nodes since "
25885 "there is a fixed value constraint");
25886 goto end_elem;
25887 } else {
25888 /*
25889 * 5.2.2.2 The appropriate case among the following must
25890 * be true:
25891 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025892 if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025893 /*
25894 * 5.2.2.2.1 If the {content type} of the ·actual type
25895 * definition· is mixed, then the *initial value* of the
25896 * item must match the canonical lexical representation
25897 * of the {value constraint} value.
25898 *
25899 * ... the *initial value* of an element information
25900 * item is the string composed of, in order, the
25901 * [character code] of each character information item in
25902 * the [children] of that element information item.
25903 */
25904 if (! xmlStrEqual(inode->value, inode->decl->value)){
25905 /*
25906 * VAL TODO: Report invalid & expected values as well.
25907 * VAL TODO: Implement the canonical stuff.
25908 */
25909 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025910 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025911 ret, NULL, NULL,
25912 "The initial value '%s' does not match the fixed "
25913 "value constraint '%s'",
25914 inode->value, inode->decl->value);
25915 goto end_elem;
25916 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025917 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025918 /*
25919 * 5.2.2.2.2 If the {content type} of the ·actual type
25920 * definition· is a simple type definition, then the
25921 * *actual value* of the item must match the canonical
25922 * lexical representation of the {value constraint} value.
25923 */
25924 /*
25925 * VAL TODO: *actual value* is the normalized value, impl.
25926 * this.
25927 * VAL TODO: Report invalid & expected values as well.
25928 * VAL TODO: Implement a comparison with the computed values.
25929 */
25930 if (! xmlStrEqual(inode->value,
25931 inode->decl->value)) {
25932 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025933 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025934 ret, NULL, NULL,
25935 "The actual value '%s' does not match the fixed "
25936 "value constraint '%s'",
25937 inode->value,
25938 inode->decl->value);
25939 goto end_elem;
25940 }
25941 }
25942 }
25943 }
25944 }
25945
25946end_elem:
25947 if (vctxt->depth < 0) {
25948 /* TODO: raise error? */
25949 return (0);
25950 }
25951 if (vctxt->depth == vctxt->skipDepth)
25952 vctxt->skipDepth = -1;
25953 /*
25954 * Evaluate the history of XPath state objects.
25955 */
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000025956 if (inode->appliedXPath &&
25957 (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025958 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025959 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025960 * MAYBE TODO:
25961 * SPEC (6) "The element information item must be ·valid· with
25962 * respect to each of the {identity-constraint definitions} as per
25963 * Identity-constraint Satisfied (§3.11.4)."
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025964 */
25965 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025966 * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
25967 * need to be built in any case.
25968 * We will currently build IDC node-tables and bubble them only if
25969 * keyrefs do exist.
25970 */
25971
25972 /*
25973 * Add the current IDC target-nodes to the IDC node-tables.
25974 */
25975 if ((inode->idcMatchers != NULL) &&
25976 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
25977 {
25978 if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
25979 goto internal_error;
25980 }
25981 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025982 * Validate IDC keyrefs.
25983 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025984 if (vctxt->inode->hasKeyrefs)
25985 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
25986 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025987 /*
25988 * Merge/free the IDC table.
25989 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025990 if (inode->idcTable != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025991#ifdef DEBUG_IDC_NODE_TABLE
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025992 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025993 inode->nsName,
25994 inode->localName,
25995 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025996#endif
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025997 if ((vctxt->depth > 0) &&
25998 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
25999 {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026000 /*
26001 * Merge the IDC node table with the table of the parent node.
26002 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026003 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26004 goto internal_error;
26005 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026006 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026007 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026008 * Clear the current ielem.
26009 * VAL TODO: Don't free the PSVI IDC tables if they are
26010 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026011 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026012 xmlSchemaClearElemInfo(inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026013 /*
26014 * Skip further processing if we are on the validation root.
26015 */
26016 if (vctxt->depth == 0) {
26017 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026018 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000026019 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026020 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026021 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026022 * Reset the keyrefDepth if needed.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026023 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026024 if (vctxt->aidcs != NULL) {
26025 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26026 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026027 if (aidc->keyrefDepth == vctxt->depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026028 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026029 * A 'keyrefDepth' of a key/unique IDC matches the current
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026030 * depth, this means that we are leaving the scope of the
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026031 * top-most keyref IDC which refers to this IDC.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026032 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026033 aidc->keyrefDepth = -1;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026034 }
26035 aidc = aidc->next;
26036 } while (aidc != NULL);
26037 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026038 vctxt->depth--;
26039 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000026040 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026041 * VAL TODO: 7 If the element information item is the ·validation root·, it must be
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026042 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
26043 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026044 return (ret);
26045
26046internal_error:
26047 vctxt->err = -1;
26048 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000026049}
26050
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026051/*
26052* 3.4.4 Complex Type Definition Validation Rules
26053* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26054*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000026055static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026056xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000026057{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026058 xmlSchemaNodeInfoPtr pielem;
26059 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000026060 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000026061
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026062 if (vctxt->depth <= 0) {
26063 VERROR_INT("xmlSchemaValidateChildElem",
26064 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026065 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026066 }
26067 pielem = vctxt->elemInfos[vctxt->depth -1];
26068 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26069 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026070 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026071 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026072 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026073 if (INODE_NILLED(pielem)) {
26074 /*
26075 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
26076 */
26077 ACTIVATE_PARENT_ELEM;
26078 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26079 VERROR(ret, NULL,
26080 "Neither character nor element content is allowed, "
26081 "because the element was 'nilled'");
26082 ACTIVATE_ELEM;
26083 goto unexpected_elem;
26084 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026085
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026086 ptype = pielem->typeDef;
26087
26088 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26089 /*
26090 * Workaround for "anyType": we have currently no content model
26091 * assigned for "anyType", so handle it explicitely.
26092 * "anyType" has an unbounded, lax "any" wildcard.
26093 */
26094 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26095 vctxt->inode->localName,
26096 vctxt->inode->nsName);
26097
26098 if (vctxt->inode->decl == NULL) {
26099 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026100 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026101 * Process "xsi:type".
26102 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026103 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026104 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26105 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26106 if (iattr != NULL) {
26107 ret = xmlSchemaProcessXSIType(vctxt, iattr,
26108 &(vctxt->inode->typeDef), NULL);
26109 if (ret != 0) {
26110 if (ret == -1) {
26111 VERROR_INT("xmlSchemaValidateChildElem",
26112 "calling xmlSchemaProcessXSIType() to "
26113 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000026114 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000026115 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026116 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000026117 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026118 } else {
26119 /*
26120 * Fallback to "anyType".
26121 *
26122 * SPEC (cvc-assess-elt)
26123 * "If the item cannot be ·strictly assessed·, [...]
26124 * an element information item's schema validity may be laxly
26125 * assessed if its ·context-determined declaration· is not
26126 * skip by ·validating· with respect to the ·ur-type
26127 * definition· as per Element Locally Valid (Type) (§3.3.4)."
26128 */
26129 vctxt->inode->typeDef =
26130 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026131 }
26132 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026133 return (0);
26134 }
26135
26136 switch (ptype->contentType) {
26137 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026138 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026139 * SPEC (2.1) "If the {content type} is empty, then the
26140 * element information item has no character or element
26141 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026142 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026143 ACTIVATE_PARENT_ELEM
26144 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26145 VERROR(ret, NULL,
26146 "Element content is not allowed, "
26147 "because the content type is empty");
26148 ACTIVATE_ELEM
26149 goto unexpected_elem;
26150 break;
26151
26152 case XML_SCHEMA_CONTENT_MIXED:
26153 case XML_SCHEMA_CONTENT_ELEMENTS: {
26154 xmlRegExecCtxtPtr regexCtxt;
26155 xmlChar *values[10];
26156 int terminal, nbval = 10, nbneg;
26157
26158 /* VAL TODO: Optimized "anyType" validation.*/
26159
26160 if (ptype->contModel == NULL) {
26161 VERROR_INT("xmlSchemaValidateChildElem",
26162 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026163 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000026164 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026165 /*
26166 * Safety belf for evaluation if the cont. model was already
26167 * examined to be invalid.
26168 */
26169 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26170 VERROR_INT("xmlSchemaValidateChildElem",
26171 "validating elem, but elem content is already invalid");
26172 return (-1);
26173 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000026174
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026175 regexCtxt = pielem->regexCtxt;
26176 if (regexCtxt == NULL) {
26177 /*
26178 * Create the regex context.
26179 */
26180 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26181 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26182 vctxt);
26183 if (regexCtxt == NULL) {
26184 VERROR_INT("xmlSchemaValidateChildElem",
26185 "failed to create a regex context");
26186 return (-1);
26187 }
26188 pielem->regexCtxt = regexCtxt;
26189#ifdef DEBUG_AUTOMATA
26190 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26191 pielem->localName);
26192#endif
26193 }
26194
26195 /*
26196 * SPEC (2.4) "If the {content type} is element-only or mixed,
26197 * then the sequence of the element information item's
26198 * element information item [children], if any, taken in
26199 * order, is ·valid· with respect to the {content type}'s
26200 * particle, as defined in Element Sequence Locally Valid
26201 * (Particle) (§3.9.4)."
26202 */
26203 ret = xmlRegExecPushString2(regexCtxt,
26204 vctxt->inode->localName,
26205 vctxt->inode->nsName,
26206 vctxt->inode);
26207#ifdef DEBUG_AUTOMATA
26208 if (ret < 0)
26209 xmlGenericError(xmlGenericErrorContext,
26210 "AUTOMATON push ERROR for '%s' on '%s'\n",
26211 vctxt->inode->localName, pielem->localName);
26212 else
26213 xmlGenericError(xmlGenericErrorContext,
26214 "AUTOMATON push OK for '%s' on '%s'\n",
26215 vctxt->inode->localName, pielem->localName);
26216#endif
26217 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26218 VERROR_INT("xmlSchemaValidateChildElem",
26219 "calling xmlRegExecPushString2()");
26220 return (-1);
26221 }
26222 if (ret < 0) {
26223 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26224 &values[0], &terminal);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026225 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026226 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26227 "This element is not expected",
26228 nbval, nbneg, values);
26229 ret = vctxt->err;
26230 goto unexpected_elem;
26231 } else
26232 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000026233 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026234 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026235 case XML_SCHEMA_CONTENT_SIMPLE:
26236 case XML_SCHEMA_CONTENT_BASIC:
26237 ACTIVATE_PARENT_ELEM
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026238 if (WXS_IS_COMPLEX(ptype)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026239 /*
26240 * SPEC (cvc-complex-type) (2.2)
26241 * "If the {content type} is a simple type definition, then
26242 * the element information item has no element information
26243 * item [children], ..."
26244 */
26245 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26246 VERROR(ret, NULL, "Element content is not allowed, "
26247 "because the content type is a simple type definition");
26248 } else {
26249 /*
26250 * SPEC (cvc-type) (3.1.2) "The element information item must
26251 * have no element information item [children]."
26252 */
26253 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26254 VERROR(ret, NULL, "Element content is not allowed, "
26255 "because the type definition is simple");
26256 }
26257 ACTIVATE_ELEM
26258 ret = vctxt->err;
26259 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026260 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026261
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026262 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026263 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026264 }
26265 return (ret);
26266unexpected_elem:
26267 /*
26268 * Pop this element and set the skipDepth to skip
26269 * all further content of the parent element.
26270 */
26271 vctxt->skipDepth = vctxt->depth;
26272 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26273 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26274 return (ret);
26275}
26276
26277#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26278#define XML_SCHEMA_PUSH_TEXT_CREATED 2
26279#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26280
26281static int
26282xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26283 int nodeType, const xmlChar *value, int len,
26284 int mode, int *consumed)
26285{
26286 /*
26287 * Unfortunately we have to duplicate the text sometimes.
26288 * OPTIMIZE: Maybe we could skip it, if:
26289 * 1. content type is simple
26290 * 2. whitespace is "collapse"
26291 * 3. it consists of whitespace only
26292 *
26293 * Process character content.
26294 */
26295 if (consumed != NULL)
26296 *consumed = 0;
26297 if (INODE_NILLED(vctxt->inode)) {
26298 /*
26299 * SPEC cvc-elt (3.3.4 - 3.2.1)
26300 * "The element information item must have no character or
26301 * element information item [children]."
26302 */
26303 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26304 "Neither character nor element content is allowed "
26305 "because the element is 'nilled'");
26306 return (vctxt->err);
26307 }
26308 /*
26309 * SPEC (2.1) "If the {content type} is empty, then the
26310 * element information item has no character or element
26311 * information item [children]."
26312 */
26313 if (vctxt->inode->typeDef->contentType ==
26314 XML_SCHEMA_CONTENT_EMPTY) {
26315 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26316 "Character content is not allowed, "
26317 "because the content type is empty");
26318 return (vctxt->err);
26319 }
26320
26321 if (vctxt->inode->typeDef->contentType ==
26322 XML_SCHEMA_CONTENT_ELEMENTS) {
26323 if ((nodeType != XML_TEXT_NODE) ||
26324 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26325 /*
26326 * SPEC cvc-complex-type (2.3)
26327 * "If the {content type} is element-only, then the
26328 * element information item has no character information
26329 * item [children] other than those whose [character
26330 * code] is defined as a white space in [XML 1.0 (Second
26331 * Edition)]."
26332 */
26333 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26334 "Character content other than whitespace is not allowed "
26335 "because the content type is 'element-only'");
26336 return (vctxt->err);
26337 }
26338 return (0);
26339 }
26340
26341 if ((value == NULL) || (value[0] == 0))
26342 return (0);
26343 /*
26344 * Save the value.
26345 * NOTE that even if the content type is *mixed*, we need the
26346 * *initial value* for default/fixed value constraints.
26347 */
26348 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26349 ((vctxt->inode->decl == NULL) ||
26350 (vctxt->inode->decl->value == NULL)))
26351 return (0);
26352
26353 if (vctxt->inode->value == NULL) {
26354 /*
26355 * Set the value.
26356 */
26357 switch (mode) {
26358 case XML_SCHEMA_PUSH_TEXT_PERSIST:
26359 /*
26360 * When working on a tree.
26361 */
26362 vctxt->inode->value = value;
26363 break;
26364 case XML_SCHEMA_PUSH_TEXT_CREATED:
26365 /*
26366 * When working with the reader.
26367 * The value will be freed by the element info.
26368 */
26369 vctxt->inode->value = value;
26370 if (consumed != NULL)
26371 *consumed = 1;
26372 vctxt->inode->flags |=
26373 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26374 break;
26375 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26376 /*
26377 * When working with SAX.
26378 * The value will be freed by the element info.
26379 */
26380 if (len != -1)
26381 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26382 else
26383 vctxt->inode->value = BAD_CAST xmlStrdup(value);
26384 vctxt->inode->flags |=
26385 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26386 break;
26387 default:
26388 break;
26389 }
Kasimier T. Buchcik5bb0c082005-12-20 10:48:33 +000026390 } else {
26391 if (len < 0)
26392 len = xmlStrlen(value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026393 /*
26394 * Concat the value.
26395 */
26396 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000026397 vctxt->inode->value = BAD_CAST xmlStrncat(
26398 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026399 } else {
26400 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026401 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026402 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26403 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026404 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026405
26406 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000026407}
26408
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026409static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026410xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000026411{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026412 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000026413
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026414 if ((vctxt->skipDepth != -1) &&
26415 (vctxt->depth >= vctxt->skipDepth)) {
26416 VERROR_INT("xmlSchemaValidateElem",
26417 "in skip-state");
26418 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026419 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026420 if (vctxt->xsiAssemble) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026421 /*
Kasimier T. Buchcik215406f2005-12-07 12:14:09 +000026422 * We will stop validation if there was an error during
26423 * dynamic schema construction.
26424 * Note that we simply set @skipDepth to 0, this could
26425 * mean that a streaming document via SAX would be
26426 * still read to the end but it won't be validated any more.
26427 * TODO: If we are sure how to stop the validation at once
26428 * for all input scenarios, then this should be changed to
26429 * instantly stop the validation.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026430 */
Kasimier T. Buchcik215406f2005-12-07 12:14:09 +000026431 ret = xmlSchemaAssembleByXSI(vctxt);
26432 if (ret != 0) {
26433 if (ret == -1)
26434 goto internal_error;
26435 vctxt->skipDepth = 0;
26436 return(ret);
26437 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026438 }
26439 if (vctxt->depth > 0) {
26440 /*
26441 * Validate this element against the content model
26442 * of the parent.
26443 */
26444 ret = xmlSchemaValidateChildElem(vctxt);
26445 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026446 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026447 VERROR_INT("xmlSchemaValidateElem",
26448 "calling xmlSchemaStreamValidateChildElement()");
26449 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026450 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026451 goto exit;
26452 }
26453 if (vctxt->depth == vctxt->skipDepth)
26454 goto exit;
26455 if ((vctxt->inode->decl == NULL) &&
26456 (vctxt->inode->typeDef == NULL)) {
26457 VERROR_INT("xmlSchemaValidateElem",
26458 "the child element was valid but neither the "
26459 "declaration nor the type was set");
26460 goto internal_error;
26461 }
26462 } else {
26463 /*
26464 * Get the declaration of the validation root.
26465 */
26466 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26467 vctxt->inode->localName,
26468 vctxt->inode->nsName);
26469 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026470 ret = XML_SCHEMAV_CVC_ELT_1;
26471 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026472 "No matching global declaration available "
26473 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026474 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026475 }
26476 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026477
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026478 if (vctxt->inode->decl == NULL)
26479 goto type_validation;
26480
26481 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26482 int skip;
26483 /*
26484 * Wildcards.
26485 */
26486 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26487 if (ret != 0) {
26488 if (ret < 0) {
26489 VERROR_INT("xmlSchemaValidateElem",
26490 "calling xmlSchemaValidateElemWildcard()");
26491 goto internal_error;
26492 }
26493 goto exit;
26494 }
26495 if (skip) {
26496 vctxt->skipDepth = vctxt->depth;
26497 goto exit;
26498 }
26499 /*
26500 * The declaration might be set by the wildcard validation,
26501 * when the processContents is "lax" or "strict".
26502 */
26503 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26504 /*
26505 * Clear the "decl" field to not confuse further processing.
26506 */
26507 vctxt->inode->decl = NULL;
26508 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026509 }
Daniel Veillard4255d502002-04-16 15:50:10 +000026510 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026511 /*
26512 * Validate against the declaration.
26513 */
26514 ret = xmlSchemaValidateElemDecl(vctxt);
26515 if (ret != 0) {
26516 if (ret < 0) {
26517 VERROR_INT("xmlSchemaValidateElem",
26518 "calling xmlSchemaValidateElemDecl()");
26519 goto internal_error;
26520 }
26521 goto exit;
26522 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026523 /*
26524 * Validate against the type definition.
26525 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026526type_validation:
26527
26528 if (vctxt->inode->typeDef == NULL) {
26529 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26530 ret = XML_SCHEMAV_CVC_TYPE_1;
26531 VERROR(ret, NULL,
26532 "The type definition is absent");
26533 goto exit;
26534 }
26535 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26536 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26537 ret = XML_SCHEMAV_CVC_TYPE_2;
26538 VERROR(ret, NULL,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026539 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026540 goto exit;
26541 }
26542 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026543 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026544 * during validation against the declaration. This must be done
26545 * _before_ attribute validation.
26546 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026547 if (vctxt->xpathStates != NULL) {
26548 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000026549 vctxt->inode->appliedXPath = 1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026550 if (ret == -1) {
26551 VERROR_INT("xmlSchemaValidateElem",
26552 "calling xmlSchemaXPathEvaluate()");
26553 goto internal_error;
26554 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026555 }
26556 /*
26557 * Validate attributes.
26558 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026559 if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026560 if ((vctxt->nbAttrInfos != 0) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026561 (vctxt->inode->typeDef->attrUses != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026562
26563 ret = xmlSchemaVAttributesComplex(vctxt);
26564 }
26565 } else if (vctxt->nbAttrInfos != 0) {
26566
26567 ret = xmlSchemaVAttributesSimple(vctxt);
26568 }
26569 /*
26570 * Clear registered attributes.
26571 */
26572 if (vctxt->nbAttrInfos != 0)
26573 xmlSchemaClearAttrInfos(vctxt);
26574 if (ret == -1) {
26575 VERROR_INT("xmlSchemaValidateElem",
26576 "calling attributes validation");
26577 goto internal_error;
26578 }
26579 /*
26580 * Don't return an error if attributes are invalid on purpose.
26581 */
26582 ret = 0;
26583
26584exit:
26585 if (ret != 0)
26586 vctxt->skipDepth = vctxt->depth;
26587 return (ret);
26588internal_error:
26589 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000026590}
26591
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026592#ifdef XML_SCHEMA_READER_ENABLED
26593static int
26594xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000026595{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026596 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
26597 int depth, nodeType, ret = 0, consumed;
26598 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000026599
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026600 vctxt->depth = -1;
26601 ret = xmlTextReaderRead(vctxt->reader);
26602 /*
26603 * Move to the document element.
26604 */
26605 while (ret == 1) {
26606 nodeType = xmlTextReaderNodeType(vctxt->reader);
26607 if (nodeType == XML_ELEMENT_NODE)
26608 goto root_found;
26609 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026610 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026611 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026612
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026613root_found:
26614
26615 do {
26616 depth = xmlTextReaderDepth(vctxt->reader);
26617 nodeType = xmlTextReaderNodeType(vctxt->reader);
26618
26619 if (nodeType == XML_ELEMENT_NODE) {
26620
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026621 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026622 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26623 VERROR_INT("xmlSchemaVReaderWalk",
26624 "calling xmlSchemaValidatorPushElem()");
26625 goto internal_error;
26626 }
26627 ielem = vctxt->inode;
26628 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
26629 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
26630 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
26631 /*
26632 * Is the element empty?
26633 */
26634 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
26635 if (ret == -1) {
26636 VERROR_INT("xmlSchemaVReaderWalk",
26637 "calling xmlTextReaderIsEmptyElement()");
26638 goto internal_error;
26639 }
26640 if (ret) {
26641 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26642 }
26643 /*
26644 * Register attributes.
26645 */
26646 vctxt->nbAttrInfos = 0;
26647 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
26648 if (ret == -1) {
26649 VERROR_INT("xmlSchemaVReaderWalk",
26650 "calling xmlTextReaderMoveToFirstAttribute()");
26651 goto internal_error;
26652 }
26653 if (ret == 1) {
26654 do {
26655 /*
26656 * VAL TODO: How do we know that the reader works on a
26657 * node tree, to be able to pass a node here?
26658 */
26659 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
26660 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
26661 xmlTextReaderNamespaceUri(vctxt->reader), 1,
26662 xmlTextReaderValue(vctxt->reader), 1) == -1) {
26663
26664 VERROR_INT("xmlSchemaVReaderWalk",
26665 "calling xmlSchemaValidatorPushAttribute()");
26666 goto internal_error;
26667 }
26668 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
26669 if (ret == -1) {
26670 VERROR_INT("xmlSchemaVReaderWalk",
26671 "calling xmlTextReaderMoveToFirstAttribute()");
26672 goto internal_error;
26673 }
26674 } while (ret == 1);
26675 /*
26676 * Back to element position.
26677 */
26678 ret = xmlTextReaderMoveToElement(vctxt->reader);
26679 if (ret == -1) {
26680 VERROR_INT("xmlSchemaVReaderWalk",
26681 "calling xmlTextReaderMoveToElement()");
26682 goto internal_error;
26683 }
26684 }
26685 /*
26686 * Validate the element.
26687 */
26688 ret= xmlSchemaValidateElem(vctxt);
26689 if (ret != 0) {
26690 if (ret == -1) {
26691 VERROR_INT("xmlSchemaVReaderWalk",
26692 "calling xmlSchemaValidateElem()");
26693 goto internal_error;
26694 }
26695 goto exit;
26696 }
26697 if (vctxt->depth == vctxt->skipDepth) {
26698 int curDepth;
26699 /*
26700 * Skip all content.
26701 */
26702 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
26703 ret = xmlTextReaderRead(vctxt->reader);
26704 curDepth = xmlTextReaderDepth(vctxt->reader);
26705 while ((ret == 1) && (curDepth != depth)) {
26706 ret = xmlTextReaderRead(vctxt->reader);
26707 curDepth = xmlTextReaderDepth(vctxt->reader);
26708 }
26709 if (ret < 0) {
26710 /*
26711 * VAL TODO: A reader error occured; what to do here?
26712 */
26713 ret = 1;
26714 goto exit;
26715 }
26716 }
26717 goto leave_elem;
26718 }
26719 /*
26720 * READER VAL TODO: Is an END_ELEM really never called
26721 * if the elem is empty?
26722 */
26723 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26724 goto leave_elem;
26725 } else if (nodeType == END_ELEM) {
26726 /*
26727 * Process END of element.
26728 */
26729leave_elem:
26730 ret = xmlSchemaValidatorPopElem(vctxt);
26731 if (ret != 0) {
26732 if (ret < 0) {
26733 VERROR_INT("xmlSchemaVReaderWalk",
26734 "calling xmlSchemaValidatorPopElem()");
26735 goto internal_error;
26736 }
26737 goto exit;
26738 }
26739 if (vctxt->depth >= 0)
26740 ielem = vctxt->inode;
26741 else
26742 ielem = NULL;
26743 } else if ((nodeType == XML_TEXT_NODE) ||
26744 (nodeType == XML_CDATA_SECTION_NODE) ||
26745 (nodeType == WHTSP) ||
26746 (nodeType == SIGN_WHTSP)) {
26747 /*
26748 * Process character content.
26749 */
26750 xmlChar *value;
26751
26752 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
26753 nodeType = XML_TEXT_NODE;
26754
26755 value = xmlTextReaderValue(vctxt->reader);
26756 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
26757 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
26758 if (! consumed)
26759 xmlFree(value);
26760 if (ret == -1) {
26761 VERROR_INT("xmlSchemaVReaderWalk",
26762 "calling xmlSchemaVPushText()");
26763 goto internal_error;
26764 }
26765 } else if ((nodeType == XML_ENTITY_NODE) ||
26766 (nodeType == XML_ENTITY_REF_NODE)) {
26767 /*
26768 * VAL TODO: What to do with entities?
26769 */
26770 TODO
26771 }
26772 /*
26773 * Read next node.
26774 */
26775 ret = xmlTextReaderRead(vctxt->reader);
26776 } while (ret == 1);
26777
26778exit:
26779 return (ret);
26780internal_error:
26781 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000026782}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026783#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000026784
26785/************************************************************************
26786 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026787 * SAX validation handlers *
Daniel Veillard4255d502002-04-16 15:50:10 +000026788 * *
26789 ************************************************************************/
26790
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026791/*
26792* Process text content.
26793*/
26794static void
26795xmlSchemaSAXHandleText(void *ctx,
26796 const xmlChar * ch,
26797 int len)
26798{
26799 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26800
26801 if (vctxt->depth < 0)
26802 return;
26803 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26804 return;
26805 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26806 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26807 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
26808 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
26809 VERROR_INT("xmlSchemaSAXHandleCDataSection",
26810 "calling xmlSchemaVPushText()");
26811 vctxt->err = -1;
26812 xmlStopParser(vctxt->parserCtxt);
26813 }
26814}
26815
26816/*
26817* Process CDATA content.
26818*/
26819static void
26820xmlSchemaSAXHandleCDataSection(void *ctx,
26821 const xmlChar * ch,
26822 int len)
26823{
26824 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26825
26826 if (vctxt->depth < 0)
26827 return;
26828 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26829 return;
26830 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26831 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26832 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
26833 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
26834 VERROR_INT("xmlSchemaSAXHandleCDataSection",
26835 "calling xmlSchemaVPushText()");
26836 vctxt->err = -1;
26837 xmlStopParser(vctxt->parserCtxt);
26838 }
26839}
26840
26841static void
26842xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
26843 const xmlChar * name ATTRIBUTE_UNUSED)
26844{
26845 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26846
26847 if (vctxt->depth < 0)
26848 return;
26849 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26850 return;
26851 /* SAX VAL TODO: What to do here? */
26852 TODO
26853}
26854
26855static void
26856xmlSchemaSAXHandleStartElementNs(void *ctx,
26857 const xmlChar * localname,
26858 const xmlChar * prefix ATTRIBUTE_UNUSED,
26859 const xmlChar * URI,
26860 int nb_namespaces,
26861 const xmlChar ** namespaces,
26862 int nb_attributes,
26863 int nb_defaulted ATTRIBUTE_UNUSED,
26864 const xmlChar ** attributes)
26865{
26866 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26867 int ret;
26868 xmlSchemaNodeInfoPtr ielem;
26869 int i, j;
26870
26871 /*
26872 * SAX VAL TODO: What to do with nb_defaulted?
26873 */
26874 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026875 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026876 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026877 vctxt->depth++;
26878 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026879 return;
26880 /*
26881 * Push the element.
26882 */
26883 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26884 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26885 "calling xmlSchemaValidatorPushElem()");
26886 goto internal_error;
26887 }
26888 ielem = vctxt->inode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026889 /*
26890 * TODO: Is this OK?
26891 */
26892 ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026893 ielem->localName = localname;
26894 ielem->nsName = URI;
26895 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26896 /*
26897 * Register namespaces on the elem info.
26898 */
26899 if (nb_namespaces != 0) {
26900 /*
26901 * Although the parser builds its own namespace list,
26902 * we have no access to it, so we'll use an own one.
26903 */
26904 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
26905 /*
26906 * Store prefix and namespace name.
26907 */
26908 if (ielem->nsBindings == NULL) {
26909 ielem->nsBindings =
26910 (const xmlChar **) xmlMalloc(10 *
26911 sizeof(const xmlChar *));
26912 if (ielem->nsBindings == NULL) {
26913 xmlSchemaVErrMemory(vctxt,
26914 "allocating namespace bindings for SAX validation",
26915 NULL);
26916 goto internal_error;
26917 }
26918 ielem->nbNsBindings = 0;
26919 ielem->sizeNsBindings = 5;
26920 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
26921 ielem->sizeNsBindings *= 2;
26922 ielem->nsBindings =
26923 (const xmlChar **) xmlRealloc(
26924 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026925 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026926 if (ielem->nsBindings == NULL) {
26927 xmlSchemaVErrMemory(vctxt,
26928 "re-allocating namespace bindings for SAX validation",
26929 NULL);
26930 goto internal_error;
26931 }
26932 }
26933
26934 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
26935 if (namespaces[j+1][0] == 0) {
26936 /*
26937 * Handle xmlns="".
26938 */
26939 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
26940 } else
26941 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
26942 namespaces[j+1];
26943 ielem->nbNsBindings++;
26944 }
26945 }
26946 /*
26947 * Register attributes.
26948 * SAX VAL TODO: We are not adding namespace declaration
26949 * attributes yet.
26950 */
26951 if (nb_attributes != 0) {
26952 xmlChar *value;
26953
26954 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
26955 /*
26956 * Duplicate the value.
26957 */
26958 value = xmlStrndup(attributes[j+3],
26959 attributes[j+4] - attributes[j+3]);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026960 /*
26961 * TODO: Set the node line.
26962 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026963 ret = xmlSchemaValidatorPushAttribute(vctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026964 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026965 value, 1);
26966 if (ret == -1) {
26967 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26968 "calling xmlSchemaValidatorPushAttribute()");
26969 goto internal_error;
26970 }
26971 }
26972 }
26973 /*
26974 * Validate the element.
26975 */
26976 ret = xmlSchemaValidateElem(vctxt);
26977 if (ret != 0) {
26978 if (ret == -1) {
26979 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26980 "calling xmlSchemaValidateElem()");
26981 goto internal_error;
26982 }
26983 goto exit;
26984 }
26985
26986exit:
26987 return;
26988internal_error:
26989 vctxt->err = -1;
26990 xmlStopParser(vctxt->parserCtxt);
26991 return;
26992}
26993
26994static void
26995xmlSchemaSAXHandleEndElementNs(void *ctx,
26996 const xmlChar * localname ATTRIBUTE_UNUSED,
26997 const xmlChar * prefix ATTRIBUTE_UNUSED,
26998 const xmlChar * URI ATTRIBUTE_UNUSED)
26999{
27000 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27001 int res;
27002
27003 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000027004 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027005 */
27006 if (vctxt->skipDepth != -1) {
27007 if (vctxt->depth > vctxt->skipDepth) {
27008 vctxt->depth--;
27009 return;
27010 } else
27011 vctxt->skipDepth = -1;
27012 }
27013 /*
27014 * SAX VAL TODO: Just a temporary check.
27015 */
27016 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27017 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
27018 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27019 "elem pop mismatch");
27020 }
27021 res = xmlSchemaValidatorPopElem(vctxt);
27022 if (res != 0) {
27023 if (res < 0) {
27024 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27025 "calling xmlSchemaValidatorPopElem()");
27026 goto internal_error;
27027 }
27028 goto exit;
27029 }
27030exit:
27031 return;
27032internal_error:
27033 vctxt->err = -1;
27034 xmlStopParser(vctxt->parserCtxt);
27035 return;
27036}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027037
Daniel Veillard4255d502002-04-16 15:50:10 +000027038/************************************************************************
27039 * *
27040 * Validation interfaces *
27041 * *
27042 ************************************************************************/
27043
27044/**
27045 * xmlSchemaNewValidCtxt:
27046 * @schema: a precompiled XML Schemas
27047 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027048 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000027049 *
27050 * Returns the validation context or NULL in case of error
27051 */
27052xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027053xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27054{
Daniel Veillard4255d502002-04-16 15:50:10 +000027055 xmlSchemaValidCtxtPtr ret;
27056
27057 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27058 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027059 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000027060 return (NULL);
27061 }
27062 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027063 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027064 ret->dict = xmlDictCreate();
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000027065 ret->nodeQNames = xmlSchemaItemListCreate();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027066 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000027067 return (ret);
27068}
27069
27070/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027071 * xmlSchemaClearValidCtxt:
27072 * @ctxt: the schema validation context
27073 *
27074 * Free the resources associated to the schema validation context;
27075 * leaves some fields alive intended for reuse of the context.
27076 */
27077static void
27078xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27079{
27080 if (vctxt == NULL)
27081 return;
27082
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027083 /*
27084 * TODO: Should we clear the flags?
27085 * Might be problematic if one reuses the context
27086 * and assumes that the options remain the same.
27087 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000027088 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027089 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027090 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000027091#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027092 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000027093#endif
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027094 vctxt->hasKeyrefs = 0;
27095
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027096 if (vctxt->value != NULL) {
27097 xmlSchemaFreeValue(vctxt->value);
27098 vctxt->value = NULL;
27099 }
27100 /*
27101 * Augmented IDC information.
27102 */
27103 if (vctxt->aidcs != NULL) {
27104 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27105 do {
27106 next = cur->next;
27107 xmlFree(cur);
27108 cur = next;
27109 } while (cur != NULL);
27110 vctxt->aidcs = NULL;
27111 }
27112 if (vctxt->idcNodes != NULL) {
27113 int i;
27114 xmlSchemaPSVIIDCNodePtr item;
27115
27116 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027117 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027118 xmlFree(item->keys);
27119 xmlFree(item);
27120 }
27121 xmlFree(vctxt->idcNodes);
27122 vctxt->idcNodes = NULL;
27123 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027124 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027125 * Note that we won't delete the XPath state pool here.
27126 */
27127 if (vctxt->xpathStates != NULL) {
27128 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27129 vctxt->xpathStates = NULL;
27130 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027131 /*
27132 * Attribute info.
27133 */
27134 if (vctxt->nbAttrInfos != 0) {
27135 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027136 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027137 /*
27138 * Element info.
27139 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027140 if (vctxt->elemInfos != NULL) {
27141 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027142 xmlSchemaNodeInfoPtr ei;
27143
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027144 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027145 ei = vctxt->elemInfos[i];
27146 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027147 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027148 xmlSchemaClearElemInfo(ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027149 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027150 }
27151 xmlSchemaItemListClear(vctxt->nodeQNames);
27152 /* Recreate the dict. */
27153 xmlDictFree(vctxt->dict);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027154 /*
27155 * TODO: Is is save to recreate it? Do we have a scenario
27156 * where the user provides the dict?
27157 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027158 vctxt->dict = xmlDictCreate();
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027159}
27160
27161/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027162 * xmlSchemaFreeValidCtxt:
27163 * @ctxt: the schema validation context
27164 *
27165 * Free the resources associated to the schema validation context
27166 */
27167void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027168xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27169{
Daniel Veillard4255d502002-04-16 15:50:10 +000027170 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027171 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000027172 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027173 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027174 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027175 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027176 if (ctxt->idcNodes != NULL) {
27177 int i;
27178 xmlSchemaPSVIIDCNodePtr item;
27179
27180 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027181 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027182 xmlFree(item->keys);
27183 xmlFree(item);
27184 }
27185 xmlFree(ctxt->idcNodes);
27186 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027187 if (ctxt->idcKeys != NULL) {
27188 int i;
27189 for (i = 0; i < ctxt->nbIdcKeys; i++)
27190 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27191 xmlFree(ctxt->idcKeys);
27192 }
27193
27194 if (ctxt->xpathStates != NULL)
27195 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27196 if (ctxt->xpathStatePool != NULL)
27197 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27198
27199 /*
27200 * Augmented IDC information.
27201 */
27202 if (ctxt->aidcs != NULL) {
27203 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27204 do {
27205 next = cur->next;
27206 xmlFree(cur);
27207 cur = next;
27208 } while (cur != NULL);
27209 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027210 if (ctxt->attrInfos != NULL) {
27211 int i;
27212 xmlSchemaAttrInfoPtr attr;
27213
27214 /* Just a paranoid call to the cleanup. */
27215 if (ctxt->nbAttrInfos != 0)
27216 xmlSchemaClearAttrInfos(ctxt);
27217 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27218 attr = ctxt->attrInfos[i];
27219 xmlFree(attr);
27220 }
27221 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000027222 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027223 if (ctxt->elemInfos != NULL) {
27224 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027225 xmlSchemaNodeInfoPtr ei;
27226
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027227 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027228 ei = ctxt->elemInfos[i];
27229 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027230 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027231 xmlSchemaClearElemInfo(ei);
27232 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027233 }
27234 xmlFree(ctxt->elemInfos);
27235 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027236 if (ctxt->nodeQNames != NULL)
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000027237 xmlSchemaItemListFree(ctxt->nodeQNames);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027238 if (ctxt->dict != NULL)
27239 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000027240 xmlFree(ctxt);
27241}
27242
27243/**
Daniel Veillardf10ae122005-07-10 19:03:16 +000027244 * xmlSchemaIsValid:
27245 * @ctxt: the schema validation context
27246 *
27247 * Check if any error was detected during validation.
27248 *
27249 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27250 * of internal error.
27251 */
27252int
27253xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27254{
27255 if (ctxt == NULL)
27256 return(-1);
27257 return(ctxt->err == 0);
27258}
27259
27260/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027261 * xmlSchemaSetValidErrors:
27262 * @ctxt: a schema validation context
27263 * @err: the error function
27264 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000027265 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000027266 *
William M. Brack2f2a6632004-08-20 23:09:47 +000027267 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000027268 */
27269void
27270xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027271 xmlSchemaValidityErrorFunc err,
27272 xmlSchemaValidityWarningFunc warn, void *ctx)
27273{
Daniel Veillard4255d502002-04-16 15:50:10 +000027274 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027275 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000027276 ctxt->error = err;
27277 ctxt->warning = warn;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027278 ctxt->errCtxt = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027279 if (ctxt->pctxt != NULL)
27280 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000027281}
27282
27283/**
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027284 * xmlSchemaSetValidStructuredErrors:
27285 * @ctxt: a schema validation context
27286 * @serror: the structured error function
27287 * @ctx: the functions context
27288 *
27289 * Set the structured error callback
27290 */
27291void
27292xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027293 xmlStructuredErrorFunc serror, void *ctx)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027294{
27295 if (ctxt == NULL)
27296 return;
27297 ctxt->serror = serror;
27298 ctxt->error = NULL;
27299 ctxt->warning = NULL;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027300 ctxt->errCtxt = ctx;
27301 if (ctxt->pctxt != NULL)
27302 xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027303}
27304
27305/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000027306 * xmlSchemaGetValidErrors:
27307 * @ctxt: a XML-Schema validation context
27308 * @err: the error function result
27309 * @warn: the warning function result
27310 * @ctx: the functions context result
27311 *
27312 * Get the error and warning callback informations
27313 *
27314 * Returns -1 in case of error and 0 otherwise
27315 */
27316int
27317xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027318 xmlSchemaValidityErrorFunc * err,
27319 xmlSchemaValidityWarningFunc * warn, void **ctx)
Daniel Veillard259f0df2004-08-18 09:13:18 +000027320{
27321 if (ctxt == NULL)
27322 return (-1);
27323 if (err != NULL)
27324 *err = ctxt->error;
27325 if (warn != NULL)
27326 *warn = ctxt->warning;
27327 if (ctx != NULL)
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027328 *ctx = ctxt->errCtxt;
Daniel Veillard259f0df2004-08-18 09:13:18 +000027329 return (0);
27330}
27331
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027332
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027333/**
Daniel Veillard6927b102004-10-27 17:29:04 +000027334 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027335 * @ctxt: a schema validation context
27336 * @options: a combination of xmlSchemaValidOption
27337 *
27338 * Sets the options to be used during the validation.
27339 *
27340 * Returns 0 in case of success, -1 in case of an
27341 * API error.
27342 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027343int
27344xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27345 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027346
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027347{
27348 int i;
27349
27350 if (ctxt == NULL)
27351 return (-1);
27352 /*
27353 * WARNING: Change the start value if adding to the
27354 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027355 * TODO: Is there an other, more easy to maintain,
27356 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027357 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027358 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027359 if (options & 1<<i)
27360 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027361 }
27362 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027363 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027364}
27365
27366/**
Daniel Veillard6927b102004-10-27 17:29:04 +000027367 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027368 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027369 *
William M. Brack21e4ef22005-01-02 09:53:13 +000027370 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027371 *
William M. Brack21e4ef22005-01-02 09:53:13 +000027372 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027373 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027374int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027375xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027376
27377{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027378 if (ctxt == NULL)
27379 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027380 else
27381 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027382}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027383
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027384static int
27385xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27386{
27387 xmlAttrPtr attr;
27388 int ret = 0;
27389 xmlSchemaNodeInfoPtr ielem = NULL;
27390 xmlNodePtr node, valRoot;
27391 const xmlChar *nsName;
27392
27393 /* DOC VAL TODO: Move this to the start function. */
27394 valRoot = xmlDocGetRootElement(vctxt->doc);
27395 if (valRoot == NULL) {
27396 /* VAL TODO: Error code? */
27397 VERROR(1, NULL, "The document has no document element");
27398 return (1);
27399 }
27400 vctxt->depth = -1;
27401 vctxt->validationRoot = valRoot;
27402 node = valRoot;
27403 while (node != NULL) {
27404 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27405 goto next_sibling;
27406 if (node->type == XML_ELEMENT_NODE) {
27407
27408 /*
27409 * Init the node-info.
27410 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000027411 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027412 if (xmlSchemaValidatorPushElem(vctxt) == -1)
27413 goto internal_error;
27414 ielem = vctxt->inode;
27415 ielem->node = node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027416 ielem->nodeLine = node->line;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027417 ielem->localName = node->name;
27418 if (node->ns != NULL)
27419 ielem->nsName = node->ns->href;
27420 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27421 /*
27422 * Register attributes.
27423 * DOC VAL TODO: We do not register namespace declaration
27424 * attributes yet.
27425 */
27426 vctxt->nbAttrInfos = 0;
27427 if (node->properties != NULL) {
27428 attr = node->properties;
27429 do {
27430 if (attr->ns != NULL)
27431 nsName = attr->ns->href;
27432 else
27433 nsName = NULL;
27434 ret = xmlSchemaValidatorPushAttribute(vctxt,
27435 (xmlNodePtr) attr,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027436 /*
27437 * Note that we give it the line number of the
27438 * parent element.
27439 */
27440 ielem->nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027441 attr->name, nsName, 0,
27442 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27443 if (ret == -1) {
27444 VERROR_INT("xmlSchemaDocWalk",
27445 "calling xmlSchemaValidatorPushAttribute()");
27446 goto internal_error;
27447 }
27448 attr = attr->next;
27449 } while (attr);
27450 }
27451 /*
27452 * Validate the element.
27453 */
27454 ret = xmlSchemaValidateElem(vctxt);
27455 if (ret != 0) {
27456 if (ret == -1) {
27457 VERROR_INT("xmlSchemaDocWalk",
27458 "calling xmlSchemaValidateElem()");
27459 goto internal_error;
27460 }
27461 /*
27462 * Don't stop validation; just skip the content
27463 * of this element.
27464 */
27465 goto leave_node;
27466 }
27467 if ((vctxt->skipDepth != -1) &&
27468 (vctxt->depth >= vctxt->skipDepth))
27469 goto leave_node;
27470 } else if ((node->type == XML_TEXT_NODE) ||
27471 (node->type == XML_CDATA_SECTION_NODE)) {
27472 /*
27473 * Process character content.
27474 */
Daniel Veillard14b56432006-03-09 18:41:40 +000027475 if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027476 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27477 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27478 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27479 if (ret < 0) {
27480 VERROR_INT("xmlSchemaVDocWalk",
27481 "calling xmlSchemaVPushText()");
27482 goto internal_error;
27483 }
27484 /*
27485 * DOC VAL TODO: Should we skip further validation of the
27486 * element content here?
27487 */
27488 } else if ((node->type == XML_ENTITY_NODE) ||
27489 (node->type == XML_ENTITY_REF_NODE)) {
27490 /*
27491 * DOC VAL TODO: What to do with entities?
27492 */
27493 TODO
27494 } else {
27495 goto leave_node;
27496 /*
27497 * DOC VAL TODO: XInclude nodes, etc.
27498 */
27499 }
27500 /*
27501 * Walk the doc.
27502 */
27503 if (node->children != NULL) {
27504 node = node->children;
27505 continue;
27506 }
27507leave_node:
27508 if (node->type == XML_ELEMENT_NODE) {
27509 /*
27510 * Leaving the scope of an element.
27511 */
27512 if (node != vctxt->inode->node) {
27513 VERROR_INT("xmlSchemaVDocWalk",
27514 "element position mismatch");
27515 goto internal_error;
27516 }
27517 ret = xmlSchemaValidatorPopElem(vctxt);
27518 if (ret != 0) {
27519 if (ret < 0) {
27520 VERROR_INT("xmlSchemaVDocWalk",
27521 "calling xmlSchemaValidatorPopElem()");
27522 goto internal_error;
27523 }
27524 }
27525 if (node == valRoot)
27526 goto exit;
27527 }
27528next_sibling:
27529 if (node->next != NULL)
27530 node = node->next;
27531 else {
27532 node = node->parent;
27533 goto leave_node;
27534 }
27535 }
27536
27537exit:
27538 return (ret);
27539internal_error:
27540 return (-1);
27541}
27542
27543static int
Daniel Veillardf10ae122005-07-10 19:03:16 +000027544xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027545 /*
27546 * Some initialization.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027547 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027548 vctxt->err = 0;
27549 vctxt->nberrors = 0;
27550 vctxt->depth = -1;
27551 vctxt->skipDepth = -1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027552 vctxt->xsiAssemble = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027553 vctxt->hasKeyrefs = 0;
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000027554#ifdef ENABLE_IDC_NODE_TABLES_TEST
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027555 vctxt->createIDCNodeTables = 1;
27556#else
27557 vctxt->createIDCNodeTables = 0;
27558#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027559 /*
27560 * Create a schema + parser if necessary.
27561 */
27562 if (vctxt->schema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027563 xmlSchemaParserCtxtPtr pctxt;
27564
27565 vctxt->xsiAssemble = 1;
27566 /*
27567 * If not schema was given then we will create a schema
27568 * dynamically using XSI schema locations.
27569 *
27570 * Create the schema parser context.
27571 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027572 if ((vctxt->pctxt == NULL) &&
27573 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
27574 return (-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027575 pctxt = vctxt->pctxt;
27576 pctxt->xsiAssemble = 1;
27577 /*
27578 * Create the schema.
27579 */
27580 vctxt->schema = xmlSchemaNewSchema(pctxt);
27581 if (vctxt->schema == NULL)
27582 return (-1);
27583 /*
27584 * Create the schema construction context.
27585 */
27586 pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
27587 if (pctxt->constructor == NULL)
27588 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000027589 pctxt->constructor->mainSchema = vctxt->schema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027590 /*
27591 * Take ownership of the constructor to be able to free it.
27592 */
27593 pctxt->ownsConstructor = 1;
27594 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027595 /*
27596 * Augment the IDC definitions.
27597 */
27598 if (vctxt->schema->idcDef != NULL) {
27599 xmlHashScan(vctxt->schema->idcDef,
27600 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
27601 }
Daniel Veillardf10ae122005-07-10 19:03:16 +000027602 return(0);
27603}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027604
Daniel Veillardf10ae122005-07-10 19:03:16 +000027605static void
27606xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027607 if (vctxt->xsiAssemble) {
27608 if (vctxt->schema != NULL) {
27609 xmlSchemaFree(vctxt->schema);
27610 vctxt->schema = NULL;
27611 }
27612 }
27613 xmlSchemaClearValidCtxt(vctxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +000027614}
27615
27616static int
27617xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
27618{
27619 int ret = 0;
27620
27621 if (xmlSchemaPreRun(vctxt) < 0)
27622 return(-1);
27623
27624 if (vctxt->doc != NULL) {
27625 /*
27626 * Tree validation.
27627 */
27628 ret = xmlSchemaVDocWalk(vctxt);
27629#ifdef LIBXML_READER_ENABLED
27630 } else if (vctxt->reader != NULL) {
27631 /*
27632 * XML Reader validation.
27633 */
27634#ifdef XML_SCHEMA_READER_ENABLED
27635 ret = xmlSchemaVReaderWalk(vctxt);
27636#endif
27637#endif
27638 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
27639 /*
27640 * SAX validation.
27641 */
27642 ret = xmlParseDocument(vctxt->parserCtxt);
27643 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027644 VERROR_INT("xmlSchemaVStart",
Daniel Veillardf10ae122005-07-10 19:03:16 +000027645 "no instance to validate");
27646 ret = -1;
27647 }
27648
27649 xmlSchemaPostRun(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027650 if (ret == 0)
27651 ret = vctxt->err;
27652 return (ret);
27653}
27654
27655/**
27656 * xmlSchemaValidateOneElement:
27657 * @ctxt: a schema validation context
27658 * @elem: an element node
27659 *
27660 * Validate a branch of a tree, starting with the given @elem.
27661 *
27662 * Returns 0 if the element and its subtree is valid, a positive error
27663 * code number otherwise and -1 in case of an internal or API error.
27664 */
27665int
27666xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
27667{
27668 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
27669 return (-1);
27670
27671 if (ctxt->schema == NULL)
27672 return (-1);
27673
27674 ctxt->doc = elem->doc;
27675 ctxt->node = elem;
27676 ctxt->validationRoot = elem;
27677 return(xmlSchemaVStart(ctxt));
27678}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027679
Daniel Veillard259f0df2004-08-18 09:13:18 +000027680/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027681 * xmlSchemaValidateDoc:
27682 * @ctxt: a schema validation context
27683 * @doc: a parsed document tree
27684 *
27685 * Validate a document tree in memory.
27686 *
27687 * Returns 0 if the document is schemas valid, a positive error code
27688 * number otherwise and -1 in case of internal or API error.
27689 */
27690int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027691xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
27692{
Daniel Veillard4255d502002-04-16 15:50:10 +000027693 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027694 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000027695
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027696 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027697 ctxt->node = xmlDocGetRootElement(doc);
27698 if (ctxt->node == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027699 xmlSchemaCustomErr(ACTXT_CAST ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027700 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
27701 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027702 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027703 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027704 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027705 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027706 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000027707}
27708
Daniel Veillardcdc82732005-07-08 15:04:06 +000027709
27710/************************************************************************
27711 * *
27712 * Function and data for SAX streaming API *
27713 * *
27714 ************************************************************************/
27715typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
27716typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
27717
27718struct _xmlSchemaSplitSAXData {
27719 xmlSAXHandlerPtr user_sax;
27720 void *user_data;
27721 xmlSchemaValidCtxtPtr ctxt;
27722 xmlSAXHandlerPtr schemas_sax;
27723};
27724
Daniel Veillard971771e2005-07-09 17:32:57 +000027725#define XML_SAX_PLUG_MAGIC 0xdc43ba21
27726
27727struct _xmlSchemaSAXPlug {
27728 unsigned int magic;
27729
27730 /* the original callbacks informations */
27731 xmlSAXHandlerPtr *user_sax_ptr;
27732 xmlSAXHandlerPtr user_sax;
27733 void **user_data_ptr;
27734 void *user_data;
27735
27736 /* the block plugged back and validation informations */
27737 xmlSAXHandler schemas_sax;
27738 xmlSchemaValidCtxtPtr ctxt;
27739};
27740
Daniel Veillardcdc82732005-07-08 15:04:06 +000027741/* All those functions just bounces to the user provided SAX handlers */
27742static void
27743internalSubsetSplit(void *ctx, const xmlChar *name,
27744 const xmlChar *ExternalID, const xmlChar *SystemID)
27745{
Daniel Veillard971771e2005-07-09 17:32:57 +000027746 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027747 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27748 (ctxt->user_sax->internalSubset != NULL))
27749 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
27750 SystemID);
27751}
27752
27753static int
27754isStandaloneSplit(void *ctx)
27755{
Daniel Veillard971771e2005-07-09 17:32:57 +000027756 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027757 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27758 (ctxt->user_sax->isStandalone != NULL))
27759 return(ctxt->user_sax->isStandalone(ctxt->user_data));
27760 return(0);
27761}
27762
27763static int
27764hasInternalSubsetSplit(void *ctx)
27765{
Daniel Veillard971771e2005-07-09 17:32:57 +000027766 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027767 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27768 (ctxt->user_sax->hasInternalSubset != NULL))
27769 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
27770 return(0);
27771}
27772
27773static int
27774hasExternalSubsetSplit(void *ctx)
27775{
Daniel Veillard971771e2005-07-09 17:32:57 +000027776 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027777 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27778 (ctxt->user_sax->hasExternalSubset != NULL))
27779 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
27780 return(0);
27781}
27782
27783static void
27784externalSubsetSplit(void *ctx, const xmlChar *name,
27785 const xmlChar *ExternalID, const xmlChar *SystemID)
27786{
Daniel Veillard971771e2005-07-09 17:32:57 +000027787 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027788 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27789 (ctxt->user_sax->internalSubset != NULL))
27790 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
27791 SystemID);
27792}
27793
27794static xmlParserInputPtr
27795resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
27796{
Daniel Veillard971771e2005-07-09 17:32:57 +000027797 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027798 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27799 (ctxt->user_sax->resolveEntity != NULL))
27800 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
27801 systemId));
27802 return(NULL);
27803}
27804
27805static xmlEntityPtr
27806getEntitySplit(void *ctx, const xmlChar *name)
27807{
Daniel Veillard971771e2005-07-09 17:32:57 +000027808 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027809 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27810 (ctxt->user_sax->getEntity != NULL))
27811 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
27812 return(NULL);
27813}
27814
27815static xmlEntityPtr
27816getParameterEntitySplit(void *ctx, const xmlChar *name)
27817{
Daniel Veillard971771e2005-07-09 17:32:57 +000027818 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027819 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27820 (ctxt->user_sax->getParameterEntity != NULL))
27821 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
27822 return(NULL);
27823}
27824
27825
27826static void
27827entityDeclSplit(void *ctx, const xmlChar *name, int type,
27828 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
27829{
Daniel Veillard971771e2005-07-09 17:32:57 +000027830 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027831 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27832 (ctxt->user_sax->entityDecl != NULL))
27833 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
27834 systemId, content);
27835}
27836
27837static void
27838attributeDeclSplit(void *ctx, const xmlChar * elem,
27839 const xmlChar * name, int type, int def,
27840 const xmlChar * defaultValue, xmlEnumerationPtr tree)
27841{
Daniel Veillard971771e2005-07-09 17:32:57 +000027842 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027843 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27844 (ctxt->user_sax->attributeDecl != NULL)) {
27845 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
27846 def, defaultValue, tree);
27847 } else {
27848 xmlFreeEnumeration(tree);
27849 }
27850}
27851
27852static void
27853elementDeclSplit(void *ctx, const xmlChar *name, int type,
27854 xmlElementContentPtr content)
27855{
Daniel Veillard971771e2005-07-09 17:32:57 +000027856 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027857 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27858 (ctxt->user_sax->elementDecl != NULL))
27859 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
27860}
27861
27862static void
27863notationDeclSplit(void *ctx, const xmlChar *name,
27864 const xmlChar *publicId, const xmlChar *systemId)
27865{
Daniel Veillard971771e2005-07-09 17:32:57 +000027866 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027867 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27868 (ctxt->user_sax->notationDecl != NULL))
27869 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
27870 systemId);
27871}
27872
27873static void
27874unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
27875 const xmlChar *publicId, const xmlChar *systemId,
27876 const xmlChar *notationName)
27877{
Daniel Veillard971771e2005-07-09 17:32:57 +000027878 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027879 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27880 (ctxt->user_sax->unparsedEntityDecl != NULL))
27881 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
27882 systemId, notationName);
27883}
27884
27885static void
27886setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
27887{
Daniel Veillard971771e2005-07-09 17:32:57 +000027888 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027889 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27890 (ctxt->user_sax->setDocumentLocator != NULL))
27891 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
27892}
27893
27894static void
27895startDocumentSplit(void *ctx)
27896{
Daniel Veillard971771e2005-07-09 17:32:57 +000027897 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027898 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27899 (ctxt->user_sax->startDocument != NULL))
27900 ctxt->user_sax->startDocument(ctxt->user_data);
27901}
27902
27903static void
27904endDocumentSplit(void *ctx)
27905{
Daniel Veillard971771e2005-07-09 17:32:57 +000027906 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027907 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27908 (ctxt->user_sax->endDocument != NULL))
27909 ctxt->user_sax->endDocument(ctxt->user_data);
27910}
27911
27912static void
27913processingInstructionSplit(void *ctx, const xmlChar *target,
27914 const xmlChar *data)
27915{
Daniel Veillard971771e2005-07-09 17:32:57 +000027916 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027917 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27918 (ctxt->user_sax->processingInstruction != NULL))
27919 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
27920}
27921
27922static void
27923commentSplit(void *ctx, const xmlChar *value)
27924{
Daniel Veillard971771e2005-07-09 17:32:57 +000027925 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027926 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27927 (ctxt->user_sax->comment != NULL))
27928 ctxt->user_sax->comment(ctxt->user_data, value);
27929}
27930
27931/*
27932 * Varargs error callbacks to the user application, harder ...
27933 */
27934
Daniel Veillardffa3c742005-07-21 13:24:09 +000027935static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027936warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027937 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027938 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27939 (ctxt->user_sax->warning != NULL)) {
27940 TODO
27941 }
27942}
Daniel Veillardffa3c742005-07-21 13:24:09 +000027943static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027944errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027945 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027946 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27947 (ctxt->user_sax->error != NULL)) {
27948 TODO
27949 }
27950}
Daniel Veillardffa3c742005-07-21 13:24:09 +000027951static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027952fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027953 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027954 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27955 (ctxt->user_sax->fatalError != NULL)) {
27956 TODO
27957 }
27958}
27959
27960/*
27961 * Those are function where both the user handler and the schemas handler
27962 * need to be called.
27963 */
27964static void
27965charactersSplit(void *ctx, const xmlChar *ch, int len)
27966{
Daniel Veillard971771e2005-07-09 17:32:57 +000027967 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027968 if (ctxt == NULL)
27969 return;
27970 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
27971 ctxt->user_sax->characters(ctxt->user_data, ch, len);
27972 if (ctxt->ctxt != NULL)
27973 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
27974}
27975
27976static void
27977ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
27978{
Daniel Veillard971771e2005-07-09 17:32:57 +000027979 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027980 if (ctxt == NULL)
27981 return;
27982 if ((ctxt->user_sax != NULL) &&
27983 (ctxt->user_sax->ignorableWhitespace != NULL))
27984 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
27985 if (ctxt->ctxt != NULL)
27986 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
27987}
27988
27989static void
27990cdataBlockSplit(void *ctx, const xmlChar *value, int len)
27991{
Daniel Veillard971771e2005-07-09 17:32:57 +000027992 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027993 if (ctxt == NULL)
27994 return;
27995 if ((ctxt->user_sax != NULL) &&
27996 (ctxt->user_sax->ignorableWhitespace != NULL))
27997 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, value, len);
27998 if (ctxt->ctxt != NULL)
27999 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28000}
28001
28002static void
28003referenceSplit(void *ctx, const xmlChar *name)
28004{
Daniel Veillard971771e2005-07-09 17:32:57 +000028005 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillard14b56432006-03-09 18:41:40 +000028006 if (ctxt == NULL)
28007 return;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028008 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28009 (ctxt->user_sax->reference != NULL))
28010 ctxt->user_sax->reference(ctxt->user_data, name);
28011 if (ctxt->ctxt != NULL)
28012 xmlSchemaSAXHandleReference(ctxt->user_data, name);
28013}
28014
28015static void
28016startElementNsSplit(void *ctx, const xmlChar * localname,
28017 const xmlChar * prefix, const xmlChar * URI,
28018 int nb_namespaces, const xmlChar ** namespaces,
28019 int nb_attributes, int nb_defaulted,
28020 const xmlChar ** attributes) {
Daniel Veillard971771e2005-07-09 17:32:57 +000028021 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028022 if (ctxt == NULL)
28023 return;
28024 if ((ctxt->user_sax != NULL) &&
28025 (ctxt->user_sax->startElementNs != NULL))
28026 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28027 URI, nb_namespaces, namespaces,
28028 nb_attributes, nb_defaulted,
28029 attributes);
28030 if (ctxt->ctxt != NULL)
28031 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28032 URI, nb_namespaces, namespaces,
28033 nb_attributes, nb_defaulted,
28034 attributes);
28035}
28036
28037static void
28038endElementNsSplit(void *ctx, const xmlChar * localname,
28039 const xmlChar * prefix, const xmlChar * URI) {
Daniel Veillard971771e2005-07-09 17:32:57 +000028040 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028041 if (ctxt == NULL)
28042 return;
28043 if ((ctxt->user_sax != NULL) &&
28044 (ctxt->user_sax->endElementNs != NULL))
28045 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28046 if (ctxt->ctxt != NULL)
28047 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28048}
28049
Daniel Veillard4255d502002-04-16 15:50:10 +000028050/**
Daniel Veillard971771e2005-07-09 17:32:57 +000028051 * xmlSchemaSAXPlug:
28052 * @ctxt: a schema validation context
Daniel Veillard1f33c4d2005-07-10 21:38:31 +000028053 * @sax: a pointer to the original xmlSAXHandlerPtr
28054 * @user_data: a pointer to the original SAX user data pointer
Daniel Veillard971771e2005-07-09 17:32:57 +000028055 *
28056 * Plug a SAX based validation layer in a SAX parsing event flow.
28057 * The original @saxptr and @dataptr data are replaced by new pointers
28058 * but the calls to the original will be maintained.
28059 *
28060 * Returns a pointer to a data structure needed to unplug the validation layer
28061 * or NULL in case of errors.
28062 */
28063xmlSchemaSAXPlugPtr
28064xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28065 xmlSAXHandlerPtr *sax, void **user_data)
28066{
28067 xmlSchemaSAXPlugPtr ret;
28068 xmlSAXHandlerPtr old_sax;
28069
28070 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28071 return(NULL);
28072
28073 /*
28074 * We only allow to plug into SAX2 event streams
28075 */
28076 old_sax = *sax;
28077 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28078 return(NULL);
28079 if ((old_sax != NULL) &&
28080 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28081 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28082 return(NULL);
28083
28084 /*
28085 * everything seems right allocate the local data needed for that layer
28086 */
28087 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28088 if (ret == NULL) {
28089 return(NULL);
28090 }
28091 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28092 ret->magic = XML_SAX_PLUG_MAGIC;
28093 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28094 ret->ctxt = ctxt;
28095 ret->user_sax_ptr = sax;
28096 ret->user_sax = old_sax;
28097 if (old_sax == NULL) {
28098 /*
28099 * go direct, no need for the split block and functions.
28100 */
28101 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28102 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28103 /*
28104 * Note that we use the same text-function for both, to prevent
28105 * the parser from testing for ignorable whitespace.
28106 */
28107 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28108 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28109
28110 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28111 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28112
28113 ret->user_data = ctxt;
28114 *user_data = ctxt;
28115 } else {
28116 /*
28117 * for each callback unused by Schemas initialize it to the Split
28118 * routine only if non NULL in the user block, this can speed up
28119 * things at the SAX level.
28120 */
28121 if (old_sax->internalSubset != NULL)
28122 ret->schemas_sax.internalSubset = internalSubsetSplit;
28123 if (old_sax->isStandalone != NULL)
28124 ret->schemas_sax.isStandalone = isStandaloneSplit;
28125 if (old_sax->hasInternalSubset != NULL)
28126 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28127 if (old_sax->hasExternalSubset != NULL)
28128 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28129 if (old_sax->resolveEntity != NULL)
28130 ret->schemas_sax.resolveEntity = resolveEntitySplit;
28131 if (old_sax->getEntity != NULL)
28132 ret->schemas_sax.getEntity = getEntitySplit;
28133 if (old_sax->entityDecl != NULL)
28134 ret->schemas_sax.entityDecl = entityDeclSplit;
28135 if (old_sax->notationDecl != NULL)
28136 ret->schemas_sax.notationDecl = notationDeclSplit;
28137 if (old_sax->attributeDecl != NULL)
28138 ret->schemas_sax.attributeDecl = attributeDeclSplit;
28139 if (old_sax->elementDecl != NULL)
28140 ret->schemas_sax.elementDecl = elementDeclSplit;
28141 if (old_sax->unparsedEntityDecl != NULL)
28142 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28143 if (old_sax->setDocumentLocator != NULL)
28144 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28145 if (old_sax->startDocument != NULL)
28146 ret->schemas_sax.startDocument = startDocumentSplit;
28147 if (old_sax->endDocument != NULL)
28148 ret->schemas_sax.endDocument = endDocumentSplit;
28149 if (old_sax->processingInstruction != NULL)
28150 ret->schemas_sax.processingInstruction = processingInstructionSplit;
28151 if (old_sax->comment != NULL)
28152 ret->schemas_sax.comment = commentSplit;
28153 if (old_sax->warning != NULL)
28154 ret->schemas_sax.warning = warningSplit;
28155 if (old_sax->error != NULL)
28156 ret->schemas_sax.error = errorSplit;
28157 if (old_sax->fatalError != NULL)
28158 ret->schemas_sax.fatalError = fatalErrorSplit;
28159 if (old_sax->getParameterEntity != NULL)
28160 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28161 if (old_sax->externalSubset != NULL)
28162 ret->schemas_sax.externalSubset = externalSubsetSplit;
28163
28164 /*
28165 * the 6 schemas callback have to go to the splitter functions
28166 * Note that we use the same text-function for ignorableWhitespace
28167 * if possible, to prevent the parser from testing for ignorable
28168 * whitespace.
28169 */
28170 ret->schemas_sax.characters = charactersSplit;
28171 if ((old_sax->ignorableWhitespace != NULL) &&
28172 (old_sax->ignorableWhitespace != old_sax->characters))
28173 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28174 else
28175 ret->schemas_sax.ignorableWhitespace = charactersSplit;
28176 ret->schemas_sax.cdataBlock = cdataBlockSplit;
28177 ret->schemas_sax.reference = referenceSplit;
28178 ret->schemas_sax.startElementNs = startElementNsSplit;
28179 ret->schemas_sax.endElementNs = endElementNsSplit;
28180
28181 ret->user_data_ptr = user_data;
28182 ret->user_data = *user_data;
28183 *user_data = ret;
28184 }
28185
28186 /*
28187 * plug the pointers back.
28188 */
28189 *sax = &(ret->schemas_sax);
Daniel Veillardf10ae122005-07-10 19:03:16 +000028190 ctxt->sax = *sax;
28191 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28192 xmlSchemaPreRun(ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000028193 return(ret);
28194}
28195
28196/**
28197 * xmlSchemaSAXUnplug:
28198 * @plug: a data structure returned by xmlSchemaSAXPlug
28199 *
28200 * Unplug a SAX based validation layer in a SAX parsing event flow.
28201 * The original pointers used in the call are restored.
28202 *
28203 * Returns 0 in case of success and -1 in case of failure.
28204 */
28205int
28206xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28207{
28208 xmlSAXHandlerPtr *sax;
28209 void **user_data;
28210
28211 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28212 return(-1);
28213 plug->magic = 0;
28214
Daniel Veillardf10ae122005-07-10 19:03:16 +000028215 xmlSchemaPostRun(plug->ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000028216 /* restore the data */
28217 sax = plug->user_sax_ptr;
28218 *sax = plug->user_sax;
28219 if (plug->user_sax != NULL) {
28220 user_data = plug->user_data_ptr;
28221 *user_data = plug->user_data;
28222 }
28223
28224 /* free and return */
28225 xmlFree(plug);
28226 return(0);
28227}
28228
28229/**
Daniel Veillard4255d502002-04-16 15:50:10 +000028230 * xmlSchemaValidateStream:
28231 * @ctxt: a schema validation context
28232 * @input: the input to use for reading the data
28233 * @enc: an optional encoding information
28234 * @sax: a SAX handler for the resulting events
28235 * @user_data: the context to provide to the SAX handler.
28236 *
Daniel Veillardcdc82732005-07-08 15:04:06 +000028237 * Validate an input based on a flow of SAX event from the parser
28238 * and forward the events to the @sax handler with the provided @user_data
28239 * the user provided @sax handler must be a SAX2 one.
Daniel Veillard4255d502002-04-16 15:50:10 +000028240 *
28241 * Returns 0 if the document is schemas valid, a positive error code
28242 * number otherwise and -1 in case of internal or API error.
28243 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028244int
Daniel Veillard4255d502002-04-16 15:50:10 +000028245xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028246 xmlParserInputBufferPtr input, xmlCharEncoding enc,
28247 xmlSAXHandlerPtr sax, void *user_data)
28248{
Daniel Veillard971771e2005-07-09 17:32:57 +000028249 xmlSchemaSAXPlugPtr plug = NULL;
28250 xmlSAXHandlerPtr old_sax = NULL;
28251 xmlParserCtxtPtr pctxt = NULL;
28252 xmlParserInputPtr inputStream = NULL;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028253 int ret;
28254
Daniel Veillard4255d502002-04-16 15:50:10 +000028255 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028256 return (-1);
Daniel Veillardcdc82732005-07-08 15:04:06 +000028257
Daniel Veillardcdc82732005-07-08 15:04:06 +000028258 /*
28259 * prepare the parser
28260 */
28261 pctxt = xmlNewParserCtxt();
28262 if (pctxt == NULL)
28263 return (-1);
28264 old_sax = pctxt->sax;
Daniel Veillard971771e2005-07-09 17:32:57 +000028265 pctxt->sax = sax;
28266 pctxt->userData = user_data;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028267#if 0
28268 if (options)
28269 xmlCtxtUseOptions(pctxt, options);
28270#endif
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000028271 pctxt->linenumbers = 1;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028272
Daniel Veillardf0af8ec2005-07-08 17:27:33 +000028273 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028274 if (inputStream == NULL) {
28275 ret = -1;
28276 goto done;
28277 }
28278 inputPush(pctxt, inputStream);
28279 ctxt->parserCtxt = pctxt;
28280 ctxt->input = input;
28281
28282 /*
Daniel Veillard971771e2005-07-09 17:32:57 +000028283 * Plug the validation and launch the parsing
Daniel Veillardcdc82732005-07-08 15:04:06 +000028284 */
Daniel Veillard971771e2005-07-09 17:32:57 +000028285 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28286 if (plug == NULL) {
28287 ret = -1;
28288 goto done;
28289 }
28290 ctxt->input = input;
28291 ctxt->enc = enc;
28292 ctxt->sax = pctxt->sax;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028293 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28294 ret = xmlSchemaVStart(ctxt);
28295
28296 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28297 ret = ctxt->parserCtxt->errNo;
28298 if (ret == 0)
28299 ret = 1;
28300 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028301
28302done:
Daniel Veillard971771e2005-07-09 17:32:57 +000028303 ctxt->parserCtxt = NULL;
28304 ctxt->sax = NULL;
28305 ctxt->input = NULL;
28306 if (plug != NULL) {
28307 xmlSchemaSAXUnplug(plug);
28308 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028309 /* cleanup */
Daniel Veillard971771e2005-07-09 17:32:57 +000028310 if (pctxt != NULL) {
28311 pctxt->sax = old_sax;
28312 xmlFreeParserCtxt(pctxt);
28313 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028314 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000028315}
28316
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028317/**
28318 * xmlSchemaValidateFile:
28319 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000028320 * @filename: the URI of the instance
28321 * @options: a future set of options, currently unused
28322 *
28323 * Do a schemas validation of the given resource, it will use the
28324 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028325 *
28326 * Returns 0 if the document is valid, a positive error code
28327 * number otherwise and -1 in case of an internal or API error.
28328 */
28329int
28330xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000028331 const char * filename,
28332 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028333{
28334 int ret;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028335 xmlParserInputBufferPtr input;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028336
28337 if ((ctxt == NULL) || (filename == NULL))
28338 return (-1);
28339
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028340 input = xmlParserInputBufferCreateFilename(filename,
28341 XML_CHAR_ENCODING_NONE);
28342 if (input == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028343 return (-1);
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028344 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28345 NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028346 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000028347}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028348
Daniel Veillard5d4644e2005-04-01 13:11:58 +000028349#define bottom_xmlschemas
28350#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000028351#endif /* LIBXML_SCHEMAS_ENABLED */